From 6b5019dcdbc47392364d6ee15dedad54a33980ba Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 18 Sep 2025 17:01:32 -0400 Subject: [PATCH 1/8] working update --- .env.example | 4 + .github/workflows/e2e.yml | 52 +- README.md | 3 +- ...{EasyPrivateVoting.ts => PrivateVoting.ts} | 44 +- .../private_voting-EasyPrivateVoting.json | 2983 -------------- .../private_voting-PrivateVoting.json | 3410 +++++++++++++++++ app/embedded-wallet.ts | 49 +- app/main.ts | 8 +- contracts/Nargo.toml | 6 +- contracts/src/main.nr | 20 +- package.json | 18 +- scripts/deploy.ts | 42 +- yarn.lock | 528 +-- 13 files changed, 3809 insertions(+), 3358 deletions(-) create mode 100644 .env.example rename app/artifacts/{EasyPrivateVoting.ts => PrivateVoting.ts} (68%) delete mode 100644 app/artifacts/private_voting-EasyPrivateVoting.json create mode 100644 app/artifacts/private_voting-PrivateVoting.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..a799b96 --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +CONTRACT_ADDRESS= +DEPLOYER_ADDRESS= +DEPLOYMENT_SALT= +AZTEC_NODE_URL=http://localhost:8080 \ No newline at end of file diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 293b294..c1ea76e 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -9,38 +9,38 @@ jobs: timeout-minutes: 120 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: lts/* + - uses: actions/setup-node@v4 + with: + node-version: lts/* - - name: Set up Docker - uses: docker/setup-buildx-action@v2 + - name: Set up Docker + uses: docker/setup-buildx-action@v2 - - name: Install Aztec CLI - run: | - curl -s https://install.aztec.network > tmp.sh - bash tmp.sh <<< yes "yes" + - name: Install Aztec CLI + run: | + curl -s https://install.aztec.network > tmp.sh + bash tmp.sh <<< yes "yes" - - name: Update path - run: echo "/home/runner/.aztec/bin" >> $GITHUB_PATH + - name: Update path + run: echo "/home/runner/.aztec/bin" >> $GITHUB_PATH - - name: Set Aztec version and start sandbox - run: | - aztec-up 0.87.4 - aztec start --sandbox & + - name: Set Aztec version and start sandbox + run: | + aztec-up 2.0.2 + aztec start --sandbox & - - name: Install dependencies - working-directory: ./app - run: npm install -g yarn && yarn + - name: Install dependencies + working-directory: ./app + run: npm install -g yarn && yarn - - name: Install Playwright Browsers - working-directory: ./app - run: yarn playwright install --with-deps + - name: Install Playwright Browsers + working-directory: ./app + run: yarn playwright install --with-deps - - name: Build - run: yarn build + - name: Build + run: yarn build - - name: Run tests - run: yarn test + - name: Run tests + run: yarn test diff --git a/README.md b/README.md index e371e07..1014781 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,10 @@ This is an example web app that demonstrates how to interact with an Aztec contr 1. Install the Aztec tools from the first few steps in [Quick Start Guide](https://docs.aztec.network/developers/getting_started). -Please note that this project uses `0.87.4` version of Aztec SDK. If you wish to use a different version, please update the dependencies in the `app/package.json` and in `contracts/Nargo.toml` file to match your version. +Please note that this project uses `2.0.2` version of Aztec SDK. If you wish to use a different version, please update the dependencies in the `app/package.json` and in `contracts/Nargo.toml` file to match your version. You can install a specific version of Aztec tools by running `aztec-up 0.X.X` - 2. Compile smart contracts in `/contracts`: ```sh diff --git a/app/artifacts/EasyPrivateVoting.ts b/app/artifacts/PrivateVoting.ts similarity index 68% rename from app/artifacts/EasyPrivateVoting.ts rename to app/artifacts/PrivateVoting.ts index ee66b3a..a184917 100644 --- a/app/artifacts/EasyPrivateVoting.ts +++ b/app/artifacts/PrivateVoting.ts @@ -14,7 +14,6 @@ import { type ContractInstanceWithAddress, type ContractMethod, type ContractStorageLayout, - type ContractNotes, decodeFromAbi, DeployMethod, EthAddress, @@ -26,7 +25,6 @@ import { loadContractArtifact, loadContractArtifactForPublic, type NoirCompiledContract, - NoteSelector, Point, type PublicKey, PublicKeys, @@ -34,21 +32,21 @@ import { type U128Like, type WrappedFieldLike, } from '@aztec/aztec.js'; -import EasyPrivateVotingContractArtifactJson from './private_voting-EasyPrivateVoting.json' with { type: 'json' }; -export const EasyPrivateVotingContractArtifact = loadContractArtifact(EasyPrivateVotingContractArtifactJson as NoirCompiledContract); +import PrivateVotingContractArtifactJson from './private_voting-PrivateVoting.json' with { type: 'json' }; +export const PrivateVotingContractArtifact = loadContractArtifact(PrivateVotingContractArtifactJson as NoirCompiledContract); /** - * Type-safe interface for contract EasyPrivateVoting; + * Type-safe interface for contract PrivateVoting; */ -export class EasyPrivateVotingContract extends ContractBase { +export class PrivateVotingContract extends ContractBase { private constructor( instance: ContractInstanceWithAddress, wallet: Wallet, ) { - super(instance, EasyPrivateVotingContractArtifact, wallet); + super(instance, PrivateVotingContractArtifact, wallet); } @@ -63,7 +61,7 @@ export class EasyPrivateVotingContract extends ContractBase { address: AztecAddress, wallet: Wallet, ) { - return Contract.at(address, EasyPrivateVotingContract.artifact, wallet) as Promise; + return Contract.at(address, PrivateVotingContract.artifact, wallet) as Promise; } @@ -71,28 +69,28 @@ export class EasyPrivateVotingContract extends ContractBase { * Creates a tx to deploy a new instance of this contract. */ public static deploy(wallet: Wallet, admin: AztecAddressLike) { - return new DeployMethod(PublicKeys.default(), wallet, EasyPrivateVotingContractArtifact, EasyPrivateVotingContract.at, Array.from(arguments).slice(1)); + return new DeployMethod(PublicKeys.default(), wallet, PrivateVotingContractArtifact, PrivateVotingContract.at, Array.from(arguments).slice(1)); } /** * Creates a tx to deploy a new instance of this contract using the specified public keys hash to derive the address. */ public static deployWithPublicKeys(publicKeys: PublicKeys, wallet: Wallet, admin: AztecAddressLike) { - return new DeployMethod(publicKeys, wallet, EasyPrivateVotingContractArtifact, EasyPrivateVotingContract.at, Array.from(arguments).slice(2)); + return new DeployMethod(publicKeys, wallet, PrivateVotingContractArtifact, PrivateVotingContract.at, Array.from(arguments).slice(2)); } /** * Creates a tx to deploy a new instance of this contract using the specified constructor method. */ - public static deployWithOpts( + public static deployWithOpts( opts: { publicKeys?: PublicKeys; method?: M; wallet: Wallet }, - ...args: Parameters + ...args: Parameters ) { - return new DeployMethod( + return new DeployMethod( opts.publicKeys ?? PublicKeys.default(), opts.wallet, - EasyPrivateVotingContractArtifact, - EasyPrivateVotingContract.at, + PrivateVotingContractArtifact, + PrivateVotingContract.at, Array.from(arguments).slice(1), opts.method ?? 'constructor', ); @@ -104,14 +102,14 @@ export class EasyPrivateVotingContract extends ContractBase { * Returns this contract's artifact. */ public static get artifact(): ContractArtifact { - return EasyPrivateVotingContractArtifact; + return PrivateVotingContractArtifact; } /** * Returns this contract's artifact with public bytecode. */ public static get artifactForPublic(): ContractArtifact { - return loadContractArtifactForPublic(EasyPrivateVotingContractArtifactJson as NoirCompiledContract); + return loadContractArtifactForPublic(PrivateVotingContractArtifactJson as NoirCompiledContract); } @@ -133,15 +131,6 @@ active_at_block: { } - public static get notes(): ContractNotes<'ValueNote'> { - return { - ValueNote: { - id: new NoteSelector(0), - } - } as ContractNotes<'ValueNote'>; - } - - /** Type-safe wrappers for the public methods exposed by the contract. */ public declare methods: { @@ -157,6 +146,9 @@ active_at_block: { /** get_vote(candidate: field) */ get_vote: ((candidate: FieldLike) => ContractFunctionInteraction) & Pick; + /** process_message(message_ciphertext: struct, message_context: struct) */ + process_message: ((message_ciphertext: FieldLike[], message_context: { tx_hash: FieldLike, unique_note_hashes_in_tx: FieldLike[], first_nullifier_in_tx: FieldLike, recipient: AztecAddressLike }) => ContractFunctionInteraction) & Pick; + /** public_dispatch(selector: field) */ public_dispatch: ((selector: FieldLike) => ContractFunctionInteraction) & Pick; diff --git a/app/artifacts/private_voting-EasyPrivateVoting.json b/app/artifacts/private_voting-EasyPrivateVoting.json deleted file mode 100644 index c09592f..0000000 --- a/app/artifacts/private_voting-EasyPrivateVoting.json +++ /dev/null @@ -1,2983 +0,0 @@ -{ - "transpiled": true, - "noir_version": "1.0.0-beta.5+0000000000000000000000000000000000000000", - "name": "EasyPrivateVoting", - "functions": [ - { - "name": "add_to_tally_public", - "is_unconstrained": true, - "custom_attributes": [ - "public", - "internal" - ], - "abi": { - "parameters": [ - { - "name": "candidate", - "type": { - "kind": "field" - }, - "visibility": "private" - } - ], - "return_type": null, - "error_types": { - "206160798890201757": { - "error_kind": "string", - "string": "Storage slot 0 not allowed. Storage slots must start from 1." - }, - "2024020833944022298": { - "error_kind": "string", - "string": "Function add_to_tally_public can only be called internally" - }, - "3557153117338734214": { - "error_kind": "string", - "string": "Vote has ended" - }, - "5019202896831570965": { - "error_kind": "string", - "string": "attempt to add with overflow" - }, - "13699457482007836410": { - "error_kind": "string", - "string": "Not initialized" - }, - "14225679739041873922": { - "error_kind": "string", - "string": "Index out of bounds" - }, - "17843811134343075018": { - "error_kind": "string", - "string": "Stack too deep" - } - } - }, - "bytecode": "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", - "debug_symbols": "tZnbbuM4DIbfJde5kChSh77KYFCkbToIEKRFpl1gUfTdl5RIOilgo+Ps3NSfaemveNDBzsfmaf/w/uv+cHp++b25+/GxeTgfjsfDr/vjy+Pu7fByYuvHJsifGMvmLm43EaJe87gm0Kveoz5HbU96T/o8632mzR3xtbB8lSvfR3lQEwMwtGggXbktBLFUAbE0hhgNmgLg5g5QoCkkVobMgMHALCSWIlAVclYorAzyv0pWqGapZNAUWjIoA1KIBmSgjVNEA7NAMrDuybon6564cUoMMvjEfiUZ/ACxcHxSDgZoUBUKGGSFao2rNa7WWNwZoBYMYKDdMQYDNODGGLYbAh4PZoGmkNDALGgWNAslA7NkayM1MsCUJRfIacoysAFZIdqjaBYwC5glBQOzoLWRuu1Apiy10SEnA2nDLmcpkgFZQaI6AA2agkR1gHYvffAdqkI0S7Q2UhtYBaqCzLgBWUEKewAaWGOyxlQUslmyde9edCCDplDtv1fr3qxx08Y1BAO3cHfiSqiRuxNP6iopGNAUpCQG8FCJp3nFZFAUZO0YQAZNIVvjbN2LWYp1lyKhJNAUJAXE9dNkeg5oChLwDhJeKgIcH2J3mkS1gwRzQFGQ1WyAjJDXn1a5V2bfWwsGaFAHxCCJHxSDkz+VlOfYqRnJYAZJpSoVIxmYkttkaBk6NaOCRhWcilHzHpJbJesbpUZzEpKsKhUjSbASOTWj5D2Sq6Db0FXIVchVJOUZhSTGg2Q1UypGUqpK1Uh2jk4QLM4Q0MkiDtFtMpUy9f1NxpI7kVMz6pEcVEe9RJARKBWjBk5mSwGc3BbdFt0GycltsjEokVMzQu+B3qPXBnWSaHRbH/2gqn6kHr9BbpPRK0lf2adRpo6S23oVt07k1IzAlBEsftjruRNGp2JE4OQ2zwd6PtDzgcX/R6/s/Pm53dgp5v7tvN/LIebiWMOHndfdeX9629yd3o/H7eaf3fG9N/r9ujv169vuzE+5KvanJ76y4PPhuBf63E69w3zXUipo78qzwQUafVdBcmsDkEzSnAYsaASwUfCScTEKuFJI8wrYQlEFbDG7Qr6OBM4rVJR9YUQCM84pLHrRmnnB83rOi3yzF+XvekHVc1Fnc9EWFKiYFzGnNDeGuFBUjeTU2CV4Iys3uhFh1o2lwgZeZkwC+OVgrrDjQl1SqDY5GOtsLJYKk+TFYqSUUpiTWPYkw+RJnZ3m8fbajLcX5/dzUnHNglWilycfS12BvtTWkkRE8uIqk0Rkp6404sLKW5NVRuEUz5b4Qo3zOdkWHD4pzxYXpEVPWnJXCGbzuuwKTK7keQlamCfFCpTqtHKmlFdl9SKc9P3amhLChZVvVcgwW1nt9spK4ebKSvHmykrwP1TWtwNaV6Wk+HpRG96o0OJsYaWFpVMOpCaBUOaTurR2wnRQS2F27ZTVcVYiVN9I+FvYrMRiefLXDE9qxrQmqSmjRyNOnvD71PVZLS4dMbJKQJjmWYr1WmFp7SzoFV7aFAyoX06MC4tnIosFXmyI/B53rbCwt/M3QasMgNDmNZaWTp+ql6eDP1JotnTmSOv84O+M5ke6yMgfaZToSS1LnrS/qxFz9kUnl7pOoxRf+0qDdRr84ccXHpjXWJpq6GmJdLGlfZ1qtJCWXHzxKpCnCd+u5xrR0m7iChfx/Lr6hW++H2ZaFYo4bSUclnUS0yk61nWjSD7VGNeNgvywxTkt6yTyVBa1rXNkKs4E6xxJiNN3g1WOFLSEFMxrBJqfthqtcmJ6KWqwbgReU63QjS58FfjJt7vHw/nqt7JPkTofdg/Hvd4+v58eL56+/ftqT+y3ttfzy+P+6f28F6XpBzf+84N/RdomgJ/yIZZvK25rk5soz/jNIwH9/JSh/Ac=", - "brillig_names": [ - "add_to_tally_public" - ] - }, - { - "name": "cast_vote", - "is_unconstrained": false, - "custom_attributes": [ - "private" - ], - "abi": { - "parameters": [ - { - "name": "inputs", - "type": { - "kind": "struct", - "path": "aztec::context::inputs::private_context_inputs::PrivateContextInputs", - "fields": [ - { - "name": "call_context", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::call_context::CallContext", - "fields": [ - { - "name": "msg_sender", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "function_selector", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::function_selector::FunctionSelector", - "fields": [ - { - "name": "inner", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - } - ] - } - }, - { - "name": "historical_header", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::block_header::BlockHeader", - "fields": [ - { - "name": "last_archive", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "content_commitment", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::content_commitment::ContentCommitment", - "fields": [ - { - "name": "num_txs", - "type": { - "kind": "field" - } - }, - { - "name": "blobs_hash", - "type": { - "kind": "field" - } - }, - { - "name": "in_hash", - "type": { - "kind": "field" - } - }, - { - "name": "out_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "state", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::state_reference::StateReference", - "fields": [ - { - "name": "l1_to_l2_message_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "partial", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::partial_state_reference::PartialStateReference", - "fields": [ - { - "name": "note_hash_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "nullifier_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "public_data_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - ] - } - } - ] - } - }, - { - "name": "global_variables", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::global_variables::GlobalVariables", - "fields": [ - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - }, - { - "name": "block_number", - "type": { - "kind": "field" - } - }, - { - "name": "slot_number", - "type": { - "kind": "field" - } - }, - { - "name": "timestamp", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 64 - } - }, - { - "name": "coinbase", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::eth_address::EthAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "fee_recipient", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "gas_fees", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_fees::GasFees", - "fields": [ - { - "name": "fee_per_da_gas", - "type": { - "kind": "field" - } - }, - { - "name": "fee_per_l2_gas", - "type": { - "kind": "field" - } - } - ] - } - } - ] - } - }, - { - "name": "total_fees", - "type": { - "kind": "field" - } - }, - { - "name": "total_mana_used", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "tx_context", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::transaction::tx_context::TxContext", - "fields": [ - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - }, - { - "name": "gas_settings", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_settings::GasSettings", - "fields": [ - { - "name": "gas_limits", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas::Gas", - "fields": [ - { - "name": "da_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "l2_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "teardown_gas_limits", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas::Gas", - "fields": [ - { - "name": "da_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "l2_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "max_fees_per_gas", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_fees::GasFees", - "fields": [ - { - "name": "fee_per_da_gas", - "type": { - "kind": "field" - } - }, - { - "name": "fee_per_l2_gas", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "max_priority_fees_per_gas", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_fees::GasFees", - "fields": [ - { - "name": "fee_per_da_gas", - "type": { - "kind": "field" - } - }, - { - "name": "fee_per_l2_gas", - "type": { - "kind": "field" - } - } - ] - } - } - ] - } - } - ] - } - }, - { - "name": "start_side_effect_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - }, - "visibility": "private" - }, - { - "name": "candidate", - "type": { - "kind": "field" - }, - "visibility": "private" - } - ], - "return_type": { - "abi_type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs", - "fields": [ - { - "name": "call_context", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::call_context::CallContext", - "fields": [ - { - "name": "msg_sender", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "function_selector", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::function_selector::FunctionSelector", - "fields": [ - { - "name": "inner", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - } - ] - } - }, - { - "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": { - "kind": "struct", - "path": "aztec::protocol_types::abis::max_block_number::MaxBlockNumber", - "fields": [ - { - "name": "_opt", - "type": { - "kind": "struct", - "path": "std::option::Option", - "fields": [ - { - "name": "_is_some", - "type": { - "kind": "boolean" - } - }, - { - "name": "_value", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - ] - } - }, - { - "name": "note_hash_read_requests", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::read_request::ReadRequest", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "nullifier_read_requests", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::read_request::ReadRequest", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "key_validation_requests_and_generators", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator", - "fields": [ - { - "name": "request", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest", - "fields": [ - { - "name": "pk_m", - "type": { - "kind": "struct", - "path": "std::embedded_curve_ops::EmbeddedCurvePoint", - "fields": [ - { - "name": "x", - "type": { - "kind": "field" - } - }, - { - "name": "y", - "type": { - "kind": "field" - } - }, - { - "name": "is_infinite", - "type": { - "kind": "boolean" - } - } - ] - } - }, - { - "name": "sk_app", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "sk_app_generator", - "type": { - "kind": "field" - } - } - ] - } - } - }, - { - "name": "note_hashes", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::note_hash::NoteHash", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "nullifiers", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::nullifier::Nullifier", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "note_hash", - "type": { - "kind": "field" - } - } - ] - } - } - }, - { - "name": "private_call_requests", - "type": { - "kind": "array", - "length": 5, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::private_call_request::PrivateCallRequest", - "fields": [ - { - "name": "call_context", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::call_context::CallContext", - "fields": [ - { - "name": "msg_sender", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "function_selector", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::function_selector::FunctionSelector", - "fields": [ - { - "name": "inner", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - } - ] - } - }, - { - "name": "args_hash", - "type": { - "kind": "field" - } - }, - { - "name": "returns_hash", - "type": { - "kind": "field" - } - }, - { - "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": "public_call_requests", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::counted::Counted", - "fields": [ - { - "name": "inner", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::public_call_request::PublicCallRequest", - "fields": [ - { - "name": "msg_sender", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "calldata_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "public_teardown_call_request", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::public_call_request::PublicCallRequest", - "fields": [ - { - "name": "msg_sender", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "calldata_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "l2_to_l1_msgs", - "type": { - "kind": "array", - "length": 2, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message", - "fields": [ - { - "name": "recipient", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::eth_address::EthAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "content", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "private_logs", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::private_log::PrivateLogData", - "fields": [ - { - "name": "log", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::log::Log", - "fields": [ - { - "name": "fields", - "type": { - "kind": "array", - "length": 18, - "type": { - "kind": "field" - } - } - }, - { - "name": "length", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "note_hash_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "contract_class_logs_hashes", - "type": { - "kind": "array", - "length": 1, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::counted::Counted", - "fields": [ - { - "name": "inner", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::log_hash::LogHash", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "length", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "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": "historical_header", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::block_header::BlockHeader", - "fields": [ - { - "name": "last_archive", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "content_commitment", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::content_commitment::ContentCommitment", - "fields": [ - { - "name": "num_txs", - "type": { - "kind": "field" - } - }, - { - "name": "blobs_hash", - "type": { - "kind": "field" - } - }, - { - "name": "in_hash", - "type": { - "kind": "field" - } - }, - { - "name": "out_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "state", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::state_reference::StateReference", - "fields": [ - { - "name": "l1_to_l2_message_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "partial", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::partial_state_reference::PartialStateReference", - "fields": [ - { - "name": "note_hash_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "nullifier_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "public_data_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - ] - } - } - ] - } - }, - { - "name": "global_variables", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::global_variables::GlobalVariables", - "fields": [ - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - }, - { - "name": "block_number", - "type": { - "kind": "field" - } - }, - { - "name": "slot_number", - "type": { - "kind": "field" - } - }, - { - "name": "timestamp", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 64 - } - }, - { - "name": "coinbase", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::eth_address::EthAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "fee_recipient", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "gas_fees", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_fees::GasFees", - "fields": [ - { - "name": "fee_per_da_gas", - "type": { - "kind": "field" - } - }, - { - "name": "fee_per_l2_gas", - "type": { - "kind": "field" - } - } - ] - } - } - ] - } - }, - { - "name": "total_fees", - "type": { - "kind": "field" - } - }, - { - "name": "total_mana_used", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "tx_context", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::transaction::tx_context::TxContext", - "fields": [ - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - }, - { - "name": "gas_settings", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_settings::GasSettings", - "fields": [ - { - "name": "gas_limits", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas::Gas", - "fields": [ - { - "name": "da_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "l2_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "teardown_gas_limits", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas::Gas", - "fields": [ - { - "name": "da_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "l2_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "max_fees_per_gas", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_fees::GasFees", - "fields": [ - { - "name": "fee_per_da_gas", - "type": { - "kind": "field" - } - }, - { - "name": "fee_per_l2_gas", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "max_priority_fees_per_gas", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_fees::GasFees", - "fields": [ - { - "name": "fee_per_da_gas", - "type": { - "kind": "field" - } - }, - { - "name": "fee_per_l2_gas", - "type": { - "kind": "field" - } - } - ] - } - } - ] - } - } - ] - } - } - ] - }, - "visibility": "databus" - }, - "error_types": { - "576755928210959028": { - "error_kind": "string", - "string": "0 has a square root; you cannot claim it is not square" - }, - "855401245733623969": { - "error_kind": "string", - "string": "Obtained invalid key validation request" - }, - "2709101749560550278": { - "error_kind": "string", - "string": "Cannot serialize point at infinity as bytes." - }, - "2896122431943215824": { - "error_kind": "fmtstring", - "length": 144, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "2920182694213909827": { - "error_kind": "string", - "string": "attempt to subtract with overflow" - }, - "3305101268118424981": { - "error_kind": "string", - "string": "Attempted to delete past the length of a CapsuleArray" - }, - "3367683922240523006": { - "error_kind": "fmtstring", - "length": 58, - "item_types": [ - { - "kind": "field" - } - ] - }, - "5019202896831570965": { - "error_kind": "string", - "string": "attempt to add with overflow" - }, - "5727012404371710682": { - "error_kind": "string", - "string": "push out of bounds" - }, - "5870202753060865374": { - "error_kind": "fmtstring", - "length": 61, - "item_types": [ - { - "kind": "field" - }, - { - "kind": "field" - } - ] - }, - "6336853191198150230": { - "error_kind": "fmtstring", - "length": 77, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "6485997221020871071": { - "error_kind": "string", - "string": "call to assert_max_bit_size" - }, - "6753155520859132764": { - "error_kind": "string", - "string": "Failed to deliver note" - }, - "7233212735005103307": { - "error_kind": "string", - "string": "attempt to multiply with overflow" - }, - "8270195893599566439": { - "error_kind": "string", - "string": "Invalid public keys hint for address" - }, - "8830323656616886390": { - "error_kind": "string", - "string": "Got a public log emitted by a different contract" - }, - "12822839658937144934": { - "error_kind": "fmtstring", - "length": 75, - "item_types": [] - }, - "13649294680379557736": { - "error_kind": "string", - "string": "extend_from_bounded_vec out of bounds" - }, - "14225679739041873922": { - "error_kind": "string", - "string": "Index out of bounds" - }, - "14514982005979867414": { - "error_kind": "string", - "string": "attempt to bit-shift with overflow" - }, - "14657895983200220173": { - "error_kind": "string", - "string": "Attempted to read past the length of a CapsuleArray" - }, - "15366650908120444287": { - "error_kind": "fmtstring", - "length": 48, - "item_types": [ - { - "kind": "field" - }, - { - "kind": "field" - } - ] - }, - "16218014537381711836": { - "error_kind": "string", - "string": "Value does not fit in field" - }, - "16446004518090376065": { - "error_kind": "string", - "string": "Input length must be a multiple of 32" - }, - "16954218183513903507": { - "error_kind": "string", - "string": "Attempted to read past end of BoundedVec" - }, - "17843811134343075018": { - "error_kind": "string", - "string": "Stack too deep" - }, - "17879506016437779469": { - "error_kind": "fmtstring", - "length": 128, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "18194595712952743247": { - "error_kind": "fmtstring", - "length": 98, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - }, - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - }, - { - "kind": "field" - } - ] - } - } - }, - "bytecode": "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", - "debug_symbols": "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WHpYelh6WHh4UdFJklSSalJL6kmaNJJmUnpIekh6SHpIekh6SHpIekh6SHpIepT0KOlR0qOkR0mPkh4lPUp6lPQo6VHTo6ZHTY+aHjU9anrU9KjpUdOjpkdLj5YeLT1aerT0aOnR0qOlR0uPlh49PXp69PTo6dHTo6dHT4+eHj09enpoemh6aHpoemh6aHpoemh6eJxXJwvyOD9IkkpSTWpJPUmTRlJ6jPSY6THTY6bHTI+ZHjM9ZnrM9JjpMdPD0sPSw9LD0sPSw9LD0sPSw9LDwsMLl06SpJJUk1pST9KkkTST0kPSQ9JD0kPSQ9JD0kPSQ9JD0kPSo6RHSY+SHiU9SnqU9CjpUdKjpEdJj5oeNT1qetT0qOlR06OmR02Pmh41PVp6tPRo6eFxPpxaUk96esyH00iaSRa04vwkSSpJNakl9aT06OnR06Onh6aHpoemh6aHpoemh6aHpoemh6bHSI+RHiM9RnqM9BjpMdJjpMdIj5EeMz1mesz0mOkx02Omx0yPmR4zPWZ6WHpYelh6WHpYelh6WHpYelh6WHh4cdRJklSSalJL6kmaNJJmUnpIekh6SHpIekh6SHpIekh6SHpIepT0KOlR0qOkR0mPkh4lPUp6lPQo6VHTo6ZHTY+aHjU9anrU9KjpUdOjpkdLj5YeLT1aerT0aOmRcd4zznvGec847xnnPeO8Z5z3jPOecd4zznvGec847xnnPeO8Z5z3jPOecd4zznvGec847xnnPeO8Z5z3jPOecd4zznvGec847xnnPeO8Z5z3jPOecd4zznvGec847xnnPeO8Z5z3jPOecd4zznvGec847xnnPeO8Z5z3jPOecd4zznvGec847xnnPeNcM84141wzzjXjXDPONeNcM84141wzzjXjXDPONeNcM84141wzzjXjXDPONeNcM84141wzzjXjXDPONeNcM84141wzzjXjXDPONeNcM84141wzzjXjXDPONeNcM84141wzzjXjXDPONeNcM84141wzzjXjXDPONeNcM84141wzzjXjXDPONeNcM84141wzzjXjXDPONeNcM84141wzzjXjXDPONeNcM84141wzzjXjXDPONeNcM84141wzzjXjXDPONeNcM84141wzzjXjXDPONeNcM84141wzzjXjXDPONeNcM84141wzzjXjXDPONeNcM84141wzzjXjfGScj4zzkXE+Ms5HxvnIOB8Z5yPjfGScj4zzkXE+Ms5HxvnIOB8Z5yPjfGScj4zzkXE+Ms5HxvnIOB8Z5yPjfGScj4zzkXE+Ms5HxvnIOB8Z5yPjfGScj4zzkXE+Ms5HxvnIOB8Z514LNtebuReDnSRJJakmtaSepEkjaSalR0+Pnh49PTzOm1NL6kmaNJJmkgV5nB8kSSUpPTQ9ND00PTQ9ND00PUZ6jPQY6THSY6THSI+RHiM9RnqM9JjpMdNjpsdMj5keMz1mesz0mOkx08PSw9LD0sPSw9LD0sPSw9LD0sPCwwvJTpKkklSTWlJP0qSRNJPSQ9JD0kPSQ9LD49xnE3ucH6RJI2kmWZDH+UGSVJJqUnqU9CjpUdKjpEdJj5oeNT1qetT0qOlR06OmR02Pmh41PVp6tPRo6dHSo6VHS4+WHi09Wnq09Ojp0dOjp0dPj54ePT16evT06OnR00PTQ9ND00PTQ9NDw8OreobD+j/VaZlNp5lkQX5CB0lSSapJLaknaVJ69PTo6aHpoemh6aHpoemh6aHpoemh6aHpMdJjpMdIj5EeIz1Geoz0GOkx0mOkx0yPmR4zPWZ6zPSY6THTY6bHTI+ZHpYelh6WHpYelh6WHpYelh6WHnZ6FC/8meYkSSWpJrWknqRJI+npYQ+np4dVX3PgkSRJJakmtaSepEkjaSalR0mPkh4lPVbisubUknqSJo2kmbQ81FdKeCRJUkmqSS2pJ2nSSJpJ6dFSeaUrG06atP7W79uK35MsaMXvSZL0VJGH3xBfJ+DEBnZQwQFO0BJ91YCHOApYQHfzq++rBzz8Yvr6AQ8/P19B4MQBTtASfSWBE13X25qvHXBiT/R5/+dqFR1UcIATtERfA+BEAQtYQdwMN8PNcDPcLN28JCdQwAJWsIEdVHCAE8RNcBPcBDfBTXAT3AQ3wU1wE9wKbgW3glvBreBWcCu4FdwKbgW3ilvFreJWcau4VdwqbhW3ilvFreHWcGu4Ndwabg03j0Jpjh1U0I9BHSdoiR6FJwpYwAo2sIMK4qa4eRT6ShbHqjknCljACjawgwoOcIK4+RofMhwFLGAFG9jB5VbEcYATtESP+RMFLGAFG9hB3Aw3w83S7Vx9pzhWsIEdVHCAE7TEYzWeAwXETXAT3AQ3wU1wE9wEt4Jbwa3gVnAruBXcCm4Ft4Jbwa3iVnGruFXcKm4Vt4pbxa3iVnFruDXcGm4Nt4Zbw63h1nBruDXcOm4dt45bx63j1nHruHXcOm4dN8VNcVPcFDfFTXFT3BQ3xU1xG7gN3AZuA7eB28Bt4DZwG7gN3CZuE7eJ28Rt4jZxm7hN3CZuEzfDzXAz3Aw3w81wM9wMN8PN0u1YQehEAQtYwQZ2UMEBThA3ckkll1RyST1ySXVsYAcVHOBMPF4PzFHAAlawgR1UcIATtMSKW8Wt4lZxq7hV3CpuFbeKW8Wt4dZwa7g13BpuDbeGW8Ot4dZw67h13DpuHbeOW8et49Zx67h13BQ3xU1xU9wUN8VNcVPcFDfFbeA2cBu4DdwGbgO3gdvAbeA2cJu4TdwmbhO3idvEbeI2cZu4TdwMN8PNcDPcDDfDzXAz3Aw3S7f2eIACFrCCDeygggOcIG6Cm+AmuAlugpvgJrgJboKb4EYuaeSSRi5px8uIOjawg56uhuMAJ2iJx8vIgQJ6cnS342XkwAa623RUcIDLbS2FUrzY6ETPJScut1odC7jcanNsYAeXW/XT9Fxy4gTdzY/Bc8mJAhawgg10XT9Nzw/t4bgUmh+654cTK9jAdbzNT8jzw4kDnKAlen5YC7gULzAKLKC7+Wl6fjixg+52/O4AJ2iJnh9OFNDPzRuB54cTG9hBBQc4QUv0/HCiu/ml9vxwYgUb2EEFBzhBC/Tqo0AB3a05VrCBHVRwgBO0RM8PzRwFLGAFG9hBBQc4QUssuBXcCm4Ft4Jbwa3gVnAruBXcKm4Vt4pbxa3iVnGruFXcKm4Vt4Zbw63h1nBruDXcGm4Nt4Zbw63j1nHruHXcOm4dt45bx63j1nFT3BQ3xU1xU9wUN8VNcVPcFLeB28Bt4DZwG7gN3AZuA7eB28Bt4jZxm7hN3CZuE7eJ28Rt4jZxM9wMN8PNcDPcDDfDzXAz3Czd9PEABSxgBRvYQQUHOEHcyCVKLlFyiZJLlFyi5BIllyi5RMklSi5RcomSS5RcouQSJZcouUTJJUouUXKJkkuUXKLHgsUPx+W2VncqeixafGADO6jgACdoiccSxgcKiFvDreHWcGu4NdyOJY2boyUeyxofKGABK+i66ugKxzrED9AVpmMBK9jADio4wAm6m9+AY0njAwVcbuq3xfPDiQ3s4HJTcVy6ur6lvd4pUMACuq5fB88Eeiy57Lp+STwTqB+vZwL1I/NMMNzYM8GBnglOFHC5DT8yzwQnNrCDy234jfXwH8fCz26xDscLn2TVuxevfHp27Doui1kcK9jADio4wAkut1VUU7wEKrBEK/HSp8AGdlDBAU7QEj3mTxQQt4Kbx/w8FrzuoIJ+QsfvTtASPeZPFLCAFWxgBxXEreLmMe+Dtl4VFehu07GA7uZ306PbR3i9DCpwgpbo0W3iKGABK+h58vizDio4wAlaIl8d43hTOLCA/aiDKF4C9ezcdxzgBC3RQ/5EPwlvZh7yJ1awgR1UcIATdLcV3F4QFSigu/mheyLw0WAvihIf5vWqqEAFBzhBSzx6Kp1qUkvqSZo0TvLCpOJjvV6ZFChgASvYwA4qOMAJ4lZwK7gV3ApuBbeCW8Gt4FZwK7hV3CpuFbeKW8Wt4lZxq7hV3CpuDbeGW8Ot4dZwa7g13BpuDbeGW8et49Zx67h13DpuHbeOW8et46a4KW6Km+KmuCluipviprgpbgO3gdvAbeA2cBu4DdwGbgO3gdvEbeI2cZu4TdwmbhO3idvEbeJmuBluhpvhZrgZboab4Wa4Wbr5Al2BAhawgg3soIIDnCBu5BIjlxi5xMglRi4xcomRS4xcYuQSI5cYucTIJUYuMXKJkUuMXGLkEiOXGLnEyCVGLjFyiZFLjFxi5BIjlxi5xMglRi4xcomRS4xcYuQSI5cYucTIJUYuMXKJkUuMXGLkEiOXGLnEyCVGLjFyiZFLjFxi5BIjlxi5xMglRi4xcomRS4xcYuQSI5cYucTIJUYuMXKJkUuMXGLkEiOXGLnEyCVGLjFyiZFLjFxi5BIjlxi5xMglRi4xcomRS4xcYuQSI5cYucTIJUYuMXKJkUuMXGLkEstcUh+ZS+ojc0l9ZC6pj8wl9ZG5pD4yl9RH5pL6yFxSH5lL6uOBm+AmuAlugpvgJrgJboKb4Ca4FdwKbgW3glvBreBWcCu4FdwKbhW3ilvFreJWcau4VdwqbhW3ilvDreHWcGu4Ndwabg23hlvDreHWceu4ddw6bh23jlvHrePWceu4KW6Km+KmuCluipviprgpborbwG3gNnAbuA3cBm4Dt4HbwG3gNnGbuE3cJm4Tt4nbxG3iNnGbuBluhpvhZrgZboab4Wa4GW7kEiGXCLlEyCVCLhFyiZBLhFwi5BIhlwi5RMglQi4RcomQS4RcIuQSIZcIuUTIJUIuEXKJkEuEXCLkEiGXCLlEyCVCLhFyiZBLhFwi5BIhlwi5RMglQi4RcomQS4RcIuQSIZcIuUTIJUIuEXKJkEuEXCLkEiGXCLlEyCVCLhFyiZBLhFwi5BIhlwi5RMglQi4RcomQS4RcIuQSIZcIuUTIJXKEdHW0xCOkD3SL5ljACjawgwp6t5fTTLKgI57VUcACutV0bOCyEj8Fj+cTBzhBC/Q1ywIFLGAFG9hBBQc4QXcrCz2eTxSwgBVsoPewOWnSSJpJFuQdhwe5YnX0I22OfqTH3moTtESPzhP9SIdjASvYwA66mx+DR+eJE1xu5bHQo/NEAZebbxvnhY+By634CXl0nqjgcjt+dSZZkIfmQZJUklzRL5HH2rnHnP/1anxexhgoYAH9SP0EPdZO7KCCA1xuxz52FuRP7YOWlR+VP7MPqkktqSdpkpuY4wQt0aP4xPX31S++x+uJS8EvrT+BD7Igj9fqV8/j9cQCrgOtfiwerye61bE9n4IDdC+/ph6vdbUqL0csq/ajejliWUUc9djU8MQKNrCDCg5wgstt7WpTj00OV8FHPbY5XDUE9djWsPmGgv6kXfUc9dja8MQBTtAS/Ul7ooAu5qfpoXriACdoiR6qJwrof+YXymPuREv0mDvR/8wc15Vcg321xoZNtcaOTbXGlk21xp5NtcamTbXGrk21xrZNtca+TbXGxk21xs5Ntfb06OnR06OnR0+Pnh49PTQ9ND00PTQ9ND00PTQ9jnA7cF0Qvx65cSE7F7J1IXsXsnkhuxeyfSH7F7KBITsYsoUhexiyiSG7GLKNIfsYspEhOxmylSF7GbKZIbsZsp3hsWlh93buseZ4bFx44hJaA5P12LxwDY7WY/vCNRpZj+0K12BjPTYjXAOI9diOUP13/cl2YgPXya11HOuxLeGJA5ygJXr8nChgAd2tOzawg8tt+Ll5KA0/HA+lE5fu8N/1p96JFWxg588UHOAEcWu4eQSeWMAG9mO/sHpsWHjQSJpJFuSBd5CLq2MBK6igH55fQ3/UDb/n/qg7sYAVbGAHFRygXwxvNf6sO9Cj78TlNr0tefidWMHlNr2FeQSeqOAAJ2iJHoYnCljACuI2cZu4TdwmbhM3w80jcnq785A8sYKu6/fco3KN3VavjAv0w1FHP5zhqOAAXWE6WuKxbWhx9OSy3PqxnadbHBt6HqjgAD3r+DEcG3s6Hlt7HihgASvYQNf14z021j3QEo/Ndf3Qj+11DyxgBRvYQQVH4rFtrjl2UMEBTtAS/cGz5qbWY/PAEwtYwQZ2cEWzf3kdGwmeOEFL9O0EH37ffPtA/x7zirDqH1ZeERao4AAnaIm+oeeJfhZ+j31TzxMr6G5+33xrzxMVdDe/Or7B54mW6Jt8nihgASvYQH9i+zU7Nvxc10GP7TyrYwEr2EB/h2iOE7TEYyvPAwUsYAUb6EfWHRUc4AQt8djVUx0L6GKr2euxS+d0dGNzXMb+feTFVoF6bIVYvdbqpJlkQSuUTpKkklSTWpKbiKOCA5ygJfrT50QBC1hB1/X76e90/l3hNVb+ku0lVieVpJrUknqSK/rxe1SdOEFL9Kg6UUC/zC7m8eMfd75qVKArLPLwOUiSSlJNakl+Tf3OeuScOMAJWqJHzomu6g3Co8E/1HxZqHb8/zPJTvLqKP828OKok0pSTWpJPclNiuMAZ6IHzInrPNcUgeplT4EKrsNUp5lkQb7l5kGSVJLWifsXpBc8BXZQwQFO0BI9wk4UsIC4Vdw87vzL1AueAgfobn7RfWfcA31v3DVXoXrBU131QdULnqp/bXrBU2ADl5vHopdBBS43b+xeBlWPq+M7lLmsb1F2kCSVpJrUklzR77Y/1o5Gc+yJ679w7Ip7YAXXkfpX0zj2xj1QwQHOxGNHXD9BDzX/zPD6perfFl6/FDjACVqiR+CJAhawgu7mF87D8EQF3c0vp4fhiZboYXiiu/k18wfYiRVcl9dPzbcnO0iTnlbHNfAdyg6yk459Ag+SpJLkJtOxgR1U0BL9aeafbF4fFbgU/OvN66MCFRzH1mU19wasuTlgzd0Ba24PWHN/wJobBNbcIbDmFoE19wisuUlgzV0Ca24TWHOfwJobBdbcKbDmVoE19wqsuVlgzd0Ca24XWHO/wJobBlYvhKqrTLZ6IVRgAdcl0+rYwA76JeuOA1ztSP36+yPyQH9EnihgAd3Nb5D3jpy43IbfFX9wDj8yj97hLcN7SE60RI9p/+D1QqjAAtZjf7h6bDB4UE/SpJE0gzya/UPVy5qqfxZ7WVP1z0ovawoc4AT9SP20PZpPFLCAFXy6HS00lkuvM5Zeq16R5B9NXpB0Uk9axzT96vnO8SdO0AK9HClQwAJWsIEdVHCAE8TNX0T9e9HLkQILWMEGdnCc18BLkE6yIN9Z3j83vQApsIAVbGAH/Wy64wAn6Gezbq0XIAWW8yZZrIheLVZEr15y5F0PXnF00khy8QMt0UP2RAELWEE/lenYQQXXVXs4zSQLiqVUq8VSqtViKdVqsZRqtVhKtVospVotllKt1tOjp0dPD00PTQ9ND00PTQ9ND00PTQ9ND3/jXeXW1SuLAgVc18z8d/3r8sQGdlDBAU7QEj2cTxQQt4mbP5zNY8AfzicqOMAJWqI/nE8UsIDu5kHiX5cndnBdRm+PvojZQTPJDmrHImYHSZIrHuhH2hz9SLujJXqQnyigH+lwrGADO6igu5njBC3RQ/5EAQtYwQauL4DV+9C8Tqit3ofmdULt4ce7Qj7QElfIBwpYwAo2sIMK4lZxq7g13BpuDbeGW8Ot4dZwa7g13BpuHbeOW8et49Zx67h13DpuHbeOm+KmuCluipviprgpboqb4qa4DdwGbgO3gdvAbeA2cBu4DdwGbhO3idvEbeI2cZu4Tdymu6njBN3NQ8QeoIAFXG6rh6l5nVBgBxUc4AQt0OuEApfbKgVoXicU6BbFsYMKDtAtqqMlygMUsETekSOBHNjADio4wAla4pFADqzHS1c7djo8qCc9RfX4vZE0k/z4HT1JnChgASvYwOXkl9D3QTtoJPml6o6W6BniRDk2Dmu55WHLLQ9bbnnYcsvDllsettzysOWWh01iK7SWWx623PKw5ZaHLbc8bLnlYcstD1tuedhyy8OWWx623PKw5ZaHLbc8bLnlYfM6n7b6EZvX+QR20JvX8bsDnKAlei44UcACVrCB7jYdFRzg0214S/Edk5x8x6SDJKkk1SRXNMd1pMX/1SO7+O33yD6xgBVcR1o8UjyyT1RwgBN0t9X+vGIoUMBy7DrVSux/1krsf9ZK7H/WSux/1krsf9ZK7H/WSux/1krsf9ZK7H/WiqSHpIekh6SHpIekh6SHpEdJD+9pW72dzVdSa6uTsXnpUGADO6jgACdoiR7tJwqIW8Wt4lZx81eC1efZvKAocIKW6AF/ooBLdw32t2NJNL9zxyIDi/zJvroom9cGBRawgg3soIIDXIdYDwtL9Cf7ie7ml9+f7CdWsIHupo6uOxwt0eP2RAFd16+Cx+3qfGxeOdSaXxCP2+bH63Hb/Mg8bpsb+zP8REv0Z/iJPqLgR+bP8BMr2EB389vqD+7uh+MP7u6H4+HdvXF6eHc/HA/v7ifk4X1iBRvYQQUH6G5+DB7ejl5VdLQRryoKrOCy8EedVxUFKujd28fvTtAS/cF9ooAFrGADO6ggboLb0Z2+rlk9+tMPdLfqWEB3K46u2x0HOEFL9IBe08Cblx0FFrCCLZJ1PQL6QAUHOMHM8fUI6AMF9KszHDuo4AD9LPwe+9v8gR7zJwpYzk6sdlQondjADio4wAlaokf36sZrXpUU2MAOKjjAdRb+MPTVyk70mD9RwAL6SI43DY9jT/teltSGNwKP4xMFdAVvOx7HJ/oAkZ+Qx/GJCq7jHX7nPaRPtEQP6RMFLGAF3c1voYf0iQoOcIIW6HVM3tHd2jHKJY4N7KDrTscBTtASPY5X70rzmqfAAi631SHXvOYpsIPLzbsOvOYpcILu5ofucbz675rXPLXVz9a85qmtzrXmNU+BDXRdvw4exydaosfxia7r5+YR663Eq5sCFRygJXrHWz+wgg30AQo/t6OQ6cABTtASj2KmAwUsYAX9ovo184fwiRO0RH8Im98sfwifWMAK+picXx0f6TpRwQFO0BLHAxSwgD6y6BdqKLjOwrx5evCeaIkevCf6WfifefCeWMEGdlBBH8f0K+ldbCdaonexnShgASvYwA4q6Gex0BcCCxSwgH4WzbGBHVTQz+LhOEFL9O63EwUsYAUb6PeiO07QEj1MT/SzUMcCVrCBHVRwgBN0txWxXnIVKGAB3W06NrCDCkahQ/NCrEBL9M72EwUsYAUb2EHXLY5+FisKfXGvQAF9uNqv+jFe7Y3gGLA+sIMKDnCClqgP0MfGvcH4oJd3JR2FWP7d5yVX3buSfGmuwAJW0BX8qo8OKjjACVrifICSx3DUkhxYwQZ2UEHO4ignOdASzc/C77z5WfhV9xHrEzuo4DoL79nyRbgCLdAX4ereyeXlWYEFrGADO6iguxXHCVqiuFt1FLCAFWxgBxV0t+Y4QUv0kW7vSPL6rcACVrCBHVTQ3dRxgpboY97ea+KLcHV/6fVFuLr3ZnhdWPdw8rqwwA4q6MUGfhY+9u2f+14a1j02vTYsUMACupsfTnM3c/TCBj+ypuAAJ+jnthq4F4gFCljAqHlreswNOLCDCg5wgpZ4zBA4UECvzvAr6SPdJyo4QD8Lv5LriX6i54cTBSxgBRvYQQVd1xuiZ4ITBXRdv4Wzgg3soIKu67fbY957D7yELLCBHVRwnDXHTY+i5AMt0GvLAgUsYAUb2EG/vsPREj26TxTQz2I6+h0yxwlaokes93Z4PVlgAdcZex+I14517wPx2rHufSBeO3ZcB68dO9Fj80QBC1hB1+2OA5ygJR6TAvw0j0kBBxawgg3soIIDnInHxDe/Or2AFVztoR2/20E/i+MXBjjBdRbek+MVZIECrqvj3wFeQRbYwA4quNy6Xx2PwhMt0aPwRAELWMEGuq7fIZ8P4DnKa8W69xB5rVhgB/3IvPXNAfqR+XXweDvQHqCXLbmFR+GJFWxgBxUcoFcveaP1J6/jUTF2ooAFrGCLM/YdALt3APkWgIGW6FF4outWxwJWsIGrTfpj5lhq68QBTtASfXLPiQIW0K9Oc1RwgBP0s/A/OyrIDhSwgCsC/Dl/LKp1YgcVHOAELdHj+EAfGPJM4IVegQWsYAM7qOAAJ2iJipvi5oNEnj290CuwgR1UcCQO1zVHAQtYwQZ20EcGvWmMAU7QEldAqudfLwILLKCm7hzgBC3ROHTj0K2k24rCwAZ2UNPYBjgDvQxrekeNl2EFKriKSbxb6CjJWpVe7ajJOtB3wTxRwFX8451FXpQV2MAOuu46Xl/paXpnkddcBVaw87vrIL03yautAidoib7F5YkCFtAthmMDO+hu03GAE3S31WjPvSEPFLCAnNCxP+SBHVRwgBO0xGOXyAO5fMrl87jw8QuvsAqcoCV6tJwoYAEr2MAO4jZwG7gN3CZuE7eJ28Rt4jZx83DyNxCvsQqcoCV6OJ0oYAEr2MAO4ma4GW4Wbt3rrAIFLGAFG9hBBQc4QdwEN8FNcBPcBDfBTXAT3AQ3wa3gVnAruBXcCm4Ft4Jbwa3gVnCruFXcKm4Vt4pbxa3iVnGruFXcGm4Nt4Zbw63h1nBruDXcGm4Nt45bx63j1nHruHXcOm4dt45bx01xU9wUN8VNcVPcFDfFTXFT3AZuA7eB28Bt4DZwG7gN3AZuA7eJ28Rt4jZxm7hN3CZuE7eJ28TNcDPcDDfDzXAz3Aw3w81wI5cIuUTIJUIuEXKJkEuEXCLkEiGXCLlEyCVCLhFyiZBLhFwi5BIhlwi5RMglQi4RcomQS4RcIuQSIZcIuUTIJUIuEXKJkEuEXCLkEiGXCLlEyCVCLhFyiZBLhFwi5BIhlwi5RMglQi4RcomQS4RcIuQSIZcIuUTIJUIuEXKJkEuEXCLkEiGXCLlEyCVCLhFyiZBLhFwi5BIhlwi5RMglQi4RcomQS4RcIuQSIZcIuUSOXDIcl9v6cu9e1RWo4AAnaImeS04UsIAVxG3iNnGbuE3cJm6Gm+HmuWQVlXSvAwtsYAcVHKC7VUcL9DqwQHdTR3cbjhVsYAcVHOAELdFzyYkC4ia4CW6Cm+AmuAluglvBreBWcCu4FdwKbgW3glvBreBWcau4VdwqbhW3ilvFreJWcau4Ndwabg23hlvDreHWcGu4Ndwabh23jlvHrePWceu4ddw6bh23jpviprgpboqb4qa4KW6Km+KmuA3cBm4Dt4HbwG3gNnAbuA3cBm4Tt4nbxG3iNnGbuE3cJm4Tt4mb4Wa4GW6Gm+FmuBluhpvhZulWHw9QwAJWsIEdVHCAE8SNXFLJJZVcUskllVxSySWVXFLJJZVcUskllVxSySWVXFLJJZVcUskllVxSySWVXFLJJZVcUskllVxSySWVXFLJJZVcUskllVxSySWVXFLJJZVcUskllVxSySWVXFLJJZVcUskllVxSySWVXFLJJZVcUskllVxSySWVXFLJJZVcUskllVxSySWVXFLJJZVcUskllVxSySWVXFLJJZVcUskllVxSySWVXFLJJZVcUskllVxSySWVXFLJJZVcUskllVxSySWVXFLJJZVcUskllVxSySWVXFLJJZVcUskllVxSySWNXNLIJY1c0sgl7cgl5thBBQc4QUv0XLK6+7vXwAUWsIIN7KCCA5ygJRbcCm4Ft4Jbwa3gVnAruBXcCm4Vt4pbxa3iVnGruFXcKm4Vt4pbw63h1nBruDXcGm4Nt4Zbw63h1nHruHXcOm4dt45bx63j1nHruCluipviprgpboqb4qa4KW6K28Bt4DZwG7gN3AZuA7eB28Bt4DZxm7hN3CZuE7eJ28Rt4jZxm7gZboab4Wa4GW6Gm+FmuBlulm5ekhcoYAEr2MAOKjjACeJGLunkkk4u6eSSTi7p5JJOLunkkk4u6eSSTi7p5JJOLunkkk4u6eSSTi7p5JJOLunkkk4u6eSSTi7p5JJOLunkkk4u6eSSTi7p5JJOLunkkk4u6eSSTi7p5JJOLunkkk4u6eSSTi7p5JJOLunkkk4u6eSSTi7p5JJOLunkkk4u6eSSTi7p5JJOLunkkk4u8VI/XSXy3ddcC7REzyUnCljACjawgwriNnAbuE3cJm6eS1Z9dfcCwMAGdlDBAU7QEj2XnCggboab55JV/t+9LDBQwQFO0AK9LDBQQH8v6Y4VbGAHFRzgBC3x+MY5UEDcBDfBTXAT3AQ3wU1wK7gV3ApuBbeCW8Gt4FZwK7gV3CpuFbeKW8Wt4lZxq7hV3CpuFbeGW8Ot4dZwa7g13BpuDbeGW8Ot49Zx67h13DpuHbeOW8et49ZxU9wUN8VNcVPcFDfFTXFT3BS3gdvAbeA2cBu4DdwGbgO3gdvAbeI2cZu4TdwmbhO3idvEbeI2cTPcDDfDzXAz3Aw3w81wM9ws3cbjAQpYwAo2sIMKDnCCuJFLBrlkkEsGuWSQSwa5ZJBLBrlkkEsGuWSQSwa5ZJBLxhHo1dEtiqOCA5ygJR4hfaCABaxgA3FruDXcGm4Nt45bx63j1nHruHXcOm4dt45bx01xU9wUN8VNcVPcFDfFTXFT3AZuA7eB28Bt4DZwG7gN3AZuA7eJ28Rt4jZxm7hN3CZuE7eJ28TNcDPcDDfDzXAz3Aw3w81ws3SbjwcoYAEr2MAOKugvI93RX0amoyV6SJ8oYAEr2MAOKjhA3AS3glvBzUN6FYd1XyIvsIEdVHCA7qaOluivBye2SBXzSBUHKjjACeYol5cx6ipF674kXmAB16FPv+qeKk7s4HKbh9gAJ2iJnipOFLCAFWxgB3HruHmqmN4ePFUc6KniRAELWMEGdlDBAbrbcLRETxUnCljACjbQ3bzBeKo4cYATtERPFScKWMDlZn6HPFWc2EEFBzhBS/RUcaKABcTNcDPcDDfDzXCzdPPF+AIFLGAFG+hu1VHBkehJ4URXaI4N7KCCA5ygJXr4nyhgAd3NHBvYQQUHOEFLXOE/Hn4W6+sgsIB1oTo2sIMKDnCCltjczY2bgAVcv7smhnUv5wwUMHumjfELY/zCGL8wxi+M8Qtj/MIYvzDGL4zxC2P8whi/MMYvjPELY/zCGL8wxi+M8Qtj/MIYvzDGL4zxC2P8whi/MMYvjPELr/ccaypc93rPE329nBMFLGAFG9hBBQeYPS5euDnkwA4qOMAJ2onqhZuBAhawgg3soIIDnCBugpvgJrgJbr4szqrNV6/LDLREXxnnRAELWMEGdlBBd9OFHoVrept6rWVgAzuo4AAnaIkehSf68U7HAlawgR1UcIATXG5rJqF6rWWggAWsYAM7qOAAJ4ib4qa4KW6Km+KmuCluipviprgN3Ia7eYMZBayggq7gt9tj80QBC1jBBnZQwQFO0N28RdkDFLCA7uZNw0P6xA4qOMAJWqDXTwYK6G7TsYIN7KCCA5ygJXpIr6mR6vWTgQWsYAM7qOAAJ2iJBbeCW8Gt4FZwK7gV3ApuBbeCW8Wt4nasj1sdK9jAkegxvyZ4qtdEBhawgg3soIIDnKAlenSvqUTqFY2j+p33iD3REj1iTxSwgBVsYAf9yLwReMSeOEFL9Ig9UcACVnC5Nb/U68kbqOAAJ2iJHt0nCljACuI2cZu4TdwmbhM3w81wM9wMN8PNcPPobt5gPLpPnIFeuxjoCs2xgwoOcIKW6BF7ooAFrKC7qWMHFRyguw1HS/SIPVHAAlawgR1U0N2m4wQt0SP2RAELWMEGLrfVK6FepRg4wAlaokf3iQIWsIINxK3h1nBruDXcOm4dt45bx63j1nHruHl+6N6iPD+caImeCU50BW8PHvMnDnCClugxf6KABaxgA13XW5RH94mW6NF9ooAFdF1vMB7dJ/pZ+O326D7R3cxxgsttTeJVrzEMXG5rYq56jWHgclO/qB7dJy439cvn0X3iclM/TY/uEy3QawzHmuiqXmMY6G7qWEF3G44ddLfpOEB3M0dL9Eywhi/VawwDl9taaEu9xjBwua1hRvUaw8DltpYhU68xDFxuww/dM8GBnglOFLCAFWxgBxUcIG4Ft4pbxa3iVnGruFXcKm4Vt4pbxa3h1nBruDXcGm4Nt4ZbixFoPWoMT7TE/gAFLKDreivx6B7eNDy6p99Nf/qfKGABK9jADio4wAniNnAbuA3cBm4Dt4HbwG3gNnAbuE3cPD9Mb6meH06soIKu4O3XY/5EAQtYwQZ2UMEBTtDdVsx7LWCggAWsYAM7qOAA3U0dLdFj/kQBC1jBBrrbcFRwgBO0RI/5EwUs4HJbq6Kp1wIGdlDBAU7QEj3mTxSwgLhV3CpuFbeKW8Wt4tZwa7g13BpuDTeP+dXZqV4LGDgS/Tl/oitUxwZ2UMEBTtASPeZPFLCA7ua3xWP+RHebju5mjlG3okd934mWOB6ggAWsYAM7qCBuA7cV8/PhF3XFfKCABaxgAzuo4AAn6G5u7JvXnChgASvYQFdY4eQ1e4ECFrCCDfTjHY6a6GsZrDXC1GvrAge4zsL7uby27kRfy+BEAQtYwQZ2UMEB4lZwq7hV3CpuFbeKW8Wt4lZxq7hV3HwJhLWAl3ptXWABK9jADio4wAlaYset49Zx67h13DpuHbeOW8et46a4KW6Km+KmuCluipviprgpbsPdvPUNAQtYwQZ2UMEBTtASPY7Xul/qtXXTu0u9ti6wgg3soIIDnKAlWlS76Vlbd2ABl9ta0E29ti6wgwoOcIIW6LV1gevcvJvQa+sCK9jADio4wAlaojxA3AQ3wU1wE9wEN8FNcBPcCm4Ft4Kb55K1MpB6bV1gB2ei5wfvGPV6ucAKNrCDCg5wgpbo+eHEqABSr4Gb3q3pNXCBE7REj/kTBSxgBRvYQdw6bh23jpviprgpboqb4qa4KW4e894r7DVws3qb9Jg/0GP+RAELWMEGdlDB5eY9p14DF2iJHvPeXeo1cIEFrGADO6jgAN3NT9Nj/kB/dp8oYAEr2MAOKjhA3CzdxuMBCljACjawgwoOcIK4ecx7J6rXwAUWsIOuYI6W6HF8ooAFrGADO6jgAJfbWr9PfXm+E/2d4EQBC1jBBnZQweXmfaReUBdoiR7z3q3pBXWBBaxgAzuo4ADdzS+q54cDPT+cKGABK9jADio4QNw6boqb4qa4KW6Km+KmuCluipvi5vmh+Y31/HBiATu4FNYkf/UiuRM95k8UsIAVbGAHFRygu3l78Og+sYCu6+3h2G7yQNf1u+nRfeIAXbc7WqCXwwUKWMAKNrCDCg5wgrgJboKb4Ca4CW6Cm+AmuAluglvBreDmmcB7Wb0cLrCBHVRwgF6OsS6qF75N75z1wrdABf3PpuMELdFD+kQBC1jBBnZQQSw8Nr0r2CvYAju4/sx7hb2CLXCCluixeaKABaxgAzuIhQeZdzx7KVpgA/3PiqOCA5ygJXpAnihgASvYQCw83ryb22vKAivof+Z33uPtRAUHOEEL9JqyQAELWMEOulh3tEQPpxNdTB0LWMEGdlDBAU7QEj2cTsTNA8f77Y8lAr2z3gvJAgc4QUv0R+iJApbo9D0KyU5sYAcVHOAELdFjyMcOjtUCT1RwHa/3QR+rBZ5oif5YPFHAAlawgR1UEAuPIR+pOLZdPbGD/mfFcYATtER/vp0oYAEr2MAOYuEx5OMiXvAV2ED/M2+pHk4nDnCClugvsicKWMAKNjAsxrEl6hpyGF7wFVhB/zN17KCCA5ygJXqQnShgASuIhUfLanLDS7sCC+h/Nh0b2EEFBzhBS/QYOlHAAmKxGoE9/BhWIwhsYF9ojgoOcIKWuPJvoIAFrGADcZu4TdxWe7BVwzm8nMhWCeHwGqL413U4a5X+4TVEtorvhtcQBQpYwAo2sIPrcFZn3PAaosAJuttqZ15DZKsDaHgNka3emeE1RLbq2obXEB2H7jVEgR1cd9Pc2NvOiQIWsIIN7KCCA5ygu/lZeNsxPwtvOycWsILu5qfp7zsnKjjACVqiv++cKKDr+jXz/Gt+zTzprs764Wul2dqkY/haaYEFrKCC3jz9+uoDdIXi6A3RL4n67/olGQ9QQHfz63AEzoEN7KAfg5/bETgHTn7BEo/AOVDAktfBk+6JDezgzDOenLFxxiaB5VjT1xw7qKDfgON3J2iJR4MpjgKWRO+PkgMVXCMgHlnHGlYnWqKPCZ+4+jI9yI41rE6sYAM7qOAAJ2iJXrd9Im5elu0hfSxRdeIAJ2iJPlR0ooAFrGADcfOhIk8gxxJVJ07QEn3SxYkCFrCCDewgbhO3iZtPmSh+ZD5lohz/OsAJWuCxwNTqlxvHAlMnFrCCDeygggOcoCUKboKb4Ca4CW6Cm0+vWF2K41hg6kDfy8ETk5d5BBawgg3soIIDnKAlVtwqbhU33+HB06CXeQR2UMEBTtASffeVEwUsIG4Nt4Zbw63h1nBruHXcPHg9Rx3LQ3k2OpaH8oR3LA91oiV6mJ4oYAEr2MAOKoib4qa4DdwGbgO3gdvAbeA2cBu4DdwGbh7H/mQ4loc6sYAddAVvtD4h6kAf/jlRwAJWsIEdVHCAbrGC4Vjn6UQB3cIcK9jADio4wAlaoof0iQLi5sHr733Hik7+8nSs6HTiBC3R50adKGABa7TJY0WnEzuo4AAnaIk+NfJEP7Lh6Efml89nPh7oMx9PFLCAnsz95P1pWvzk/Wl64gQt0Z+mJwpYQE+OfpD+ND2xgwoOcIKW6GG65jOMY+WlEwtYwQZ2UMEBusV6JzjKMU4UsIAVbGAHFRzgBHGbuHlsrjHAcSy3dGIFG9hBBQfIzZrcLONmWd6sY5mhtVXOOBYUqv6v3pRPFLCANZrcsaDQiR1UcIATtERvyicKWEDcKm4Vt4obwXCsInScm0fA2v1qHOsFndjyhPx98kQFB7gOfQ3FjWO9oAOP/VAO9AtVHQtYQdw6bh23jtuxH8qB3Bbltii3Rbktx34oB+J2bILy+M8//uH5R//xB38DWH0b/vx3qAEtoAdowHoOrw4Pf+Y7rGewb2z7CHDl57X3Z/2xee2CZ47x57xDD3Bl308oYCkf+4qc4M92h6Xss7RLQA1Yyj4/uwdowFI+pk0H2Am+q5NXAEpACXDl1eXZAnqAK69OyREwA1zZOzcCJMCV/bUvoAW48mqiGjAC/G1n3UA7wXdSc/C3que5+y5qDv5GJc9bXNYt9n0AV5ef7ynm4Hft+Zu+n9jqc/M30FGef1LzT9a3lf+Ctee/N/93//36/M/u/7mOXOfzP3X9p99N35RaA0bADDCH55+MFFT9z+d///Vf/vlP//aXf/nbP/3b3//85/X/xT/86x/+23//jz/8nz/9/c9/+7c//Le//ftf//rHP/zfP/313/2X/vX//Olv/vPf/vT35//7PLk//+1/Pn8+Bf/XX/7650X/+Uf++vH6T4t/r/pfPz8KNAVs3FV4flZoKthIhWfX0G0JWZ/+h8TzE/ilRH0tIR4+LiHPbHSRaB8k2msJ34PZFZ6pEIE2bh+Dl6Ucx/Ach3p5DPpaovs6F8dBPAewUqLLbQWfZHMoPPP0K4W5aRK+faYrPL/v5ZWCvVbwMUAXeHbTchlq/yAgu2Ypq1DhOIZnV1RqtPJRQjYSk4b9UmB/IYULOV9dBtk2iBH3QqzVlw1CNq1SfP/cQ+PIVf/1YbRdjE/LS1Efrw9Dd4cxWh6GXE5lfroj47WGf9S4xLMf46Jw/0yeuSaaxbMv4nWEyaZxivhc2uNUnr1319vyMdTL4/vXo8i3r8fuXMqjRyN9dmI/2utzqbtgWw/DM9jmJf3Oj1e17NrYeKTGsxszNfQL51LnzHNpbXNfNu20aD6Nnl2LlzT+PK8PGmP3OCozW1m/anw6jk0SfXYRZUt9dg+81tgdR2k9H4vz9XHUTTtd241FFnuOt73U2N8ZfdDKxoe4+3QkZRe7lgm5XO/MZ41dS9X5yFYm9lpj11LLI7JhefbCv6fRaj4i23zdUuumpWqLgFHlKKp+jJi6aR9GvDwuF+MXiU0zXVOVMwf1x2uNXfN4DupEG3vypbF/Vmmbhqq8iK4qiUtD/SixyaeztMjJs2h5JbG9HiUfMGvK5+sz2T71NVvH4vb6qu6a+siTeeLrcNkG7jMLRSN7Dir28lKl7R794sVv5wNzjseL5N7GP/Tx8OzVzLfrtt7KX56L/UMfuWvf8zwO3QR/372c1hEHUp79xJcj+fiO3Mt3r+n2KJpkOn32kL48iu0rWdXLg05fvpKtT4KXGsoL6nNY4qKhtzWevcFxNdpz6OO1xvj+S12f/9CX3PbID+r2IfLbFzT4KG+bu6Kyy+vZRC8vyc8R0o8KmxY687N+VnutUHePuDgNs9cK2yvRH9k+p8rrK9F3L0Az20Wt15fsj3GiujsOyTvy7M97S+M5JGK08fJaY36/jeu3s+j2itb8uBb98An28UyGbF/kyF719dXYto7Ja7qV9l6sWc3XdJuvv/JH+26sjf7dWBv6D401sziI57Dh646Gset98vW6zqfahzj52D7Hrv9JKi+CD31Lwx4asWYPs5caU74fa7P8I58nz2HbuLHPUVl9q403PnieA4CPt7o2x4P+tMtN+dSRtesmLjVT6PP96WU38RzbV41HvmrY66ax1fCi7PORYvJtDXuUNzUeNTXkdaiYfDdtWPlu2tgqaEbJ43IpPktsL4WXgp6X4sO3wadL0b/d976VuNfG9xIFiUv3xJckbg0BmG07OJQvgzclshftKaFvSfTs3SzPgd2Xfd+Pbf7Mt4RnL1Z7S2Ot1npDY38qtwZV5LF9xMc9mc02wyr9+yMz4/tDM4/5zbGZ/VE8jD7rS6T9MkC0eZ7MGbfEpLy+GLtBpmd3SPZqPrvSLidTrL3ZOF4PNe3GmnzhMJcY4+Xl+E3WuDXeJf37aXgr0h4lv3Ie0zYi2+c8Q8p6fWH5NJy7PxLJLPjsXmibI7HvPmFlN9h08818fyp0j4hsLur2OO49qPcHotzdcR0Y+eVA2vevaf/2Nd1K/MTlmBkxz4GE3eWY34z97WE8E1C++0jftPS6fT+3HDerl8ekfkGi5ldXrZf+988SZdfS8yienzsvJe5ejbJ5Od+LjOx4Wtu+bC5p330NZ//EE+fL69F/YOS+fn/ofiuR4xl6eWv4moQyZDY3Erur0SVHEfq1K2+Wr1xSeq/6tb/6s0jbtFOxS6+iFXuvpfo6QUcjsz5fN7LWtmPEGfuXKzLmJ4n+7fGd3VF0vnva3BzFTiIH7/rcnMj2gprFc2Gtmfle6K+V7LKtv5s/1sqZKaKblNy//Xkv/dvf93uJH3hQKgV+a9WrzeXYRr9ll4msfWHeibnh6/mej9vd+2nfDohqJ7G//rTda/ANNDeftn1bY5LVELW87m74ncbj2xpN8pOwlcd7GpX3jyavNXYDTpdP/bUpylsad7scbh7HVmN/TWve29Zf9zno+IHrMf7R5zIuA5rz2xrXtPy1NlbyC7fL6+sxdk9++qBltE3Pw/ZABn0o1++oXw6kff/m7jTuNvabx/F+A6H7ou6S4W7sSR5Gocu10+BLN8YXMozRgdctde6q9vLToZVN+9iOPZEM5ZlbU+Q5cvKF46iP/Fafm8uxf+RWvj+sv3w3nG0vUi4i+o7IzQ/D353MvePYfcX4SjTH+0N9vB628dK81/2fVDFeS+5+6d/afk/lgId+KC/9yicZb7pzUwrw7fGO+e2xivntoYr5/ZGKXQfs3Uy67cS9OVLx/UGG73fN73rE73XN+3vn97vmb8+FeZnMy2706F7v3A/MK9rOAZn5aCv2of/3U43/bvToXgffXuJWB1/ZDf3czOPbi5EvccU21Qz+bfS9T+si3+7X30vc/LT+fsfc9/vl9Ae65fT7vXJlK3K3V852j7TKW/XlMG4LiGj2ZD15XLuhPk0f2cncDNetxL1w3c1yuheuu2Gne53g25lWt5r4VuFWE9/OGLvZxPezzm428d20ortNfDtlrOSAQCnlWjne7mv0lvWbvb/W2E9N8uZ7nEu5zmD5dQKcfDtSthL3ImU35ePmg+3+5dBN4tjOoeN1WK9jkp/n0N3WGN/XuPaTfGUu30Ozb/Khr+e/le0Mpzkub5KbyXy7CU68c8wmb0r0SEKzjzclWh7FdbjoTQmt713Q0iufS9dC9q+J8FhQ6W/eWiNgbHNftoPWml8raybLWxrPb1imr2ya2M25ns8u0s3dvTtvdadxdw7u2MRt/+5X0/YoBjX187HJYn3zpWA1H5X27JR79TJXtrObKrOb6nWBjE9XtO9Oxi4Vc9cRxc8au+e+XGbQPbs658uz0e2nU/Y7zQ8P7S/k9ZkfLU/Ulxr7J13PGg35UFH565Nu89Q25kc+rh0Nn77vt3OBRbKd7aYllt1wz8xR5w+F3L9c1N1UKfquH4+50dh1Qd2bhFt2k5RuzsLdnsuzKzRHSB5td0F2vfmm2QNutnuNse8ngPH4fgLYTna6mQC24073E8Du3tR82j3HGMp7jfWjiL0U2U/kz+URnt87r9/89xp5WZ9v9/M9jZpF1eXDUg+fNcbuzS7fqeZ7M/mfY705Q6ddzuQrGs/OzhwPlPl63nqZ2y/lHDRaO3S9J7LWrc0xkkvF2RdFckWnUW2+KdJyOG+0Wt8UmTk8MK4vzV+6OS1HfPq1uuFLGoM1rq494l/TyC+qPsuukWxXJniwCM/zw2xzXW3XH1IY9X2yblrbbhLUc8yPEfmuj8fbR8PCD8+jsY3MLjc231zmHLqdY757iVnG5sn93RZznRUw3tMw6vLsMtD4pYVKHtlyVeS941DJL1eVXRTat99utp+cawPSuDFrP863DmR1ETOF+hmJb6oofYFr47g3VUbhjEbTd1VyPETWTlpvqswcRpW1Ada7x3K5ulM2V3c3VHU/P9XddKmVn1gE7jqo8GWZe2nudyd1M83V7dSpNllVqm0v8W9kbmbL39zvfml7+nbby7lxorO/G012WRzBtL2rwqpMasPeUxlFMj88ub+rwgpCa2OFlyq7dZV+Zm2mwSjMHF3eVJn5LvZkebypYpdjsc2r8n6dqMGSaJtukL2GsdbUh0nxX9DwLR+jY+j1V9C+U8d4jhSzzeJs5duTVfYStwYM9xK3Rgx/s/AW+Vrs8r7+uXnserhY/cHk5bjUXqLk5A57fjC/My5Vu7AQWd98rO9V1PJ61CGbT/767SqWvcStwb5av1/Fcv9ylLcvKu8WTxV9U2XkiM6T+yYPtW+Pw+4l7t2a9o8dh/14OTbjsL+7NfOislm+z76byrYK98p7tovm1ewUevLuEbM7kHuFIFuJZzZk3GBoe1NkXN5nRrc3RXKA6slT32lnraHRenm9/m/fvkL/yJKGxehK/dBT3t/TuI7HfEWj0y3cr5H3BY3n8Zfsbf8wGvtJ4/uzw7drGj6y+rRJu97cL6yLKKwZ93yHeKlRdwv53czLW4l7eVm/XcC/vRiFZazKhxWkPh/GbhW+aQyzX6dn/CKymxN1p0Zwfxj0qjW7VrZ86VwYNeyP0t4WKSnS5tsi2dH4eHP9zttrgM7vPi63Crcel9uR+pulgvu1TO+VCnq9x+sh1JvVsLuo5VnZZnldbF3Ht4ut6/x2sfVe4max9e5qlMLULn2vlr/VXNGhfZgf9vmK7mZDaQ6O66U/pnwaT567yVAPurHLtYW1j41ju+bkvSv6m6YR7Ws+NvPktxrdWBdrlPc0LHsQnw8IeUvj+Y0fr8n2KP2lxm6s8fbCleW7SXCrcCsJbicw3kyC+wU4byZB+4EpAbuZpc+Xppx6XMbrZSd90ubrLwb6qIe+nNy112B9i3ItE/qk0XYzq25OVNtq3Jyo9ptzyTeg8qjl9XHsvvVvzbRtj+3avSbcF7s84j5PNNsfya25ttsLUnztv+OCPFPyWxe1CFtbyCV9/HJR5/cv6rbv49705f1x3Lqk2zR2a4bsXuHWBNn67WfkdvHxljMI63WC65cWMLcc22ofase+tIA5GuXNBcxvL4L+7T4x/Xaf2LY88ebzbb+Y+73nWys/sBDV2K428APrubMC1MdJAV/RYMmTZ+fP61X2264++d7HRivjux8be4mbr8bbK5pDwKXb6yva6nbe2s01k+r2SZ0Spq+X2W91u9/JrSWTfqNxa8mkrcbNJZN+p/H4tsa9JZP2GveWTGr78q5bq8i0fXnXvVfKm8ex19he01tLJrVWvn89bmp841xuLZl0W2OzZNJv2titJZPabv+ou0sm7Q/k3pJJbTdqc/vm2vcb+83jeL+B3FsyqfXtTI17SybtD+TekkltP1Zy65tjN8nq9jfHb/ahuvHN8bsn7q0lk1q3vcidpYq2IvdGXH57MreOYzd4VCY7f4i+/n5pu++ou0smbV/7b30P7hXufA9uxxduHcNe4dYxbN8sszLhifafbw3UjnrZ4fDxnoYyYKxW39OYWQBT7NHf0ngOPOUz7lFeX4+6i7a7o85bkWebyG/bOV6WjG0lLLuR1Mp4T4IvbOsvh2pvt472ZgsraNTXF7SNb6+ispe4NfbdpvxDJW4On2+vp/6X9TdfuyfMuBv2bua4HMe7GmyF8sR3NVq5o9G+/URp336i/KbCM/uirJQ3i0Sz4u2JLyuiyreXI/yNxL1rsbunOfW4fFxs7Su10Pky+uxlGG9qsCn7HO8eBwsxzPF6u+zf1Lo3qtSvld1frJi/qmzmPP1OpaEyXs9G6A/ZPt/uzHLvu0X9bs4D+039f2FZGdvMcv3NNTHmItjj7bkI12Opb6vw4TKtvTlzZZRKYeSzR/ddFb3MOXl7/kt9MLZXS3lXpV1U+ruzaGq9qui7KpeulDrfvi7jomLv7hzfLrOLWnn3TrfHVeXtVseSBKPVTW6RbdlVzZrNJ28azO9kKFNudTNPqe/rg+9Ojvvd0eRHxZM3U2e/clLfkMlOyVVMvrnEpf7/cW2Mk2qP9hMn9Q2ZlvtJSdutV9C3SwT+1LVhaeYnt/4jJ9XeTZ+PB5X/j8e7k5SNSTfjOjD3xVUlsvzuifamiOZb+9Ay3hTpOfg7ur17OiN7gcd8e82P6+m8L8K6YTreXfODbVzHkPbukWSZ+FOkv3sknWXQevuBuyOblLDdruoLq1JsV0LJWqltS9kvuEOhQG2vZ6vsFzDNqtFSrtNVPy0+2ncTNO91De0lbvXr9Db/oRI31+jdXc/KrJs6Xi/m2nf9KbcmRWyPotG51D6sb/X5KOr3Pw936wbeXQRtuzxuYen5ay3wl5bYvW5LMDcau+WXb67TuxW51y29l7jVLf0biTvd0tt1oG/1Ue0V7nRRyfe37fh2N9luqdHsnNLrrKGqdwVYALZ/2Ih63hV49rHRP3YdH2h2VwKFeZ32/GnK4906wvqewuROzDcVcjeZx8tj2K1OmI/1dt0dtLXbbSH7fNq1ObZ+uy1kL2XX9wSyL6Jfezm/IJDrX3woXnxL4FI48AWBa0Q+3hJgfSxr7wiMHB0f14UQ3xK4htMXBJiE83jrFFiVZb53CjNr3+e1yOgtgf7WbWQDdXvvIhrDMO2tlsg0JlP9psB46zbKo7P6q751GdntZl7fJMf9q5jn0F8u2Nq3q/jdXWx1l5oZX6x2mcpun49jtyMU/Ur9Q2/v84F19zDsMoX8MrP/l8MYu9jODo95XWl5LQb1UWRX4VnytaM/vzJfnstepGZh9RP7uyL3rur2mjwvBNfkMijw+ZrodnepkWs3jOvaTb+K1N07QM6blovE47PEdhlsKnHKw94UYRD5+YFe3hQZ2cVQxmUk62siNYven8ck754OlUX18fp0ftPUclyiX1fk/2J7ZYp+e8g7WeBu8D3+sUfx/XTWc42xvmkd+7mL+bLX3xGQR2HZeX1PQlhQRy5rLnxJIucwicz3jqLmpZDrCstfkegs9d4vy+d/SUJZHXPaeyfCgn61vHcildqE2t86kbuZa3cUqqx+Ot47kTEYCLXyloRxOa9LpHxBYuSrz3U92S8IWHZIWn/rOtjjv3oV/4pAxpeN/s1TeE9A2ALl8l37y8zRXWf7vclwulst795kuL3Evclw263T7LKE7suZLLqbYXRvb9S9RGehCX0t0b6/v6ruVsm7t7+q7gaESmUlgXYpm/48W+LuPRkv78m2gV8XYrvO9/x0W1vfpV26Ekd5Ndtin+7ySfrhq/vxhRPJpe3EPkzV/Hwi89uxuismvRmrW4lvx2oRhnGuaw7/cjF2G0j5cuY8Cl+Oav1OpF7Xha4vRbbbzWbZS31c+1h/OZ3tzs7ZpfH8HuSB9mlfrq2GEm96HVL6ksbIXQWe7xf1tca3559sD+MZ95eyhdeXQ7f78mTvyqWmRD6l0d32UZ2dzp590FeN+Ulkl0hZPq1+2Lnps8i+eWSf2bguev/L9Wi7D6MMmGfr0Ff9PLrbQUpYaULa5Qk36yeN3Zi45JBGlWuXhn6+NduNH/Mbq14/kOrj89nM7/da6W6A5u6H8/6aNGFi8mWzh1+uyW49gP7I74v+uG5Vpl9oJJqbaPR5mYX/uZGMurusM0feHpeK5c+XdTfoxMBZG1LeeeQ2FSTK5t1hfHutCB3fXitiL3FziZjfPOoua3i8XtRW5+MHnpc7kXvVKNtH7u0Lsnts9wd1D9f3/c/tY7fM3vN9MK/HdVW4XzLIVoTX9fIoOxH9ftD9RuRmQpz6A/3eu+2Nbvd72+Pb/d67vaNu93tvRe72e29F7vZ7b9+rSnYZrCrIl+8RuyEnGZdC2+vKtPXzNOltI+FDuW4kxu4LNQtKS6ubsLH5A2GzvSJamKHw4bv/4+mM3ZJ5z5dDtoCcOxH5/jUZ2zGn29dE73RByLUY+9ez2Q46MYnzOm/x17Pp3z+b/c2hq+3Dgj6/ns74idP5iQZ783NiPuZ7X4oXjefj4LXGdtXwh7HWkrz+wBqya67Zk8wlbfV+S+05FNivyxR8JZt1xpyvlQCfG4ds1y5nHeVy2Zzzl8/EfUq87FWq492UePMlwOb3XwKG/MBLwCjffgkY5QdeAvYiN18C9iJ3XwJ2rZW5oHa5M7+01rIL/keuUd3lWlP3OXB36b2LIHJdz/0Xkf791roVud1ay0+01vr91lp/orXWn2it9Qda6/bRWyy/wYv11++Ko26Xj8ok3x7Xj71fmpp8P7v+5uXqbnstP9Be60+01/b99tp+or22n2iv7R/dXqvk/nTPl/HNq+JuzKqNHH1r8/pW8kt7HT+RX+dPtNefeBtoP9Fe+/fba/+J9tp/or32n3gb2HbpVzY1rZf+609d+mO/Kt6dOQJbiXuzBPYSt+YJ7CVuzRS4K7GZKzD2g3B3ZgvsJW7NF9hK3JsxcFdiU+6+l7g1a2ArcW/ewF7i1syBuxL9zZt6b/bAXuLW/IG9xK0ZBHclxps39e4sgt+MIipD99c1ZD6NIo6x+YypI19Q15Kr//l6KHI3inizbP03IveqZ7eDoref1bsNUW4/q7fr6t17Vs/HDzyrtyJ3n9XzB4o/98PElXXF62Vm5q9D59tp7Sxmea04/ywy5k/0qs6f+HafP/HtPn+ivc7vt1f7ifZqP9Fe7R/eXlu+W9Z2ebf8palZ235QDUo9+quyhrEfs2Lwe1zfLz/l+V232a3ZwHuFO7OBf6NwYzbwtkikWY6+98d1UcuPV3PuPnEb77hNr1+nb2vUVxpfqJp5XUk0H9uFoqgjbNcVIT+fzG63vUdjuXbbXJDtC42xU/ezT1V/RMVeX9htmdeDxWB2ZV673t3G3qPXmR+fKonmdpsoeTAN5rrIzqdXqynbepNMy5eFBIp9uqoi3388zN041b3Hw9xttHL38bAXuTltbS9y+/GwayI9R1W7XpbV/txEdmtd/NfrG3xqqFPmVxU+r5Dwm4q3m0NmO5G7LzKz/ERLLd9vqeUnWup+Fad7LzJ7kdt1M3drvOvrGu+5XXZvXpZPvdSsfp7Z0bcvQ/VSPPvYHIh9fyDjNyL3Sk3mboTo7mfEb0TuRd9W5Hb07WZT3Y6+3VjVzeir+gPRtxW5G31bkZ+IvucXa80ykfm6GnjuRqrujoZsRe6W8Mz2A/VVvxG52ejbD4wjzt1Y1e1Gv10o716jb+MHGv1W5G6j34r8TKPPIcBaN7POtiLtkafTHn0TObvS8R8RubdC3F7i1gpxv5G4s0Lc/ubeXDriN83s5jv4NrfePZJ9lr95JPvlIW8eSfmB75J9t9XNI/lNB9rNI5k/cSTzB47kN8MC95YY+Y3IvcU99gPWd6/Jfuj85t1pP3Ek7SeOpP7EkdSfOJLyE0dSfuBI9nMd7i7PYz9wJNulC5kMdxmnHLeX+Hp2XbMKy+M6W0K/IMEK9I8p+o4Eg89Pvgw/f0HCcq3ZJ6u8JcHWFB8mBXxF4rIf5eMyJfe+hLBP4JPLq6OYuylOd09lK3JvHtxj+4Z4Y33q7QzpO0tLT/vHSnz7OkjpeUfLdULSvL9URZk5CFCu6zO8K6FvSVQWmqjXqeJfkVCqua4zq74g0XPirPT23rWorPzRPuy5+KbEezf1Oln90kP1JQnWW2qqb0pwIh+WTv+CRH4dS5vv3dRm7Dn7eLzZLljOpbx1U9luus23LiZNs5fX18F2tahlss/8nNdWcfsg8hvyOq71lbPIyRMfRk+/INAZN2lvCWQPVLf6nkDWWlr7nsCHSsuvXESGXN9KlZrjglrtm0fw3m0sPRdbKHrpw7OPJWy2myP17KXKaezXrQg+bbhh2ylSj3zDrHLZR+AXDdllh5FFfU8er7s1bTf0VJ5P8Dida7FH+TQmaNu9n0quufB8FNubIpUN5po8NiK70yn5+v/sLn59OrtGctn0Qi8DlJ8byW7kqYmwxO+ln7ffX1+tVjZGqtf0/8tx7Mbz2dpFrjvc2ccRMNvuOP7sMueT6iH26mxsP0mqN7YL75elFL9yTezyXJbLd6rdXwxbWEBCLo/2/ilmdqNONyv49xr3Fvax+gML+1j9gZJcq9s9c3Iybf2we+GXRFrOJ6j9Md8UYSf1qtc9QL8kcrPC+DcX9t6KSdZ+oEbBu9m/O2Bk7dujpNZ+oOvbdj35d5fZ3YvcXJ/Wtgvz3VoRdStxd+Xiu8cx+pt3hjrH5wd9fS3S6w9c1O1KQ/cu6k2Jt6/HzQFF67tGdnPhX9ut7Xf3eswfaGTbk7m5BPH+gXWzEt70B8bQTesPpMRdOd3NlLgr/LydEndlubdT4vZI7jb53VyW201ev59X9Sfy6vZkfqTJ36zIt12l4s2KfBvbldOyqECsvayG32o8zzwfE49SX2vslm65synhb44iX+HLQ+31Ucx/6FFIdvwW+TBY9SUN+b5G9k29r3HNQuV125jbpz+hX03e06B0/Pl99BMa/U2NQhdya+9qUNLf7fvn8rbG4Fzm/LbG9cvsSxrX3uzrKMcnDSvfjdr9UShjLZto2c2PuncU9QdWn7X9Mlq3Vp/datycnGS7laduTk76gsbLyUlfuKive0PksVtz5ubsJHnslovRkc9J/bAU7pdEZvbM6mz6pohle/+wu/qXREbJudLjw2Dt10TybfkpUt8Teb7wU8lrYyMy98UEtyZ+fU3G3jylmstQzto2F3c3X+oLp/QVmdcJYd+1eWsy291O2stw16dO2ufJ7ObU3ZzLJp5HX/fk35nM9tQY3//YlMd+2tSdr82nhn3/c/P5/fQDO1395lhufnAe33Lf/eJ8qtTvfnLuNe5+c/7mfL6/1ZMUtgArrb6Onu3cqWdUsN6HjJejPk+ZbZKkP/55VS5jrr/K2PejcDeOdT8Kd+NYd6Ow7gcpGUIe25Z//9Je6vO/doeErT+ePMu7MkrWf+aH/lpm9xLXsoOwXcZd/osbvRt4EXpcyk7jB9L+T6z3J4/vL/j31JCfSLXtR1Jt+4FU234k1bYfSLVfavj1vYHtSh3i5Zvyl4y9261KJml/Xi6tfI6/tp+pmi2lXivfPots1/zTXPyj6vUj+0siI8tB6rzMf/iiSBaUf0ck43gvsr2wLa9Jaf1dEc128vwk6++KZBiXUepPiOgrkbs1lmPzjt93k2SMwjy7fFT+8szZ7Vv17DXNPqF57bls9oVDWeuQxOf6dVfvXw9lW431A1UyjekL13UZf7mwu6EtkcF+AjIvFYO9fElmUiou8/py8YvMrmuHdl/HpexHPz+Od2vP3S+Ye+rs6llvVsw9VXYjVDdL5n6jcrNm7jdndLNo7rf32vgstEvnwS/3ejvWlUuUfCghr/NLh2KNZmeXd69fD2XXg2BqjJmNx3wd1EN/IKh/dzS+QMx5NNelIH+V2RUU5IR6ketQT709/aNbTpTWx6XRrSK8/+f5X3/657/8/Z/++i///Kd/+8u//O1f1x9KXSWHT19pAT1AA8aC54HLDLDV0fRsUuURIAueF6GUBc+/KjWgBfQADVjKazJVmQF2Qn0ESEAJqAEtoAdoQCjXUK6h3EK5hXJbyus51GrAUl5rh7UeoAHDq1eesJTXXmVtKa9hmL6UVzl5X8prn6teApbymrDVW8BSXs+DrgFLeU316HM1lTXvr1uQPpIkqTg95bUmtaSepE5PZR1J7rG+pdQ9VgMejyQ579CI2zkOh+e1GS3JHdZaEsMdVmMZ7rC+W8dMsqDpDktvSpKfxfr2mO6xqsOme6x7M91jFRVNzX8b+W/usd4kp3usLnVzj5V9TZLcY90+q0ktyT3WMKy5x7qpNpLcwx/X//dPf//Ln/7HX/+8QmcF17//7Z8jkp7/+W//7/+J/+d//P0vf/3rX/73P/2fv//LP//5f/773/+8os4D7nH+z38f6y1uPMbj/3nG0/rvNS1ldCnP/67rv5957Y/PIYqx/v/1B20+P7ye/zPXP/hfPL8Dnr/RHiu0xaN5/d7zz563Yv1byX8r7Y/F1j9V/mn8sfpvNf6p/7G6WM9/en6dFln/pOuf1nE9o72VOKbn3ei6/u+BiPyxPP9pJZz/Dw==", - "brillig_names": [ - "discover_new_messages", - "get_public_keys_and_partial_address", - "decompose_hint", - "lte_hint", - "get_key_validation_request", - "notify_created_nullifier_oracle_wrapper", - "store_in_execution_cache_oracle_wrapper", - "notify_enqueued_public_function_call_wrapper", - "directive_invert" - ], - "verification_key": "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\nPa5YgJ+q7saoanj0s7xh8Z1ucGk1m79H5/kH" - }, - { - "name": "constructor", - "is_unconstrained": true, - "custom_attributes": [ - "public", - "initializer" - ], - "abi": { - "parameters": [ - { - "name": "admin", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - }, - "visibility": "private" - } - ], - "return_type": null, - "error_types": { - "2233873454491509486": { - "error_kind": "string", - "string": "Initializer address is not the contract deployer" - }, - "2236649814169388962": { - "error_kind": "string", - "string": "PublicImmutable already initialized" - }, - "5019202896831570965": { - "error_kind": "string", - "string": "attempt to add with overflow" - }, - "14225679739041873922": { - "error_kind": "string", - "string": "Index out of bounds" - }, - "17618083556256589634": { - "error_kind": "string", - "string": "Initialization hash does not match" - }, - "17843811134343075018": { - "error_kind": "string", - "string": "Stack too deep" - } - } - }, - "bytecode": "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", - "debug_symbols": "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", - "brillig_names": [ - "constructor" - ] - }, - { - "name": "end_vote", - "is_unconstrained": true, - "custom_attributes": [ - "public" - ], - "abi": { - "parameters": [], - "return_type": null, - "error_types": { - "8095637994846897154": { - "error_kind": "string", - "string": "Only admin can end votes" - }, - "13699457482007836410": { - "error_kind": "string", - "string": "Not initialized" - }, - "17843811134343075018": { - "error_kind": "string", - "string": "Stack too deep" - } - } - }, - "bytecode": "JwACBAEoAAABBIBEJwAABAMnAgEEACcCAgQAHwoAAQACgEQlAAAAPyUAAABAKAIAAQSARCcCAgQAOw4AAgABJiUAAACXHgIAAQAeAgACADMqAAEAAgADJwIBAQEkAgADAAAAaSUAAADAJwIBAAEvCgABAAIeAgADAQoqAgMEJAIABAAAAIslAAAA0icCAgADMAoAAQACJigAgAQEeAANAAAAgASAAyQAgAMAAAC/KgEAAQX3ofOvpa3UyjwEAgEmKgEAAQW+Hj//PqT2+jwEAgEmKgEAAQVwWXvdIQFEAjwEAgEm", - "debug_symbols": "tZXdbrMwDIbvJcccxM6vuZWpqmhLJyREKwaf9Kni3udsJIVKycGmnTQONE/92m+dh7i0p/n92A3X24eo3x7iNHZ9370f+9u5mbrbwE8fQoYPS6LWlXBa1I4X3oGshHe8QiUIv1eQMgaGA8sByBhYDogDBFGjDIFdA6VjwFw0HOjwxCxLJWIqx2ls25DJJjfO+N6M7TCJepj7vhL/mn7++tLHvRm+1qkZ+S2z2+HCKwOvXd+GaKmep2X+KChF8Tgow0lFBJkdAwoMiRgRUuOTgDsC5gmapFsJmsAmgt3rUHmC19qvBK+tzhGKKoiiCgDKqTC/VmH/VoXxqRc+2wtfIBgXVYBVKpcD5QlklF4JxLBfqgDMqij5mnyyNZFPBPOSQ8GUANqkJNzzvwXcmB2jYEvnVUzDeQPZUugCwmL0pbPWZxGmqIRUkmIwa81CQVHK2FSUm5a8FtTlEUamnnCYV1IwJ9cw9sQbJX+gY2MM1mFyOoqVoJgDbgfFCwFL/tYSYj80uqy1sGBPjz5OXTZZdlZgaWhKn6oJKusK1CVrWZmGP6e/nxcH3jXnbtzduEugjV1z6tt1e52H8+bt9P8e38Qb+z7ezu1lHttAel7b4fZ9Q18pdQhXMG+UqxQdlvDTnw==", - "brillig_names": [ - "end_vote" - ] - }, - { - "name": "get_vote", - "is_unconstrained": true, - "custom_attributes": [ - "utility" - ], - "abi": { - "parameters": [ - { - "name": "candidate", - "type": { - "kind": "field" - }, - "visibility": "private" - } - ], - "return_type": { - "abi_type": { - "kind": "field" - }, - "visibility": "public" - }, - "error_types": { - "206160798890201757": { - "error_kind": "string", - "string": "Storage slot 0 not allowed. Storage slots must start from 1." - }, - "576755928210959028": { - "error_kind": "string", - "string": "0 has a square root; you cannot claim it is not square" - }, - "2709101749560550278": { - "error_kind": "string", - "string": "Cannot serialize point at infinity as bytes." - }, - "2896122431943215824": { - "error_kind": "fmtstring", - "length": 144, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "2920182694213909827": { - "error_kind": "string", - "string": "attempt to subtract with overflow" - }, - "3305101268118424981": { - "error_kind": "string", - "string": "Attempted to delete past the length of a CapsuleArray" - }, - "3367683922240523006": { - "error_kind": "fmtstring", - "length": 58, - "item_types": [ - { - "kind": "field" - } - ] - }, - "5019202896831570965": { - "error_kind": "string", - "string": "attempt to add with overflow" - }, - "5727012404371710682": { - "error_kind": "string", - "string": "push out of bounds" - }, - "5870202753060865374": { - "error_kind": "fmtstring", - "length": 61, - "item_types": [ - { - "kind": "field" - }, - { - "kind": "field" - } - ] - }, - "6336853191198150230": { - "error_kind": "fmtstring", - "length": 77, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "6485997221020871071": { - "error_kind": "string", - "string": "call to assert_max_bit_size" - }, - "6753155520859132764": { - "error_kind": "string", - "string": "Failed to deliver note" - }, - "7233212735005103307": { - "error_kind": "string", - "string": "attempt to multiply with overflow" - }, - "8270195893599566439": { - "error_kind": "string", - "string": "Invalid public keys hint for address" - }, - "8830323656616886390": { - "error_kind": "string", - "string": "Got a public log emitted by a different contract" - }, - "12822839658937144934": { - "error_kind": "fmtstring", - "length": 75, - "item_types": [] - }, - "13649294680379557736": { - "error_kind": "string", - "string": "extend_from_bounded_vec out of bounds" - }, - "14225679739041873922": { - "error_kind": "string", - "string": "Index out of bounds" - }, - "14514982005979867414": { - "error_kind": "string", - "string": "attempt to bit-shift with overflow" - }, - "14657895983200220173": { - "error_kind": "string", - "string": "Attempted to read past the length of a CapsuleArray" - }, - "15366650908120444287": { - "error_kind": "fmtstring", - "length": 48, - "item_types": [ - { - "kind": "field" - }, - { - "kind": "field" - } - ] - }, - "16218014537381711836": { - "error_kind": "string", - "string": "Value does not fit in field" - }, - "16446004518090376065": { - "error_kind": "string", - "string": "Input length must be a multiple of 32" - }, - "16954218183513903507": { - "error_kind": "string", - "string": "Attempted to read past end of BoundedVec" - }, - "17843811134343075018": { - "error_kind": "string", - "string": "Stack too deep" - }, - "17879506016437779469": { - "error_kind": "fmtstring", - "length": 128, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "18194595712952743247": { - "error_kind": "fmtstring", - "length": 98, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - }, - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - }, - { - "kind": "field" - } - ] - } - } - }, - "bytecode": "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", - "debug_symbols": "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fLYgKWpFWtSLrMiLRtEsWkmrHKscqxyrHKscqxyrHKscqxwrHTGp6CIpakVa1IusyItG0Swqh5RDyiHlkHJIOaQcUg4ph5RDytHK0crRytHK0crRytHK0crRytHKoeXQcmg5tBxaDi2HlkPLoeXQcvRy9HL0cvRy9HL0cvRy9HL0cvRyWDmsHFYOK4eVw8ph5bByWDmsHF4OL4eXw8vh5fByeDm8HF4OL8coR+S5BrUiLepFVuRFo2gWraTI85PKMcsxyzHLMcsxyzHLMcsxy7HKscqxyrHKscqxyrHKscqxyrHSEROXLpKiVqRFvciKvGgUzaJySDmkHFIOKYeUQ8oh5ZBySDmkHK0crRytHK0crRytHK0crRytHK0cWg4th5ZDy6Hl0HJoObQcWg4tRy9HL0cvRy9HL0cvR+T5CBpFs+juWMdvVEx1ukiKWpEW9SIr8qJRNIvK4eXwcng5vBxeDi+Hl8PL4eXwcoxyjHKMcoxyjHKMcoxyjHKMcoxyzHLMcsxyzHLMcsxyzHLMcsxyzHKscqxyrHKscqxyrHKscqxyrHKsdMTkqIukqBVpUS+yIi8aRbOoHFIOKYeUQ8oh5ZBySDmkHFIOKUcrRytHK0crRytHK0crRytHK0crh5ZDy6Hl0HJoObQcWg4th5ZDy9HL0cvRy9HL0cvRy9HL0cvRy1F5bpXnVnluledWeW6V51Z5bpXnVnluledWeW6V51Z5bpXnVnluledWeW6V51Z5bpXnVnluledWeW6V51Z5bpXnVnluledWeW6V51Z5bpXnVnluledWeW6V51Z5bpXnVnluledWeW6V51Z5bpXnVnluledWeW6V51Z5bpXnVnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V5155PirPR+X5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", - "brillig_names": [ - "get_vote" - ] - }, - { - "name": "public_dispatch", - "is_unconstrained": true, - "custom_attributes": [ - "public" - ], - "abi": { - "parameters": [ - { - "name": "selector", - "type": { - "kind": "field" - }, - "visibility": "private" - } - ], - "return_type": null, - "error_types": { - "206160798890201757": { - "error_kind": "string", - "string": "Storage slot 0 not allowed. Storage slots must start from 1." - }, - "2024020833944022298": { - "error_kind": "string", - "string": "Function add_to_tally_public can only be called internally" - }, - "2233873454491509486": { - "error_kind": "string", - "string": "Initializer address is not the contract deployer" - }, - "2236649814169388962": { - "error_kind": "string", - "string": "PublicImmutable already initialized" - }, - "2830029349304997821": { - "error_kind": "fmtstring", - "length": 27, - "item_types": [ - { - "kind": "field" - } - ] - }, - "3557153117338734214": { - "error_kind": "string", - "string": "Vote has ended" - }, - "5019202896831570965": { - "error_kind": "string", - "string": "attempt to add with overflow" - }, - "8095637994846897154": { - "error_kind": "string", - "string": "Only admin can end votes" - }, - "13699457482007836410": { - "error_kind": "string", - "string": "Not initialized" - }, - "14225679739041873922": { - "error_kind": "string", - "string": "Index out of bounds" - }, - "17618083556256589634": { - "error_kind": "string", - "string": "Initialization hash does not match" - }, - "17843811134343075018": { - "error_kind": "string", - "string": "Stack too deep" - } - } - }, - "bytecode": "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", - "debug_symbols": "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", - "brillig_names": [ - "public_dispatch" - ] - }, - { - "name": "sync_private_state", - "is_unconstrained": true, - "custom_attributes": [ - "utility" - ], - "abi": { - "parameters": [], - "return_type": null, - "error_types": { - "576755928210959028": { - "error_kind": "string", - "string": "0 has a square root; you cannot claim it is not square" - }, - "2709101749560550278": { - "error_kind": "string", - "string": "Cannot serialize point at infinity as bytes." - }, - "2896122431943215824": { - "error_kind": "fmtstring", - "length": 144, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "2920182694213909827": { - "error_kind": "string", - "string": "attempt to subtract with overflow" - }, - "3305101268118424981": { - "error_kind": "string", - "string": "Attempted to delete past the length of a CapsuleArray" - }, - "3367683922240523006": { - "error_kind": "fmtstring", - "length": 58, - "item_types": [ - { - "kind": "field" - } - ] - }, - "5019202896831570965": { - "error_kind": "string", - "string": "attempt to add with overflow" - }, - "5727012404371710682": { - "error_kind": "string", - "string": "push out of bounds" - }, - "5870202753060865374": { - "error_kind": "fmtstring", - "length": 61, - "item_types": [ - { - "kind": "field" - }, - { - "kind": "field" - } - ] - }, - "6336853191198150230": { - "error_kind": "fmtstring", - "length": 77, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "6485997221020871071": { - "error_kind": "string", - "string": "call to assert_max_bit_size" - }, - "6753155520859132764": { - "error_kind": "string", - "string": "Failed to deliver note" - }, - "7233212735005103307": { - "error_kind": "string", - "string": "attempt to multiply with overflow" - }, - "8270195893599566439": { - "error_kind": "string", - "string": "Invalid public keys hint for address" - }, - "8830323656616886390": { - "error_kind": "string", - "string": "Got a public log emitted by a different contract" - }, - "12822839658937144934": { - "error_kind": "fmtstring", - "length": 75, - "item_types": [] - }, - "13649294680379557736": { - "error_kind": "string", - "string": "extend_from_bounded_vec out of bounds" - }, - "14225679739041873922": { - "error_kind": "string", - "string": "Index out of bounds" - }, - "14514982005979867414": { - "error_kind": "string", - "string": "attempt to bit-shift with overflow" - }, - "14657895983200220173": { - "error_kind": "string", - "string": "Attempted to read past the length of a CapsuleArray" - }, - "15366650908120444287": { - "error_kind": "fmtstring", - "length": 48, - "item_types": [ - { - "kind": "field" - }, - { - "kind": "field" - } - ] - }, - "16218014537381711836": { - "error_kind": "string", - "string": "Value does not fit in field" - }, - "16446004518090376065": { - "error_kind": "string", - "string": "Input length must be a multiple of 32" - }, - "16954218183513903507": { - "error_kind": "string", - "string": "Attempted to read past end of BoundedVec" - }, - "17843811134343075018": { - "error_kind": "string", - "string": "Stack too deep" - }, - "17879506016437779469": { - "error_kind": "fmtstring", - "length": 128, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "18194595712952743247": { - "error_kind": "fmtstring", - "length": 98, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - }, - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - }, - { - "kind": "field" - } - ] - } - } - }, - "bytecode": "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", - "debug_symbols": "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RjmOPJ8taBatpCPPL5KiVqRFvciKvKgcsxyzHKscqxyrHKscqxyrHKscqxyrHCsdManoIilqRVrUi6zIi0bRLCqHlEPKIeWQckg5pBxSDimHlEPK0crRytHK0crRytHK0crRytHK0cqh5dByaDm0HFoOLYeWQ8uh5dBy9HL0cvRy9HL0cvRy9HL0cvRy9HJYOawcVg4rh5XDymHlsHJYOawcXg4vh5fDy+Hl8HJ4ObwckecatJIiz0+SolakRb3IirxoFJVjlGOWY5ZjlmOWY5ZjlmOWY5ZjlmOWY5VjlWOVY5VjlWOVY5VjlWOVY6UjJi5dJEWtSIt6kRV50SiaReWQckg5pBxSDimHlEPKIeWQckg5WjlaOVo5WjlaOVo5WjlaOVo5Wjm0HFoOLYeWQ8uh5dByaDm0HFqOXo5ejl6OyPMR1Ius6O5Yt6BRNItW0pHnF0lRK9KiXmRF5bByWDmsHF4OL4eXw8vh5fByeDm8HF4OL8coxyjHKMcoxyjHKMcoxyjHKMcoxyzHLMcsxyzHLMcsxyzHLMcsxyzHKscqxyrHKscqxyrHKscqxyrHSkdMjrpIilqRFvUiK/KiUTSLyiHlkHJIOaQcUg4ph5RDyiHlkHK0crRytHK0crRytHK0crRytHK0cmg5tBxaDi2HlkPLoeXQcmg5tBy9HL0cvRy9HL0cvRyV51Z5bpXnVnluledWeW6V51Z5bpXnVnluledWeW6V51Z5bpXnVnluledWeW6V51Z5bpXnVnluledWeW6V51Z5bpXnVnluledWeW6V51Z5bpXnVnluledWeW6V51Z5bpXnVnluledWeW6V51Z5bpXnVnluledWeW6V51Z5bpXnVnluledWee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V51557pXnXnnuledeee6V5155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", - "brillig_names": [ - "sync_private_state" - ] - } - ], - "outputs": { - "globals": { - "notes": [ - { - "fields": [ - { - "kind": "integer", - "sign": false, - "value": "0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "kind": "string", - "value": "ValueNote" - }, - { - "fields": [ - { - "name": "value", - "value": { - "fields": [ - { - "name": "index", - "value": { - "kind": "integer", - "sign": false, - "value": "0000000000000000000000000000000000000000000000000000000000000000" - } - }, - { - "name": "nullable", - "value": { - "kind": "boolean", - "value": false - } - } - ], - "kind": "struct" - } - }, - { - "name": "owner", - "value": { - "fields": [ - { - "name": "index", - "value": { - "kind": "integer", - "sign": false, - "value": "0000000000000000000000000000000000000000000000000000000000000001" - } - }, - { - "name": "nullable", - "value": { - "kind": "boolean", - "value": false - } - } - ], - "kind": "struct" - } - }, - { - "name": "randomness", - "value": { - "fields": [ - { - "name": "index", - "value": { - "kind": "integer", - "sign": false, - "value": "0000000000000000000000000000000000000000000000000000000000000002" - } - }, - { - "name": "nullable", - "value": { - "kind": "boolean", - "value": false - } - } - ], - "kind": "struct" - } - } - ], - "kind": "struct" - } - ], - "kind": "tuple" - } - ], - "storage": [ - { - "fields": [ - { - "name": "contract_name", - "value": { - "kind": "string", - "value": "EasyPrivateVoting" - } - }, - { - "name": "fields", - "value": { - "fields": [ - { - "name": "admin", - "value": { - "fields": [ - { - "name": "slot", - "value": { - "kind": "integer", - "sign": false, - "value": "0000000000000000000000000000000000000000000000000000000000000001" - } - } - ], - "kind": "struct" - } - }, - { - "name": "tally", - "value": { - "fields": [ - { - "name": "slot", - "value": { - "kind": "integer", - "sign": false, - "value": "0000000000000000000000000000000000000000000000000000000000000002" - } - } - ], - "kind": "struct" - } - }, - { - "name": "vote_ended", - "value": { - "fields": [ - { - "name": "slot", - "value": { - "kind": "integer", - "sign": false, - "value": "0000000000000000000000000000000000000000000000000000000000000003" - } - } - ], - "kind": "struct" - } - }, - { - "name": "active_at_block", - "value": { - "fields": [ - { - "name": "slot", - "value": { - "kind": "integer", - "sign": false, - "value": "0000000000000000000000000000000000000000000000000000000000000004" - } - } - ], - "kind": "struct" - } - } - ], - "kind": "struct" - } - } - ], - "kind": "struct" - } - ] - }, - "structs": { - "functions": [ - { - "fields": [ - { - "name": "parameters", - "type": { - "fields": [ - { - "name": "candidate", - "type": { - "kind": "field" - } - } - ], - "kind": "struct", - "path": "EasyPrivateVoting::add_to_tally_public_parameters" - } - } - ], - "kind": "struct", - "path": "EasyPrivateVoting::add_to_tally_public_abi" - }, - { - "fields": [ - { - "name": "parameters", - "type": { - "fields": [ - { - "name": "candidate", - "type": { - "kind": "field" - } - } - ], - "kind": "struct", - "path": "EasyPrivateVoting::cast_vote_parameters" - } - } - ], - "kind": "struct", - "path": "EasyPrivateVoting::cast_vote_abi" - }, - { - "fields": [ - { - "name": "parameters", - "type": { - "fields": [ - { - "name": "admin", - "type": { - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ], - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress" - } - } - ], - "kind": "struct", - "path": "EasyPrivateVoting::constructor_parameters" - } - } - ], - "kind": "struct", - "path": "EasyPrivateVoting::constructor_abi" - }, - { - "fields": [ - { - "name": "parameters", - "type": { - "fields": [], - "kind": "struct", - "path": "EasyPrivateVoting::end_vote_parameters" - } - } - ], - "kind": "struct", - "path": "EasyPrivateVoting::end_vote_abi" - }, - { - "fields": [ - { - "name": "parameters", - "type": { - "fields": [ - { - "name": "candidate", - "type": { - "kind": "field" - } - } - ], - "kind": "struct", - "path": "EasyPrivateVoting::get_vote_parameters" - } - }, - { - "name": "return_type", - "type": { - "kind": "field" - } - } - ], - "kind": "struct", - "path": "EasyPrivateVoting::get_vote_abi" - }, - { - "fields": [ - { - "name": "parameters", - "type": { - "fields": [], - "kind": "struct", - "path": "EasyPrivateVoting::sync_private_state_parameters" - } - } - ], - "kind": "struct", - "path": "EasyPrivateVoting::sync_private_state_abi" - } - ] - } - }, - "file_map": { - "100": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/messages/discovery/mod.nr", - "source": "use protocol_types::{address::AztecAddress, debug_log::debug_log};\n\npub mod nonce_discovery;\npub mod partial_notes;\npub mod pending_tagged_log;\npub mod private_logs;\npub mod private_notes;\n\nuse private_notes::MAX_NOTE_PACKED_LEN;\n\npub struct NoteHashAndNullifier {\n /// The result of NoteHash::compute_note_hash\n pub note_hash: Field,\n /// The result of NoteHash::compute_nullifier_unconstrained (since all of message discovery is unconstrained)\n pub inner_nullifier: Field,\n}\n\n/// A function which takes a note's packed content, address of the emitting contract, nonce, storage slot and note type\n/// ID and attempts to compute its note hash (not siloed by nonce nor address) and inner nullifier (not siloed by\n/// address).\n///\n/// This function must be user-provided as its implementation requires knowledge of how note type IDs are allocated in a\n/// contract. The `#[aztec]` macro automatically creates such a contract library method called\n/// `_compute_note_hash_and_nullifier`, which looks something like this:\n///\n/// ```\n/// |packed_note, contract_address, nonce, storage_slot, note_type_id| {\n/// if note_type_id == MyNoteType::get_id() {\n/// assert(packed_note.len() == MY_NOTE_TYPE_SERIALIZATION_LENGTH);\n///\n/// let note = MyNoteType::unpack(aztec::utils::array::subarray(packed_note.storage(), 0));\n///\n/// let note_hash = note.compute_note_hash(storage_slot);\n/// let note_hash_for_nullify = aztec::note::utils::compute_note_hash_for_nullify(\n/// RetrievedNote{ note, contract_address, metadata: SettledNoteMetadata::new(nonce).into() },\n/// storage_slot\n/// );\n///\n/// let inner_nullifier = note.compute_nullifier_unconstrained(note_hash_for_nullify);\n///\n/// Option::some(\n/// aztec::messages::discovery::NoteHashAndNullifier {\n/// note_hash, inner_nullifier\n/// }\n/// )\n/// } else if note_type_id == MyOtherNoteType::get_id() {\n/// ... // Similar to above but calling MyOtherNoteType::unpack_content\n/// } else {\n/// Option::none() // Unknown note type ID\n/// };\n/// }\n/// ```\ntype ComputeNoteHashAndNullifier = unconstrained fn[Env](/* packed_note */BoundedVec, /* storage_slot */ Field, /* note_type_id */ Field, /* contract_address */ AztecAddress, /* nonce */ Field) -> Option;\n\n/// Performs the message discovery process, in which private are downloaded and inspected to find new private notes,\n/// partial notes and events, etc., and pending partial notes are processed to search for their completion logs.\n/// This is the mechanism via which a contract updates its knowledge of its private state.\n///\n/// Receives the address of the contract on which discovery is performed along with its\n/// `compute_note_hash_and_nullifier` function.\npub unconstrained fn discover_new_messages(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n) {\n debug_log(\"Performing message discovery\");\n\n private_logs::fetch_and_process_private_tagged_logs(\n contract_address,\n compute_note_hash_and_nullifier,\n );\n\n partial_notes::fetch_and_process_public_partial_note_completion_logs(\n contract_address,\n compute_note_hash_and_nullifier,\n );\n}\n" - }, - "101": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/messages/discovery/nonce_discovery.nr", - "source": "use crate::messages::discovery::{ComputeNoteHashAndNullifier, private_notes::MAX_NOTE_PACKED_LEN};\n\nuse dep::protocol_types::{\n address::AztecAddress,\n constants::MAX_NOTE_HASHES_PER_TX,\n debug_log::debug_log_format,\n hash::{compute_note_hash_nonce, compute_siloed_note_hash, compute_unique_note_hash},\n traits::ToField,\n};\n\n/// A struct with the discovered information of a complete note, required for delivery to PXE. Note that this is *not*\n/// the complete note information, since it does not include content, storage slot, etc.\npub struct DiscoveredNoteInfo {\n pub nonce: Field,\n pub note_hash: Field,\n pub inner_nullifier: Field,\n}\n\n/// Searches for note nonces that will result in a note that was emitted in a transaction. While rare, it is possible\n/// for multiple notes to have the exact same packed content and storage slot but different nonces, resulting in\n/// different unique note hashes. Because of this this function returns a *vector* of discovered notes, though in most\n/// cases it will contain a single element.\n///\n/// Due to how nonces are computed, this function requires knowledge of the transaction in which the note was created,\n/// more specifically the list of all unique note hashes in it plus the value of its first nullifier.\npub unconstrained fn attempt_note_nonce_discovery(\n unique_note_hashes_in_tx: BoundedVec,\n first_nullifier_in_tx: Field,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n packed_note: BoundedVec,\n) -> BoundedVec {\n let discovered_notes = &mut BoundedVec::new();\n\n debug_log_format(\n \"Attempting nonce discovery on {0} potential notes on contract {1} for storage slot {2}\",\n [unique_note_hashes_in_tx.len() as Field, contract_address.to_field(), storage_slot],\n );\n\n // We need to find nonces (typically just one) that result in a note hash that, once siloed into a unique note hash,\n // is one of the note hashes created by the transaction.\n unique_note_hashes_in_tx.for_eachi(|i, expected_unique_note_hash| {\n // Nonces are computed by hashing the first nullifier in the transaction with the index of the note in the\n // new note hashes array. We therefore know for each note in every transaction what its nonce is.\n let candidate_nonce = compute_note_hash_nonce(first_nullifier_in_tx, i);\n\n // Given nonce, note content and metadata, we can compute the note hash and silo it to check if it matches\n // the note hash at the array index we're currently processing.\n // TODO(#11157): handle failed note_hash_and_nullifier computation\n let hashes = compute_note_hash_and_nullifier(\n packed_note,\n storage_slot,\n note_type_id,\n contract_address,\n candidate_nonce,\n )\n .expect(f\"Failed to compute a note hash for note type {note_type_id}\");\n\n let siloed_note_hash = compute_siloed_note_hash(contract_address, hashes.note_hash);\n let unique_note_hash = compute_unique_note_hash(candidate_nonce, siloed_note_hash);\n\n if unique_note_hash == expected_unique_note_hash {\n // Note that while we did check that the note hash is the preimage of the expected unique note hash, we\n // perform no validations on the nullifier - we fundamentally cannot, since only the application knows\n // how to compute nullifiers. We simply trust it to have provided the correct one: if it hasn't, then\n // PXE may fail to realize that a given note has been nullified already, and calls to the application\n // could result in invalid transactions (with duplicate nullifiers). This is not a concern because an\n // application already has more direct means of making a call to it fail the transaction.\n discovered_notes.push(\n DiscoveredNoteInfo {\n nonce: candidate_nonce,\n note_hash: hashes.note_hash,\n inner_nullifier: hashes.inner_nullifier,\n },\n );\n\n // We don't exit the loop - it is possible (though rare) for the exact same note content to be present\n // multiple times in the same transaction with different nonces. This typically doesn't happen due to\n // notes containing random values in order to hide their contents.\n }\n });\n\n debug_log_format(\n \"Discovered a total of {0} notes\",\n [discovered_notes.len() as Field],\n );\n\n *discovered_notes\n}\n\nmod test {\n use crate::{\n messages::discovery::{NoteHashAndNullifier, private_notes::MAX_NOTE_PACKED_LEN},\n note::{\n note_interface::{NoteHash, NoteType},\n note_metadata::SettledNoteMetadata,\n retrieved_note::RetrievedNote,\n utils::compute_note_hash_for_nullify,\n },\n oracle::random::random,\n test::mocks::mock_note::MockNote,\n utils::array,\n };\n\n use dep::protocol_types::{\n address::AztecAddress,\n hash::{compute_note_hash_nonce, compute_siloed_note_hash, compute_unique_note_hash},\n traits::{FromField, Packable},\n };\n\n use super::attempt_note_nonce_discovery;\n\n // This implementation could be simpler, but this serves as a nice example of the expected flow in a real\n // implementation, and as a sanity check that the interface is sufficient.\n unconstrained fn compute_note_hash_and_nullifier(\n packed_note: BoundedVec,\n storage_slot: Field,\n note_type_id: Field,\n contract_address: AztecAddress,\n nonce: Field,\n ) -> Option {\n if note_type_id == MockNote::get_id() {\n let note = MockNote::unpack(array::subarray(packed_note.storage(), 0));\n let note_hash = note.compute_note_hash(storage_slot);\n\n let note_hash_for_nullify = compute_note_hash_for_nullify(\n RetrievedNote {\n note,\n contract_address,\n metadata: SettledNoteMetadata::new(nonce).into(),\n },\n storage_slot,\n );\n\n let inner_nullifier = note.compute_nullifier_unconstrained(note_hash_for_nullify);\n\n Option::some(NoteHashAndNullifier { note_hash, inner_nullifier })\n } else {\n Option::none()\n }\n }\n\n global VALUE: Field = 7;\n global FIRST_NULLIFIER_IN_TX: Field = 47;\n global CONTRACT_ADDRESS: AztecAddress = AztecAddress::from_field(13);\n global STORAGE_SLOT: Field = 99;\n\n #[test]\n unconstrained fn no_note_hashes() {\n let unique_note_hashes_in_tx = BoundedVec::new();\n let packed_note = BoundedVec::new();\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n MockNote::get_id(),\n packed_note,\n );\n\n assert_eq(discovered_notes.len(), 0);\n }\n\n #[test(should_fail_with = \"Failed to compute a note hash\")]\n unconstrained fn failed_hash_computation() {\n let unique_note_hashes_in_tx = BoundedVec::from_array([random()]);\n let packed_note = BoundedVec::new();\n let note_type_id = 0; // This note type id is unknown to compute_note_hash_and_nullifier\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n note_type_id,\n packed_note,\n );\n\n assert_eq(discovered_notes.len(), 0);\n }\n\n struct NoteAndData {\n note: MockNote,\n nonce: Field,\n note_hash: Field,\n unique_note_hash: Field,\n inner_nullifier: Field,\n }\n\n unconstrained fn construct_note(value: Field, note_index_in_tx: u32) -> NoteAndData {\n let nonce = compute_note_hash_nonce(FIRST_NULLIFIER_IN_TX, note_index_in_tx);\n\n let retrieved_note = MockNote::new(value)\n .contract_address(CONTRACT_ADDRESS)\n .note_metadata(SettledNoteMetadata::new(nonce).into())\n .build_retrieved_note();\n let note = retrieved_note.note;\n\n let note_hash = note.compute_note_hash(STORAGE_SLOT);\n let unique_note_hash =\n compute_unique_note_hash(nonce, compute_siloed_note_hash(CONTRACT_ADDRESS, note_hash));\n let inner_nullifier = note.compute_nullifier_unconstrained(compute_note_hash_for_nullify(\n retrieved_note,\n STORAGE_SLOT,\n ));\n\n NoteAndData { note, nonce, note_hash, unique_note_hash, inner_nullifier }\n }\n\n #[test]\n unconstrained fn single_note() {\n let note_index_in_tx = 2;\n let note_and_data = construct_note(VALUE, note_index_in_tx);\n\n let mut unique_note_hashes_in_tx = BoundedVec::from_array([\n random(), random(), random(), random(), random(), random(), random(),\n ]);\n unique_note_hashes_in_tx.set(note_index_in_tx, note_and_data.unique_note_hash);\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n MockNote::get_id(),\n BoundedVec::from_array(note_and_data.note.pack()),\n );\n\n assert_eq(discovered_notes.len(), 1);\n let discovered_note = discovered_notes.get(0);\n\n assert_eq(discovered_note.nonce, note_and_data.nonce);\n assert_eq(discovered_note.note_hash, note_and_data.note_hash);\n assert_eq(discovered_note.inner_nullifier, note_and_data.inner_nullifier);\n }\n\n #[test]\n unconstrained fn multiple_notes_same_preimage() {\n let first_note_index_in_tx = 3;\n let first_note_and_data = construct_note(VALUE, first_note_index_in_tx);\n\n let second_note_index_in_tx = 5;\n let second_note_and_data = construct_note(VALUE, second_note_index_in_tx);\n\n // Both notes have the same preimage (and therefore packed representation), so both should be found in the same\n // call.\n assert_eq(first_note_and_data.note, second_note_and_data.note);\n let packed_note = first_note_and_data.note.pack();\n\n let mut unique_note_hashes_in_tx = BoundedVec::from_array([\n random(), random(), random(), random(), random(), random(), random(),\n ]);\n unique_note_hashes_in_tx.set(first_note_index_in_tx, first_note_and_data.unique_note_hash);\n unique_note_hashes_in_tx.set(second_note_index_in_tx, second_note_and_data.unique_note_hash);\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n MockNote::get_id(),\n BoundedVec::from_array(packed_note),\n );\n\n assert_eq(discovered_notes.len(), 2);\n\n assert(discovered_notes.any(|discovered_note| {\n (discovered_note.nonce == first_note_and_data.nonce)\n & (discovered_note.note_hash == first_note_and_data.note_hash)\n & (discovered_note.inner_nullifier == first_note_and_data.inner_nullifier)\n }));\n\n assert(discovered_notes.any(|discovered_note| {\n (discovered_note.nonce == second_note_and_data.nonce)\n & (discovered_note.note_hash == second_note_and_data.note_hash)\n & (discovered_note.inner_nullifier == second_note_and_data.inner_nullifier)\n }));\n }\n}\n" - }, - "102": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr", - "source": "use crate::{\n capsules::CapsuleArray,\n messages::{\n discovery::{ComputeNoteHashAndNullifier, nonce_discovery::attempt_note_nonce_discovery},\n encoding::MAX_MESSAGE_CONTENT_LEN,\n },\n oracle::message_discovery::{deliver_note, get_log_by_tag},\n utils::array,\n};\n\nuse dep::protocol_types::{\n address::AztecAddress,\n constants::PUBLIC_LOG_SIZE_IN_FIELDS,\n debug_log::debug_log_format,\n hash::sha256_to_field,\n traits::{Deserialize, Serialize, ToField},\n};\n\nglobal PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN: u32 = 2;\n\n/// Partial notes have a maximum packed length of their private fields bound by extra content in their private message\n/// (e.g. the storage slot, note completion log tag, etc.).\npub global MAX_PARTIAL_NOTE_PRIVATE_PACKED_LEN: u32 =\n MAX_MESSAGE_CONTENT_LEN - PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN;\n\n/// The slot in the PXE capsules where we store a `CapsuleArray` of `DeliveredPendingPartialNote`.\npub global DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT\".as_bytes(),\n);\n\n/// Public logs contain an extra field at the beginning with the address of the contract that emitted them, and partial\n/// notes emit their completion tag in the log, resulting in the first two fields in the public log not being part of\n/// the packed public content.\n// TODO(#10273): improve how contract log siloing is handled\npub global NON_PACKED_CONTENT_FIELDS_IN_PUBLIC_LOG: u32 = 2;\n\n/// The maximum length of the packed representation of public fields in a partial note. This is limited by public log\n/// size and extra fields in the log (e.g. the tag).\npub global MAX_PUBLIC_PARTIAL_NOTE_PACKED_CONTENT_LENGTH: u32 =\n PUBLIC_LOG_SIZE_IN_FIELDS - NON_PACKED_CONTENT_FIELDS_IN_PUBLIC_LOG;\n\n/// A partial note that was delivered but is still pending completion. Contains the information necessary to find the\n/// log that will complete it and lead to a note being discovered and delivered.\n#[derive(Serialize, Deserialize)]\npub(crate) struct DeliveredPendingPartialNote {\n pub(crate) note_completion_log_tag: Field,\n pub(crate) storage_slot: Field,\n pub(crate) note_type_id: Field,\n pub(crate) packed_private_note_content: BoundedVec,\n pub(crate) recipient: AztecAddress,\n}\n\npub unconstrained fn process_partial_note_private_msg(\n contract_address: AztecAddress,\n recipient: AztecAddress,\n msg_metadata: u64,\n msg_content: BoundedVec,\n) {\n let (note_type_id, storage_slot, note_completion_log_tag, packed_private_note_content) =\n decode_partial_note_private_msg(msg_metadata, msg_content);\n\n // We store the information of the partial note we found in a persistent capsule in PXE, so that we can later search\n // for the public log that will complete it.\n let pending = DeliveredPendingPartialNote {\n note_completion_log_tag,\n storage_slot,\n note_type_id,\n packed_private_note_content,\n recipient,\n };\n\n CapsuleArray::at(\n contract_address,\n DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT,\n )\n .push(pending);\n}\n\n/// Searches for public logs that would result in the completion of pending partial notes, ultimately resulting in the\n/// notes being delivered to PXE if completed.\npub unconstrained fn fetch_and_process_public_partial_note_completion_logs(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n) {\n let pending_partial_notes = CapsuleArray::at(\n contract_address,\n DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT,\n );\n\n debug_log_format(\n \"{} pending partial notes\",\n [pending_partial_notes.len() as Field],\n );\n\n pending_partial_notes.for_each(|i, pending_partial_note: DeliveredPendingPartialNote| {\n let maybe_log = get_log_by_tag(pending_partial_note.note_completion_log_tag);\n if maybe_log.is_none() {\n debug_log_format(\n \"Found no completion logs for partial note with tag {}\",\n [pending_partial_note.note_completion_log_tag],\n );\n\n // Note that we're not removing the pending partial note from the capsule array, so we will continue\n // searching for this tagged log when performing message discovery in the future until we either find it or\n // the entry is somehow removed from the array.\n } else {\n debug_log_format(\n \"Completion log found for partial note with tag {}\",\n [pending_partial_note.note_completion_log_tag],\n );\n let log = maybe_log.unwrap();\n\n // Public logs have an extra field at the beginning with the contract address, which we use to verify\n // that we're getting the logs from the expected contract.\n // TODO(#10273): improve how contract log siloing is handled\n assert_eq(\n log.log_content.get(0),\n contract_address.to_field(),\n \"Got a public log emitted by a different contract\",\n );\n\n // Public fields are assumed to all be placed at the end of the packed representation, so we combine the\n // private and public packed fields (i.e. the contents of the private message and public log sans the extra\n // fields) to get the complete packed content.\n let packed_public_note_content: BoundedVec<_, MAX_PUBLIC_PARTIAL_NOTE_PACKED_CONTENT_LENGTH> =\n array::subbvec(log.log_content, NON_PACKED_CONTENT_FIELDS_IN_PUBLIC_LOG);\n let complete_packed_note = array::append(\n pending_partial_note.packed_private_note_content,\n packed_public_note_content,\n );\n\n let discovered_notes = attempt_note_nonce_discovery(\n log.unique_note_hashes_in_tx,\n log.first_nullifier_in_tx,\n compute_note_hash_and_nullifier,\n contract_address,\n pending_partial_note.storage_slot,\n pending_partial_note.note_type_id,\n complete_packed_note,\n );\n\n debug_log_format(\n \"Discovered {0} notes for partial note with tag {1}\",\n [discovered_notes.len() as Field, pending_partial_note.note_completion_log_tag],\n );\n\n discovered_notes.for_each(|discovered_note| {\n // TODO:(#10728): decide how to handle notes that fail delivery. This could be due to e.g. a\n // temporary node connectivity issue - is simply throwing good enough here?\n assert(\n deliver_note(\n contract_address,\n pending_partial_note.storage_slot,\n discovered_note.nonce,\n complete_packed_note,\n discovered_note.note_hash,\n discovered_note.inner_nullifier,\n log.tx_hash,\n pending_partial_note.recipient,\n ),\n \"Failed to deliver note\",\n );\n });\n\n // Because there is only a single log for a given tag, once we've processed the tagged log then we\n // simply delete the pending work entry, regardless of whether it was actually completed or not.\n // TODO(#11627): only remove the pending entry if we actually process a log that results in the note\n // being completed.\n pending_partial_notes.remove(i);\n }\n });\n}\n\nfn decode_partial_note_private_msg(\n msg_metadata: u64,\n msg_content: BoundedVec,\n) -> (Field, Field, Field, BoundedVec) {\n let note_type_id = msg_metadata as Field; // TODO: make note type id not be a full field\n\n assert(\n msg_content.len() > PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN,\n f\"Invalid private note message: all partial note private messages must have at least {PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN} fields\",\n );\n\n // If PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN is changed, causing the assertion below to fail, then the\n // destructuring of the partial note private message encoding below must be updated as well.\n std::static_assert(\n PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN == 2,\n \"unexpected value for PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN\",\n );\n\n // We currently have two fields that are not the partial note's packed representation, which are the storage slot\n // and the note completion log tag.\n let storage_slot = msg_content.get(0);\n let note_completion_log_tag = msg_content.get(1);\n\n let packed_private_note_content = array::subbvec(msg_content, 2);\n\n (note_type_id, storage_slot, note_completion_log_tag, packed_private_note_content)\n}\n" - }, - "104": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/messages/discovery/private_logs.nr", - "source": "use crate::{\n capsules::CapsuleArray,\n messages::{\n discovery::{\n ComputeNoteHashAndNullifier,\n partial_notes::process_partial_note_private_msg,\n pending_tagged_log::{PENDING_TAGGED_LOG_ARRAY_BASE_SLOT, PendingTaggedLog},\n private_notes::process_private_note_msg,\n },\n encoding::decode_message,\n encryption::{aes128::AES128, log_encryption::LogEncryption},\n msg_type::{\n PARTIAL_NOTE_PRIVATE_MSG_TYPE_ID, PRIVATE_EVENT_MSG_TYPE_ID, PRIVATE_NOTE_MSG_TYPE_ID,\n },\n },\n oracle::{logs::store_private_event_log, message_discovery::fetch_tagged_logs},\n utils::array,\n};\n\nuse protocol_types::{\n abis::event_selector::EventSelector,\n address::AztecAddress,\n debug_log::{debug_log, debug_log_format},\n traits::FromField,\n};\n\n/// Searches for private logs that signal new private notes that are then delivered to PXE, or new partial notes that\n/// are stored in the PXE capsules so that `fetch_and_process_public_partial_note_completion_logs` can later search for\n/// public logs that will complete them.\npub unconstrained fn fetch_and_process_private_tagged_logs(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n) {\n // We will eventually perform log discovery via tagging here, but for now we simply call the `fetchTaggedLogs` oracle.\n // This makes PXE synchronize tags, download logs and store the pending tagged logs in capsule array which are then\n // retrieved and processed here.\n fetch_tagged_logs(PENDING_TAGGED_LOG_ARRAY_BASE_SLOT);\n\n // Get the logs from the capsule array and process them one by one\n let logs =\n CapsuleArray::::at(contract_address, PENDING_TAGGED_LOG_ARRAY_BASE_SLOT);\n logs.for_each(|i, log: PendingTaggedLog| {\n process_log(contract_address, compute_note_hash_and_nullifier, log);\n logs.remove(i);\n });\n}\n\n/// Processes a log's ciphertext by decrypting it and then searching the plaintext for private notes or partial notes.\n///\n/// Private notes result in nonce discovery being performed prior to delivery, which requires knowledge of the\n/// transaction hash in which the notes would've been created (typically the same transaction in which the log was\n/// emitted), along with the list of unique note hashes in said transaction and the `compute_note_hash_and_nullifier`\n/// function.\n///\n/// Partial notes result in a pending partial note entry being stored in a PXE capsule, which will later be retrieved to\n/// search for the note's completion public log.\nunconstrained fn process_log(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n pending_tagged_log: PendingTaggedLog,\n) {\n debug_log_format(\n \"Processing log with tag {0}\",\n [pending_tagged_log.log.get(0)],\n );\n\n // The tag is ignored for now.\n let ciphertext = array::subbvec(pending_tagged_log.log, 1);\n\n let log_plaintext = AES128::decrypt_log(ciphertext, pending_tagged_log.recipient);\n\n // The first thing to do after decrypting the log is to determine what type of private log we're processing. We\n // have 3 log types: private note logs, partial note logs and event logs.\n\n let (msg_type_id, msg_metadata, msg_content) = decode_message(log_plaintext);\n\n if msg_type_id == PRIVATE_NOTE_MSG_TYPE_ID {\n debug_log(\"Processing private note msg\");\n\n process_private_note_msg(\n contract_address,\n pending_tagged_log.tx_hash,\n pending_tagged_log.unique_note_hashes_in_tx,\n pending_tagged_log.first_nullifier_in_tx,\n pending_tagged_log.recipient,\n compute_note_hash_and_nullifier,\n msg_metadata,\n msg_content,\n );\n } else if msg_type_id == PARTIAL_NOTE_PRIVATE_MSG_TYPE_ID {\n debug_log(\"Processing partial note private msg\");\n\n process_partial_note_private_msg(\n contract_address,\n pending_tagged_log.recipient,\n msg_metadata,\n msg_content,\n );\n } else if msg_type_id == PRIVATE_EVENT_MSG_TYPE_ID {\n debug_log(\"Processing private event msg\");\n\n // In the case of events, the msg metadata is the event selector.\n let event_selector = EventSelector::from_field(msg_metadata as Field);\n\n store_private_event_log(\n contract_address,\n pending_tagged_log.recipient,\n event_selector,\n msg_content,\n pending_tagged_log.tx_hash,\n pending_tagged_log.log_index_in_tx,\n pending_tagged_log.tx_index_in_block,\n );\n } else {\n debug_log_format(\"Unknown msg type id {0}\", [msg_type_id as Field]);\n }\n}\n" - }, - "105": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/messages/discovery/private_notes.nr", - "source": "use crate::{\n messages::{\n discovery::{ComputeNoteHashAndNullifier, nonce_discovery::attempt_note_nonce_discovery},\n encoding::MAX_MESSAGE_CONTENT_LEN,\n },\n oracle,\n utils::array,\n};\nuse protocol_types::{\n address::AztecAddress, constants::MAX_NOTE_HASHES_PER_TX, debug_log::debug_log_format,\n};\n\n/// The number of fields in a private note message content that are not the note's packed representation.\nglobal PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN: u32 = 1;\n\n/// The maximum length of the packed representation of a note's contents. This is limited by private log size,\n/// encryption overhead and extra fields in the message (e.g. message type id, storage slot, etc.).\npub global MAX_NOTE_PACKED_LEN: u32 =\n MAX_MESSAGE_CONTENT_LEN - PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN;\n\npub unconstrained fn process_private_note_msg(\n contract_address: AztecAddress,\n tx_hash: Field,\n unique_note_hashes_in_tx: BoundedVec,\n first_nullifier_in_tx: Field,\n recipient: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n msg_metadata: u64,\n msg_content: BoundedVec,\n) {\n let (note_type_id, storage_slot, packed_note) =\n decode_private_note_msg(msg_metadata, msg_content);\n\n attempt_note_discovery(\n contract_address,\n tx_hash,\n unique_note_hashes_in_tx,\n first_nullifier_in_tx,\n recipient,\n compute_note_hash_and_nullifier,\n storage_slot,\n note_type_id,\n packed_note,\n );\n}\n\n/// Attempts discovery of a note given information about its contents and the transaction in which it is\n/// suspected the note was created.\npub unconstrained fn attempt_note_discovery(\n contract_address: AztecAddress,\n tx_hash: Field,\n unique_note_hashes_in_tx: BoundedVec,\n first_nullifier_in_tx: Field,\n recipient: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n storage_slot: Field,\n note_type_id: Field,\n packed_note: BoundedVec,\n) {\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n first_nullifier_in_tx,\n compute_note_hash_and_nullifier,\n contract_address,\n storage_slot,\n note_type_id,\n packed_note,\n );\n\n debug_log_format(\n \"Discovered {0} notes from a private message\",\n [discovered_notes.len() as Field],\n );\n\n discovered_notes.for_each(|discovered_note| {\n // TODO:(#10728): handle notes that fail delivery. This could be due to e.g. a temporary node connectivity\n // issue, and we should perhaps not have marked the tag index as taken.\n assert(\n oracle::message_discovery::deliver_note(\n contract_address,\n storage_slot,\n discovered_note.nonce,\n packed_note,\n discovered_note.note_hash,\n discovered_note.inner_nullifier,\n tx_hash,\n recipient,\n ),\n \"Failed to deliver note\",\n );\n });\n}\n\nfn decode_private_note_msg(\n msg_metadata: u64,\n msg_content: BoundedVec,\n) -> (Field, Field, BoundedVec) {\n let note_type_id = msg_metadata as Field; // TODO: make note type id not be a full field\n\n assert(\n msg_content.len() > PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN,\n f\"Invalid private note message: all private note messages must have at least {PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN} fields\",\n );\n\n // If PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN is changed, causing the assertion below to fail, then the\n // destructuring of the private note message encoding below must be updated as well.\n std::static_assert(\n PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN == 1,\n \"unexpected value for PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN\",\n );\n\n // We currently have a single field that is not the note's packed representation, which is the storage slot.\n let storage_slot = msg_content.get(0);\n let packed_note = array::subbvec(msg_content, PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN);\n\n (note_type_id, storage_slot, packed_note)\n}\n" - }, - "106": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/messages/encoding.nr", - "source": "// TODO(#12750): don't make these values assume we're using AES.\nuse crate::{\n messages::encryption::log_encryption::PRIVATE_LOG_PLAINTEXT_SIZE_IN_FIELDS, utils::array,\n};\n\nglobal MAX_MESSAGE_LEN: u32 = PRIVATE_LOG_PLAINTEXT_SIZE_IN_FIELDS;\n\nglobal MESSAGE_EXPANDED_METADATA_LEN: u32 = 1;\n\n// The standard message layout is composed of:\n// - an initial field called the 'expanded metadata'\n// - an arbitrary number of fields following that called the 'message content'\n//\n// ```\n// message: [ msg_expanded_metadata, ...msg_content ]\n// ```\n//\n// The expanded metadata itself is interpreted as a u128, of which:\n// - the upper 64 bits are the message type id\n// - the lower 64 bits are called the 'message metadata'\n//\n// ```\n// msg_expanded_metadata: [ msg_type_id | msg_metadata ]\n// <--- 64 bits --->|<--- 64 bits --->\n// ```\n//\n// The meaning of the message metadata and message content depend on the value of the message type id. Note that there\n// is nothing special about the message metadata, it _can_ be considered part of the content. It just has a different\n// name to make it distinct from the message content given that it is not a full field.\n\n/// The maximum length of a message's content, i.e. not including the expanded message metadata.\npub global MAX_MESSAGE_CONTENT_LEN: u32 = MAX_MESSAGE_LEN - MESSAGE_EXPANDED_METADATA_LEN;\n\n/// Encodes a message following aztec-nr's standard message encoding. This message can later be decoded with\n/// `decode_message` to retrieve the original values.\n///\n/// - The `msg_type` is an identifier that groups types of messages that are all processed the same way, e.g. private\n/// notes or events. Possible values are defined in `aztec::messages::msg_type`.\n/// - The `msg_metadata` and `msg_content` are the values stored in the message, whose meaning depends on the\n/// `msg_type`. The only special thing about `msg_metadata` that separates it from `msg_content` is that it is a u64\n/// instead of a full Field (due to details of how messages are encoded), allowing applications that can fit values into\n/// this smaller variable to achieve higher data efficiency.\npub fn encode_message(\n msg_type: u64,\n msg_metadata: u64,\n msg_content: [Field; N],\n) -> [Field; (N + MESSAGE_EXPANDED_METADATA_LEN)] {\n std::static_assert(\n msg_content.len() <= MAX_MESSAGE_CONTENT_LEN,\n \"Invalid message content: it must have a length of at most MAX_MESSAGE_CONTENT_LEN\",\n );\n\n // If MESSAGE_EXPANDED_METADATA_LEN is changed, causing the assertion below to fail, then the destructuring of\n // the message encoding below must be updated as well.\n std::static_assert(\n MESSAGE_EXPANDED_METADATA_LEN == 1,\n \"unexpected value for MESSAGE_EXPANDED_METADATA_LEN\",\n );\n let mut message: [Field; (N + MESSAGE_EXPANDED_METADATA_LEN)] = std::mem::zeroed();\n\n message[0] = to_expanded_metadata(msg_type, msg_metadata);\n for i in 0..msg_content.len() {\n message[MESSAGE_EXPANDED_METADATA_LEN + i] = msg_content[i];\n }\n\n message\n}\n\n/// Decodes a standard aztec-nr message, i.e. one created via `encode_message`, returning the original encoded values.\n///\n/// Note that `encode_message` returns a fixed size array while this function takes a `BoundedVec`: this is because\n/// prior to decoding the message type is unknown, and consequentially not known at compile time. If working with\n/// fixed-size messages, consider using `BoundedVec::from_array` to convert them.\npub unconstrained fn decode_message(\n message: BoundedVec,\n) -> (u64, u64, BoundedVec) {\n assert(\n message.len() >= MESSAGE_EXPANDED_METADATA_LEN,\n f\"Invalid message: it must have at least {MESSAGE_EXPANDED_METADATA_LEN} fields\",\n );\n\n // If MESSAGE_EXPANDED_METADATA_LEN is changed, causing the assertion below to fail, then the destructuring of\n // the message encoding below must be updated as well.\n std::static_assert(\n MESSAGE_EXPANDED_METADATA_LEN == 1,\n \"unexpected value for MESSAGE_EXPANDED_METADATA_LEN\",\n );\n\n let msg_expanded_metadata = message.get(0);\n let (msg_type_id, msg_metadata) = from_expanded_metadata(msg_expanded_metadata);\n let msg_content = array::subbvec(message, MESSAGE_EXPANDED_METADATA_LEN);\n\n (msg_type_id, msg_metadata, msg_content)\n}\n\nglobal U64_SHIFT_MULTIPLIER: Field = 2.pow_32(64);\n\nfn to_expanded_metadata(msg_type: u64, msg_metadata: u64) -> Field {\n // We use multiplication instead of bit shifting operations to shift the type bits as bit shift operations are\n // expensive in circuits.\n let type_field: Field = (msg_type as Field) * U64_SHIFT_MULTIPLIER;\n let msg_metadata_field = msg_metadata as Field;\n\n type_field + msg_metadata_field\n}\n\nfn from_expanded_metadata(input: Field) -> (u64, u64) {\n input.assert_max_bit_size::<128>();\n let msg_metadata = (input as u64);\n let msg_type = ((input - (msg_metadata as Field)) / U64_SHIFT_MULTIPLIER) as u64;\n // Use division instead of bit shift since bit shifts are expensive in circuits\n (msg_type, msg_metadata)\n}\n\nmod tests {\n use crate::utils::array::subarray::subarray;\n use super::{\n decode_message, encode_message, from_expanded_metadata, MAX_MESSAGE_CONTENT_LEN,\n to_expanded_metadata,\n };\n\n global U64_MAX: u64 = (2.pow_32(64) - 1) as u64;\n global U128_MAX: Field = (2.pow_32(128) - 1);\n\n #[test]\n unconstrained fn encode_decode_empty_message(msg_type: u64, msg_metadata: u64) {\n let encoded = encode_message(msg_type, msg_metadata, []);\n let (decoded_msg_type, decoded_msg_metadata, decoded_msg_content) =\n decode_message(BoundedVec::from_array(encoded));\n\n assert_eq(decoded_msg_type, msg_type);\n assert_eq(decoded_msg_metadata, msg_metadata);\n assert_eq(decoded_msg_content.len(), 0);\n }\n\n #[test]\n unconstrained fn encode_decode_short_message(\n msg_type: u64,\n msg_metadata: u64,\n msg_content: [Field; MAX_MESSAGE_CONTENT_LEN / 2],\n ) {\n let encoded = encode_message(msg_type, msg_metadata, msg_content);\n let (decoded_msg_type, decoded_msg_metadata, decoded_msg_content) =\n decode_message(BoundedVec::from_array(encoded));\n\n assert_eq(decoded_msg_type, msg_type);\n assert_eq(decoded_msg_metadata, msg_metadata);\n assert_eq(decoded_msg_content.len(), msg_content.len());\n assert_eq(subarray(decoded_msg_content.storage(), 0), msg_content);\n }\n\n #[test]\n unconstrained fn encode_decode_full_message(\n msg_type: u64,\n msg_metadata: u64,\n msg_content: [Field; MAX_MESSAGE_CONTENT_LEN],\n ) {\n let encoded = encode_message(msg_type, msg_metadata, msg_content);\n let (decoded_msg_type, decoded_msg_metadata, decoded_msg_content) =\n decode_message(BoundedVec::from_array(encoded));\n\n assert_eq(decoded_msg_type, msg_type);\n assert_eq(decoded_msg_metadata, msg_metadata);\n assert_eq(decoded_msg_content.len(), msg_content.len());\n assert_eq(subarray(decoded_msg_content.storage(), 0), msg_content);\n }\n\n #[test]\n unconstrained fn to_expanded_metadata_packing() {\n // Test case 1: All bits set\n let packed = to_expanded_metadata(U64_MAX, U64_MAX);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 2: Only log type bits set\n let packed = to_expanded_metadata(U64_MAX, 0);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, 0);\n\n // Test case 3: Only msg_metadata bits set\n let packed = to_expanded_metadata(0, U64_MAX);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 4: No bits set\n let packed = to_expanded_metadata(0, 0);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, 0);\n }\n\n #[test]\n unconstrained fn from_expanded_metadata_packing() {\n // Test case 1: All bits set\n let input = U128_MAX as Field;\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 2: Only log type bits set\n let input = (U128_MAX - U64_MAX as Field);\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, 0);\n\n // Test case 3: Only msg_metadata bits set\n let input = U64_MAX as Field;\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 4: No bits set\n let input = 0;\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, 0);\n }\n\n #[test]\n unconstrained fn to_from_expanded_metadata(original_msg_type: u64, original_msg_metadata: u64) {\n let packed = to_expanded_metadata(original_msg_type, original_msg_metadata);\n let (unpacked_msg_type, unpacked_msg_metadata) = from_expanded_metadata(packed);\n\n assert_eq(original_msg_type, unpacked_msg_type);\n assert_eq(original_msg_metadata, unpacked_msg_metadata);\n }\n}\n" - }, - "107": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/messages/encryption/aes128.nr", - "source": "use dep::protocol_types::{\n constants::{GENERATOR_INDEX__SYMMETRIC_KEY, GENERATOR_INDEX__SYMMETRIC_KEY_2},\n hash::poseidon2_hash_with_separator,\n point::Point,\n};\n\nuse crate::{\n keys::{\n ecdh_shared_secret::derive_ecdh_shared_secret_using_aztec_address,\n ephemeral::generate_ephemeral_key_pair,\n },\n messages::{\n encryption::log_encryption::{\n EPH_PK_SIGN_BYTE_SIZE_IN_BYTES, EPH_PK_X_SIZE_IN_FIELDS,\n HEADER_CIPHERTEXT_SIZE_IN_BYTES, LogEncryption, PRIVATE_LOG_CIPHERTEXT_LEN,\n PRIVATE_LOG_PLAINTEXT_SIZE_IN_FIELDS,\n },\n logs::arithmetic_generics_utils::{\n get_arr_of_size__log_bytes__from_PT, get_arr_of_size__log_bytes_padding__from_PT,\n },\n },\n oracle::{aes128_decrypt::aes128_decrypt_oracle, shared_secret::get_shared_secret},\n prelude::AztecAddress,\n utils::{\n array,\n conversion::{\n bytes_to_fields::{bytes_from_fields, bytes_to_fields},\n fields_to_bytes::{fields_from_bytes, fields_to_bytes},\n },\n point::{get_sign_of_point, point_from_x_coord_and_sign, point_to_bytes},\n random::get_random_bytes,\n },\n};\n\nuse std::aes128::aes128_encrypt;\n\nfn extract_close_to_uniformly_random_256_bits_from_ecdh_shared_secret_using_poseidon2(\n shared_secret: Point,\n) -> [u8; 32] {\n let rand1: Field = poseidon2_hash_with_separator(\n [shared_secret.x, shared_secret.y],\n GENERATOR_INDEX__SYMMETRIC_KEY,\n );\n let rand2: Field = poseidon2_hash_with_separator(\n [shared_secret.x, shared_secret.y],\n GENERATOR_INDEX__SYMMETRIC_KEY_2,\n );\n let rand1_bytes: [u8; 16] = rand1.to_le_bytes();\n let rand2_bytes: [u8; 16] = rand2.to_le_bytes();\n let mut bytes: [u8; 32] = [0; 32];\n for i in 0..16 {\n bytes[i] = rand1_bytes[i];\n bytes[i + 1] = rand2_bytes[i];\n }\n bytes\n}\n\n// TODO(#10537): Consider nuking this function.\nfn extract_close_to_uniformly_random_256_bits_from_ecdh_shared_secret_using_sha256(\n shared_secret: Point,\n) -> [u8; 32] {\n let shared_secret_bytes: [u8; 32] = point_to_bytes(shared_secret);\n\n let mut shared_secret_bytes_with_separator: [u8; 33] = std::mem::zeroed();\n for i in 0..shared_secret_bytes.len() {\n shared_secret_bytes_with_separator[i] = shared_secret_bytes[i];\n }\n shared_secret_bytes_with_separator[32] = GENERATOR_INDEX__SYMMETRIC_KEY;\n\n sha256::digest(shared_secret_bytes_with_separator)\n}\n\nfn derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret(\n shared_secret: Point,\n randomness_extraction_fn: fn(Point) -> [u8; 32],\n) -> ([u8; 16], [u8; 16]) {\n let random_256_bits = randomness_extraction_fn(shared_secret);\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n for i in 0..16 {\n sym_key[i] = random_256_bits[i];\n iv[i] = random_256_bits[i + 16];\n }\n (sym_key, iv)\n}\n\n// TODO(#10537): Consider nuking this function.\npub fn derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_sha256(\n shared_secret: Point,\n) -> ([u8; 16], [u8; 16]) {\n derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret(\n shared_secret,\n extract_close_to_uniformly_random_256_bits_from_ecdh_shared_secret_using_sha256,\n )\n}\n\n// TODO(#10537): This function is currently unused. Consider using it instead of the sha256 one.\npub fn derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_poseidon2(\n shared_secret: Point,\n) -> ([u8; 16], [u8; 16]) {\n derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret(\n shared_secret,\n extract_close_to_uniformly_random_256_bits_from_ecdh_shared_secret_using_poseidon2,\n )\n}\n\npub struct AES128 {}\n\nimpl LogEncryption for AES128 {\n fn encrypt_log(\n plaintext: [Field; PLAINTEXT_LEN],\n recipient: AztecAddress,\n ) -> [Field; PRIVATE_LOG_CIPHERTEXT_LEN] {\n // AES 128 operates on bytes, not fields, so we need to convert the fields to bytes.\n // (This process is then reversed when processing the log in `do_process_log`)\n let plaintext_bytes = fields_to_bytes(plaintext);\n\n // *****************************************************************************\n // Compute the shared secret\n // *****************************************************************************\n\n let (eph_sk, eph_pk) = generate_ephemeral_key_pair();\n\n let eph_pk_sign_byte: u8 = get_sign_of_point(eph_pk) as u8;\n\n // (not to be confused with the tagging shared secret)\n let ciphertext_shared_secret =\n derive_ecdh_shared_secret_using_aztec_address(eph_sk, recipient);\n\n // TODO: also use this shared secret for deriving note randomness.\n\n // *****************************************************************************\n // Convert the plaintext into whatever format the encryption function expects\n // *****************************************************************************\n\n // Already done for this strategy: AES expects bytes.\n\n // *****************************************************************************\n // Encrypt the plaintext\n // *****************************************************************************\n\n let (sym_key, iv) = derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_sha256(\n ciphertext_shared_secret,\n );\n\n let ciphertext_bytes = aes128_encrypt(plaintext_bytes, iv, sym_key);\n\n // |full_pt| = |pt_length| + |pt|\n // |pt_aes_padding| = 16 - (|full_pt| % 16)\n // or... since a % b is the same as a - b * (a // b) (integer division), so:\n // |pt_aes_padding| = 16 - (|full_pt| - 16 * (|full_pt| // 16))\n // |ct| = |full_pt| + |pt_aes_padding|\n // = |full_pt| + 16 - (|full_pt| - 16 * (|full_pt| // 16))\n // = 16 + 16 * (|full_pt| // 16)\n // = 16 * (1 + |full_pt| // 16)\n assert(ciphertext_bytes.len() == 16 * (1 + (PLAINTEXT_LEN * 32) / 16));\n\n // *****************************************************************************\n // Compute the header ciphertext\n // *****************************************************************************\n\n // Header contains only the length of the ciphertext stored in 2 bytes.\n // TODO: consider nuking the header altogether and just have a fixed-size ciphertext by padding the plaintext.\n // This would be more costly constraint-wise but cheaper DA-wise.\n let mut header_plaintext: [u8; 2] = [0 as u8; 2];\n let ciphertext_bytes_length = ciphertext_bytes.len();\n header_plaintext[0] = (ciphertext_bytes_length >> 8) as u8;\n header_plaintext[1] = ciphertext_bytes_length as u8;\n\n // TODO: this is insecure and wasteful:\n // \"Insecure\", because the esk shouldn't be used twice (once for the header,\n // and again for the proper ciphertext) (at least, I never got the\n // \"go ahead\" that this would be safe, unfortunately).\n // \"Wasteful\", because the exact same computation is happening further down.\n // I'm leaving that 2nd computation where it is, because this 1st computation\n // will be imminently deleted, when the header logic is deleted.\n let (sym_key, iv) = derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_sha256(\n ciphertext_shared_secret,\n );\n\n // Note: the aes128_encrypt builtin fn automatically appends bytes to the\n // input, according to pkcs#7; hence why the output `header_ciphertext_bytes` is 16\n // bytes larger than the input in this case.\n let header_ciphertext_bytes = aes128_encrypt(header_plaintext, iv, sym_key);\n // I recall that converting a slice to an array incurs constraints, so I'll check the length this way instead:\n assert(header_ciphertext_bytes.len() == HEADER_CIPHERTEXT_SIZE_IN_BYTES);\n\n // *****************************************************************************\n // Prepend / append more bytes of data to the ciphertext, before converting back\n // to fields.\n // *****************************************************************************\n\n let mut log_bytes_padding_to_mult_31 =\n get_arr_of_size__log_bytes_padding__from_PT::();\n // Safety: this randomness won't be constrained to be random. It's in the\n // interest of the executor of this fn to encrypt with random bytes.\n log_bytes_padding_to_mult_31 = unsafe { get_random_bytes() };\n\n let mut log_bytes = get_arr_of_size__log_bytes__from_PT::();\n\n assert(\n log_bytes.len() % 31 == 0,\n \"Unexpected error: log_bytes.len() should be divisible by 31, by construction.\",\n );\n\n log_bytes[0] = eph_pk_sign_byte;\n let mut offset = 1;\n for i in 0..header_ciphertext_bytes.len() {\n log_bytes[offset + i] = header_ciphertext_bytes[i];\n }\n offset += header_ciphertext_bytes.len();\n\n for i in 0..ciphertext_bytes.len() {\n log_bytes[offset + i] = ciphertext_bytes[i];\n }\n offset += ciphertext_bytes.len();\n\n for i in 0..log_bytes_padding_to_mult_31.len() {\n log_bytes[offset + i] = log_bytes_padding_to_mult_31[i];\n }\n\n assert(\n offset + log_bytes_padding_to_mult_31.len() == log_bytes.len(),\n \"Something has gone wrong\",\n );\n\n // *****************************************************************************\n // Convert bytes back to fields\n // *****************************************************************************\n\n // TODO(#12749): As Mike pointed out, we need to make logs produced by different encryption schemes\n // indistinguishable from each other and for this reason the output here and in the last for-loop of this function\n // should cover a full field.\n let log_bytes_as_fields = bytes_to_fields(log_bytes);\n\n // *****************************************************************************\n // Prepend / append fields, to create the final log\n // *****************************************************************************\n\n let mut ciphertext: [Field; PRIVATE_LOG_CIPHERTEXT_LEN] = [0; PRIVATE_LOG_CIPHERTEXT_LEN];\n\n ciphertext[0] = eph_pk.x;\n\n let mut offset = 1;\n for i in 0..log_bytes_as_fields.len() {\n ciphertext[offset + i] = log_bytes_as_fields[i];\n }\n offset += log_bytes_as_fields.len();\n\n for i in offset..PRIVATE_LOG_CIPHERTEXT_LEN {\n // We need to get a random value that fits in 31 bytes to not leak information about the size of the log\n // (all the \"real\" log fields contain at most 31 bytes because of the way we convert the bytes to fields).\n // TODO(#12749): Long term, this is not a good solution.\n\n // Safety: we assume that the sender wants for the log to be private - a malicious one could simply reveal its\n // contents publicly. It is therefore fine to trust the sender to provide random padding.\n let field_bytes = unsafe { get_random_bytes::<31>() };\n ciphertext[i] = Field::from_be_bytes::<31>(field_bytes);\n }\n\n ciphertext\n }\n\n unconstrained fn decrypt_log(\n ciphertext: BoundedVec,\n recipient: AztecAddress,\n ) -> BoundedVec {\n let eph_pk_x = ciphertext.get(0);\n\n let ciphertext_without_eph_pk_x_fields = array::subbvec::(\n ciphertext,\n EPH_PK_X_SIZE_IN_FIELDS,\n );\n\n // Convert the ciphertext represented as fields to a byte representation (its original format)\n let ciphertext_without_eph_pk_x = bytes_from_fields(ciphertext_without_eph_pk_x_fields);\n\n // First byte of the ciphertext represents the ephemeral public key sign\n let eph_pk_sign_bool = ciphertext_without_eph_pk_x.get(0) as bool;\n // With the sign and the x-coordinate of the ephemeral public key, we can reconstruct the point\n let eph_pk = point_from_x_coord_and_sign(eph_pk_x, eph_pk_sign_bool);\n\n // Derive shared secret and symmetric key\n let ciphertext_shared_secret = get_shared_secret(recipient, eph_pk);\n let (sym_key, iv) = derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_sha256(\n ciphertext_shared_secret,\n );\n\n // Extract the header ciphertext\n let header_start = EPH_PK_SIGN_BYTE_SIZE_IN_BYTES; // Skip eph_pk_sign byte\n let header_ciphertext: [u8; HEADER_CIPHERTEXT_SIZE_IN_BYTES] =\n array::subarray(ciphertext_without_eph_pk_x.storage(), header_start);\n // We need to convert the array to a BoundedVec because the oracle expects a BoundedVec as it's designed to work\n // with logs with unknown length at compile time. This would not be necessary here as the header ciphertext length\n // is fixed. But we do it anyway to not have to have duplicate oracles.\n let header_ciphertext_bvec =\n BoundedVec::::from_array(header_ciphertext);\n\n // Decrypt header\n let header_plaintext = aes128_decrypt_oracle(header_ciphertext_bvec, iv, sym_key);\n\n // Extract ciphertext length from header (2 bytes, big-endian)\n let ciphertext_length =\n ((header_plaintext.get(0) as u32) << 8) | (header_plaintext.get(1) as u32);\n\n // Extract and decrypt main ciphertext\n let ciphertext_start = header_start + HEADER_CIPHERTEXT_SIZE_IN_BYTES;\n let ciphertext_with_padding: [u8; (PRIVATE_LOG_CIPHERTEXT_LEN - EPH_PK_X_SIZE_IN_FIELDS) * 31 - HEADER_CIPHERTEXT_SIZE_IN_BYTES - EPH_PK_SIGN_BYTE_SIZE_IN_BYTES] =\n array::subarray(ciphertext_without_eph_pk_x.storage(), ciphertext_start);\n let ciphertext: BoundedVec =\n BoundedVec::from_parts(ciphertext_with_padding, ciphertext_length);\n\n // Decrypt main ciphertext and return it\n let plaintext_bytes = aes128_decrypt_oracle(ciphertext, iv, sym_key);\n\n // Each field of the original note log was serialized to 32 bytes so we convert the bytes back to fields.\n fields_from_bytes(plaintext_bytes)\n }\n}\n\nmod test {\n use crate::{\n keys::ecdh_shared_secret::derive_ecdh_shared_secret_using_aztec_address,\n messages::encryption::log_encryption::{LogEncryption, PRIVATE_LOG_PLAINTEXT_SIZE_IN_FIELDS},\n test::helpers::test_environment::TestEnvironment,\n };\n use super::AES128;\n use protocol_types::{\n address::AztecAddress,\n indexed_tagging_secret::IndexedTaggingSecret,\n traits::{Deserialize, FromField},\n };\n use std::{embedded_curve_ops::EmbeddedCurveScalar, test::OracleMock};\n\n #[test]\n unconstrained fn encrypt_decrypt_log() {\n let mut env = TestEnvironment::new();\n // Advance 1 block so we can read historic state from private\n env.advance_block_by(1);\n\n let plaintext = [1, 2, 3];\n\n let recipient = AztecAddress::from_field(\n 0x25afb798ea6d0b8c1618e50fdeafa463059415013d3b7c75d46abf5e242be70c,\n );\n\n // Mock random values for deterministic test\n let eph_sk = 0x1358d15019d4639393d62b97e1588c095957ce74a1c32d6ec7d62fe6705d9538;\n let _ = OracleMock::mock(\"getRandomField\").returns(eph_sk).times(1);\n\n let randomness = 0x0101010101010101010101010101010101010101010101010101010101010101;\n let _ = OracleMock::mock(\"getRandomField\").returns(randomness).times(1000000);\n\n let _ = OracleMock::mock(\"getIndexedTaggingSecretAsSender\").returns(\n IndexedTaggingSecret::deserialize([69420, 1337]),\n );\n let _ = OracleMock::mock(\"incrementAppTaggingSecretIndexAsSender\").returns(());\n\n // Encrypt the log\n let encrypted_log = BoundedVec::from_array(AES128::encrypt_log(plaintext, recipient));\n\n // Mock shared secret for deterministic test\n let shared_secret = derive_ecdh_shared_secret_using_aztec_address(\n EmbeddedCurveScalar::from_field(eph_sk),\n recipient,\n );\n let _ = OracleMock::mock(\"getSharedSecret\").returns(shared_secret);\n\n // Decrypt the log\n let decrypted = AES128::decrypt_log(encrypted_log, recipient);\n\n // The decryption function spits out a BoundedVec because it's designed to work with logs with unknown length\n // at compile time. For this reason we need to convert the original input to a BoundedVec.\n let plaintext_bvec =\n BoundedVec::::from_array(plaintext);\n\n // Verify decryption matches original plaintext\n assert_eq(decrypted, plaintext_bvec, \"Decrypted bytes should match original plaintext\");\n\n // The following is a workaround of \"struct is never constructed\" Noir compilation error (we only ever use\n // static methods of the struct).\n let _ = AES128 {};\n }\n}\n" - }, - "12": { - "path": "std/convert.nr", - "source": "// docs:start:from-trait\npub trait From {\n fn from(input: T) -> Self;\n}\n// docs:end:from-trait\n\nimpl From for T {\n fn from(input: T) -> T {\n input\n }\n}\n\n// docs:start:into-trait\npub trait Into {\n fn into(self) -> T;\n}\n\nimpl Into for U\nwhere\n T: From,\n{\n fn into(self) -> T {\n T::from(self)\n }\n}\n// docs:end:into-trait\n\n// docs:start:from-impls\n// Unsigned integers\n\nimpl From for u32 {\n fn from(value: u8) -> u32 {\n value as u32\n }\n}\n\nimpl From for u64 {\n fn from(value: u8) -> u64 {\n value as u64\n }\n}\nimpl From for u64 {\n fn from(value: u32) -> u64 {\n value as u64\n }\n}\n\nimpl From for u128 {\n fn from(value: u8) -> u128 {\n value as u128\n }\n}\nimpl From for u128 {\n fn from(value: u32) -> u128 {\n value as u128\n }\n}\nimpl From for u128 {\n fn from(value: u64) -> u128 {\n value as u128\n }\n}\n\nimpl From for Field {\n fn from(value: u8) -> Field {\n value as Field\n }\n}\nimpl From for Field {\n fn from(value: u32) -> Field {\n value as Field\n }\n}\nimpl From for Field {\n fn from(value: u64) -> Field {\n value as Field\n }\n}\n\nimpl From for Field {\n fn from(value: u128) -> Field {\n value as Field\n }\n}\n\n// Signed integers\n\nimpl From for i32 {\n fn from(value: i8) -> i32 {\n value as i32\n }\n}\n\nimpl From for i64 {\n fn from(value: i8) -> i64 {\n value as i64\n }\n}\nimpl From for i64 {\n fn from(value: i32) -> i64 {\n value as i64\n }\n}\n\n// Booleans\nimpl From for u8 {\n fn from(value: bool) -> u8 {\n value as u8\n }\n}\nimpl From for u32 {\n fn from(value: bool) -> u32 {\n value as u32\n }\n}\nimpl From for u64 {\n fn from(value: bool) -> u64 {\n value as u64\n }\n}\nimpl From for i8 {\n fn from(value: bool) -> i8 {\n value as i8\n }\n}\nimpl From for i32 {\n fn from(value: bool) -> i32 {\n value as i32\n }\n}\nimpl From for i64 {\n fn from(value: bool) -> i64 {\n value as i64\n }\n}\nimpl From for Field {\n fn from(value: bool) -> Field {\n value as Field\n }\n}\n// docs:end:from-impls\n\n/// A generic interface for casting between primitive types,\n/// equivalent of using the `as` keyword between values.\n///\n/// # Example\n///\n/// ```\n/// let x: Field = 1234567890;\n/// let y: u8 = x as u8;\n/// let z: u8 = x.as_();\n/// assert_eq(y, z);\n/// ```\npub trait AsPrimitive {\n /// The equivalent of doing `self as T`.\n fn as_(self) -> T;\n}\n\n#[generate_as_primitive_impls]\ncomptime fn generate_as_primitive_impls(_: FunctionDefinition) -> Quoted {\n let types = [\n quote { bool },\n quote { u8 },\n quote { u16 },\n quote { u32 },\n quote { u64 },\n quote { u128 },\n quote { i8 },\n quote { i16 },\n quote { i32 },\n quote { i64 },\n quote { Field },\n ];\n\n let mut impls = &[];\n for type1 in types {\n for type2 in types {\n impls = impls.push_back(\n quote {\n impl AsPrimitive<$type1> for $type2 {\n fn as_(self) -> $type1 {\n self as $type1\n }\n }\n },\n );\n }\n }\n impls.join(quote {})\n}\n" - }, - "128": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/note/note_metadata.nr", - "source": "use protocol_types::traits::Serialize;\n\n// There's temporarily quite a bit of boilerplate here because Noir does not yet support enums. This file will\n// eventually be simplified into something closer to:\n//\n// pub enum NoteMetadata {\n// PendingSamePhase{ note_hash_counter: u32 },\n// PendingOtherPhase{ note_hash_counter: u32, nonce: Field },\n// Settled{ nonce: Field },\n// }\n//\n// For now, we have `NoteMetadata` acting as a sort of tagged union.\n\nstruct NoteStageEnum {\n /// A note that was created in the transaction that is currently being executed, during the current execution phase,\n /// i.e. non-revertible or revertible.\n ///\n /// These notes are not yet in the note hash tree, though they will be inserted unless nullified in this transaction\n /// (becoming a transient note).\n PENDING_SAME_PHASE: u8,\n /// A note that was created in the transaction that is currently being executed, during the previous execution\n /// phase. Because there are only two phases and their order is always the same (first non-revertible and then\n /// revertible) this implies that the note was created in the non-revertible phase, and that the current phase is\n /// the revertible phase.\n ///\n /// These notes are not yet in the note hash tree, though they will be inserted **even if nullified in this\n /// transaction**. This means that they must be nullified as if they were settled (i.e. using the unique note hash)\n /// in order to avoid double spends once they become settled.\n PENDING_PREVIOUS_PHASE: u8,\n /// A note that was created in a prior transaction and is therefore already in the note hash tree.\n SETTLED: u8,\n}\n\nglobal NoteStage: NoteStageEnum =\n NoteStageEnum { PENDING_SAME_PHASE: 1, PENDING_PREVIOUS_PHASE: 2, SETTLED: 3 };\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a note in any of the three valid stages (pending same phase, pending previous phase, or settled). In\n/// order to access the underlying fields callers must first find the appropriate stage (e.g. via `is_settled()`) and\n/// then convert this into the appropriate type (e.g. via `to_settled()`).\n#[derive(Eq, Serialize)]\npub struct NoteMetadata {\n stage: u8,\n maybe_nonce: Field,\n}\n\nimpl NoteMetadata {\n /// Constructs a `NoteMetadata` object from optional note hash counter and nonce. Both a zero note hash counter and\n /// a zero nonce are invalid, so those are used to signal non-existent values.\n pub fn from_raw_data(nonzero_note_hash_counter: bool, maybe_nonce: Field) -> Self {\n if nonzero_note_hash_counter {\n if maybe_nonce == 0 {\n Self { stage: NoteStage.PENDING_SAME_PHASE, maybe_nonce }\n } else {\n Self { stage: NoteStage.PENDING_PREVIOUS_PHASE, maybe_nonce }\n }\n } else if maybe_nonce != 0 {\n Self { stage: NoteStage.SETTLED, maybe_nonce }\n } else {\n panic(\n f\"Note has a zero note hash counter and no nonce - existence cannot be proven\",\n )\n }\n }\n\n /// Returns true if the note is pending **and** from the same phase, i.e. if it's been created in the current\n /// transaction during the current execution phase (either non-revertible or revertible).\n pub fn is_pending_same_phase(self) -> bool {\n self.stage == NoteStage.PENDING_SAME_PHASE\n }\n\n /// Returns true if the note is pending **and** from the previous phase, i.e. if it's been created in the current\n /// transaction during an execution phase prior to the current one. Because private execution only has two phases\n /// with strict ordering, this implies that the note was created in the non-revertible phase, and that the current\n /// phase is the revertible phase.\n pub fn is_pending_previous_phase(self) -> bool {\n self.stage == NoteStage.PENDING_PREVIOUS_PHASE\n }\n\n /// Returns true if the note is settled, i.e. if it's been created in a prior transaction and is therefore already\n /// in the note hash tree.\n pub fn is_settled(self) -> bool {\n self.stage == NoteStage.SETTLED\n }\n\n /// Asserts that the metadata is that of a pending note from the same phase and converts it accordingly.\n pub fn to_pending_same_phase(self) -> PendingSamePhaseNoteMetadata {\n assert_eq(self.stage, NoteStage.PENDING_SAME_PHASE);\n PendingSamePhaseNoteMetadata::new()\n }\n\n /// Asserts that the metadata is that of a pending note from a previous phase and converts it accordingly.\n pub fn to_pending_previous_phase(self) -> PendingPreviousPhaseNoteMetadata {\n assert_eq(self.stage, NoteStage.PENDING_PREVIOUS_PHASE);\n PendingPreviousPhaseNoteMetadata::new(self.maybe_nonce)\n }\n\n /// Asserts that the metadata is that of a settled note and converts it accordingly.\n pub fn to_settled(self) -> SettledNoteMetadata {\n assert_eq(self.stage, NoteStage.SETTLED);\n SettledNoteMetadata::new(self.maybe_nonce)\n }\n}\n\nimpl From for NoteMetadata {\n fn from(_value: PendingSamePhaseNoteMetadata) -> Self {\n NoteMetadata::from_raw_data(true, std::mem::zeroed())\n }\n}\n\nimpl From for NoteMetadata {\n fn from(value: PendingPreviousPhaseNoteMetadata) -> Self {\n NoteMetadata::from_raw_data(true, value.nonce())\n }\n}\n\nimpl From for NoteMetadata {\n fn from(value: SettledNoteMetadata) -> Self {\n NoteMetadata::from_raw_data(false, value.nonce())\n }\n}\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a pending same phase note, i.e. a note that was created in the transaction that is currently being\n/// executed during the current execution phase (either non-revertible or revertible).\npub struct PendingSamePhaseNoteMetadata {\n // This struct contains no fields since there is no metadata associated with a pending same phase note: it has no\n // nonce (since it may get squashed by a nullifier emitted in the same phase), and while it does have a note hash\n // counter we cannot constrain its value (and don't need to - only that it is non-zero).\n}\n\nimpl PendingSamePhaseNoteMetadata {\n pub fn new() -> Self {\n Self {}\n }\n}\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a pending previous phase note, i.e. a note that was created in the transaction that is currently\n/// being executed, during the previous execution phase. Because there are only two phases and their order is always the\n/// same (first non-revertible and then revertible) this implies that the note was created in the non-revertible phase,\n/// and that the current phase is the revertible phase.\npub struct PendingPreviousPhaseNoteMetadata {\n nonce: Field,\n // This struct does not contain a note hash counter, even though one exists for this note, because we cannot\n // constrain its value (and don't need to - only that it is non-zero).\n}\n\nimpl PendingPreviousPhaseNoteMetadata {\n pub fn new(nonce: Field) -> Self {\n Self { nonce }\n }\n\n pub fn nonce(self) -> Field {\n self.nonce\n }\n}\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a settled note, i.e. a note that was created in a prior transaction and is therefore already in the\n/// note hash tree.\npub struct SettledNoteMetadata {\n nonce: Field,\n}\n\nimpl SettledNoteMetadata {\n pub fn new(nonce: Field) -> Self {\n Self { nonce }\n }\n\n pub fn nonce(self) -> Field {\n self.nonce\n }\n}\n" - }, - "131": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/note/utils.nr", - "source": "use crate::{\n context::PrivateContext,\n note::{note_interface::NoteHash, retrieved_note::RetrievedNote},\n};\n\nuse dep::protocol_types::hash::{\n compute_siloed_note_hash, compute_siloed_nullifier, compute_unique_note_hash,\n};\n\n/// Returns the note hash that must be used to issue a private kernel read request for a note.\npub fn compute_note_hash_for_read_request(\n retrieved_note: RetrievedNote,\n storage_slot: Field,\n) -> Field\nwhere\n Note: NoteHash,\n{\n let note_hash = retrieved_note.note.compute_note_hash(storage_slot);\n\n if retrieved_note.metadata.is_settled() {\n // Settled notes are read by siloing with contract address and nonce (resulting in the final unique note hash,\n // which is already in the note hash tree).\n let siloed_note_hash = compute_siloed_note_hash(retrieved_note.contract_address, note_hash);\n compute_unique_note_hash(\n retrieved_note.metadata.to_settled().nonce(),\n siloed_note_hash,\n )\n } else {\n // Pending notes (both same phase and previous phase ones) re read by their non-siloed hash (not even by\n // contract address), which is what is stored in the new note hashes array (at the position hinted by note hash\n // counter).\n note_hash\n }\n}\n\n/// Returns the note hash that must be used to compute a note's nullifier when calling `NoteHash::compute_nullifier` or\n/// `NoteHash::compute_nullifier_unconstrained`.\npub fn compute_note_hash_for_nullify(\n retrieved_note: RetrievedNote,\n storage_slot: Field,\n) -> Field\nwhere\n Note: NoteHash,\n{\n compute_note_hash_for_nullify_from_read_request(\n retrieved_note,\n compute_note_hash_for_read_request(retrieved_note, storage_slot),\n )\n}\n\n/// Same as `compute_note_hash_for_nullify`, except it takes the note hash used in a read request (i.e. what\n/// `compute_note_hash_for_read_request` would return). This is useful in scenarios where that hash has already been\n/// computed to reduce constraints by reusing this value.\npub fn compute_note_hash_for_nullify_from_read_request(\n retrieved_note: RetrievedNote,\n note_hash_for_read_request: Field,\n) -> Field {\n // There is just one instance in which the note hash for nullification does not match the note hash used for a read\n // request, which is when dealing with pending previous phase notes. These had their existence proven using their\n // non-siloed note hash along with the note hash counter (like all pending notes), but since they will be\n // unconditionally inserted in the note hash tree (since they cannot be squashed) they must be nullified using the\n // *unique* note hash.\n // If we didn't, it'd be possible to emit a second different nullifier for the same note in a follow up transaction,\n // once the note is settled, resulting in a double spend.\n\n if retrieved_note.metadata.is_pending_previous_phase() {\n let siloed_note_hash =\n compute_siloed_note_hash(retrieved_note.contract_address, note_hash_for_read_request);\n let nonce = retrieved_note.metadata.to_pending_previous_phase().nonce();\n\n compute_unique_note_hash(nonce, siloed_note_hash)\n } else {\n note_hash_for_read_request\n }\n}\n\n/// Computes a note's siloed nullifier, i.e. the one that will be inserted into the nullifier tree.\npub fn compute_siloed_note_nullifier(\n retrieved_note: RetrievedNote,\n storage_slot: Field,\n context: &mut PrivateContext,\n) -> Field\nwhere\n Note: NoteHash,\n{\n let note_hash_for_nullify = compute_note_hash_for_nullify(retrieved_note, storage_slot);\n let inner_nullifier = retrieved_note.note.compute_nullifier(context, note_hash_for_nullify);\n\n compute_siloed_nullifier(retrieved_note.contract_address, inner_nullifier)\n}\n" - }, - "135": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/oracle/capsules.nr", - "source": "use protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}};\n\n/// Stores arbitrary information in a per-contract non-volatile database, which can later be retrieved with `load`. If\n/// data was already stored at this slot, it is overwritten.\npub unconstrained fn store(contract_address: AztecAddress, slot: Field, value: T)\nwhere\n T: Serialize,\n{\n let serialized = value.serialize();\n store_oracle(contract_address, slot, serialized);\n}\n\n/// Returns data previously stored via `storeCapsule` in the per-contract non-volatile database. Returns Option::none() if\n/// nothing was stored at the given slot.\npub unconstrained fn load(contract_address: AztecAddress, slot: Field) -> Option\nwhere\n T: Deserialize,\n{\n let serialized_option = load_oracle::(contract_address, slot, N);\n serialized_option.map(|arr| Deserialize::deserialize(arr))\n}\n\n/// Deletes data in the per-contract non-volatile database. Does nothing if no data was present.\npub unconstrained fn delete(contract_address: AztecAddress, slot: Field) {\n delete_oracle(contract_address, slot);\n}\n\n/// Copies a number of contiguous entries in the per-contract non-volatile database. This allows for efficient data\n/// structures by avoiding repeated calls to `loadCapsule` and `storeCapsule`.\n/// Supports overlapping source and destination regions (which will result in the overlapped source values being\n/// overwritten). All copied slots must exist in the database (i.e. have been stored and not deleted)\npub unconstrained fn copy(\n contract_address: AztecAddress,\n src_slot: Field,\n dst_slot: Field,\n num_entries: u32,\n) {\n copy_oracle(contract_address, src_slot, dst_slot, num_entries);\n}\n\n#[oracle(storeCapsule)]\nunconstrained fn store_oracle(\n contract_address: AztecAddress,\n slot: Field,\n values: [Field; N],\n) {}\n\n/// We need to pass in `array_len` (the value of N) as a parameter to tell the oracle how many fields the response must\n/// have.\n///\n/// Note that the oracle returns an Option<[Field; N]> because we cannot return an Option directly. That would\n/// require for the oracle resolver to know the shape of T (e.g. if T were a struct of 3 u32 values then the expected\n/// response shape would be 3 single items, whereas it were a struct containing `u32, [Field;10], u32` then the expected\n/// shape would be single, array, single.). Instead, we return the serialization and deserialize in Noir.\n#[oracle(loadCapsule)]\nunconstrained fn load_oracle(\n contract_address: AztecAddress,\n slot: Field,\n array_len: u32,\n) -> Option<[Field; N]> {}\n\n#[oracle(deleteCapsule)]\nunconstrained fn delete_oracle(contract_address: AztecAddress, slot: Field) {}\n\n#[oracle(copyCapsule)]\nunconstrained fn copy_oracle(\n contract_address: AztecAddress,\n src_slot: Field,\n dst_slot: Field,\n num_entries: u32,\n) {}\n\nmod test {\n // These tests are sort of redundant since we already test the oracle implementation directly in TypeScript, but\n // they are cheap regardless and help ensure both that the TXE implementation works accordingly and that the Noir\n // oracles are hooked up correctly.\n\n use crate::{\n oracle::capsules::{copy, delete, load, store},\n test::{helpers::test_environment::TestEnvironment, mocks::mock_struct::MockStruct},\n };\n use protocol_types::{address::AztecAddress, traits::{FromField, ToField}};\n\n unconstrained fn setup() -> AztecAddress {\n let env = TestEnvironment::new();\n env.contract_address()\n }\n\n global SLOT: Field = 1;\n\n #[test]\n unconstrained fn stores_and_loads() {\n let contract_address = setup();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value);\n\n assert_eq(load(contract_address, SLOT).unwrap(), value);\n }\n\n #[test]\n unconstrained fn store_overwrites() {\n let contract_address = setup();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value);\n\n let new_value = MockStruct::new(7, 8);\n store(contract_address, SLOT, new_value);\n\n assert_eq(load(contract_address, SLOT).unwrap(), new_value);\n }\n\n #[test]\n unconstrained fn loads_empty_slot() {\n let contract_address = setup();\n\n let loaded_value: Option = load(contract_address, SLOT);\n assert_eq(loaded_value, Option::none());\n }\n\n #[test]\n unconstrained fn deletes_stored_value() {\n let contract_address = setup();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value);\n delete(contract_address, SLOT);\n\n let loaded_value: Option = load(contract_address, SLOT);\n assert_eq(loaded_value, Option::none());\n }\n\n #[test]\n unconstrained fn deletes_empty_slot() {\n let contract_address = setup();\n\n delete(contract_address, SLOT);\n let loaded_value: Option = load(contract_address, SLOT);\n assert_eq(loaded_value, Option::none());\n }\n\n #[test]\n unconstrained fn copies_non_overlapping_values() {\n let contract_address = setup();\n\n let src = 5;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0]);\n store(contract_address, src + 1, values[1]);\n store(contract_address, src + 2, values[2]);\n\n let dst = 10;\n copy(contract_address, src, dst, 3);\n\n assert_eq(load(contract_address, dst).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2).unwrap(), values[2]);\n }\n\n #[test]\n unconstrained fn copies_overlapping_values_with_src_ahead() {\n let contract_address = setup();\n\n let src = 1;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0]);\n store(contract_address, src + 1, values[1]);\n store(contract_address, src + 2, values[2]);\n\n let dst = 2;\n copy(contract_address, src, dst, 3);\n\n assert_eq(load(contract_address, dst).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2).unwrap(), values[2]);\n\n // src[1] and src[2] should have been overwritten since they are also dst[0] and dst[1]\n assert_eq(load(contract_address, src).unwrap(), values[0]); // src[0] (unchanged)\n assert_eq(load(contract_address, src + 1).unwrap(), values[0]); // dst[0]\n assert_eq(load(contract_address, src + 2).unwrap(), values[1]); // dst[1]\n }\n\n #[test]\n unconstrained fn copies_overlapping_values_with_dst_ahead() {\n let contract_address = setup();\n\n let src = 2;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0]);\n store(contract_address, src + 1, values[1]);\n store(contract_address, src + 2, values[2]);\n\n let dst = 1;\n copy(contract_address, src, dst, 3);\n\n assert_eq(load(contract_address, dst).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2).unwrap(), values[2]);\n\n // src[0] and src[1] should have been overwritten since they are also dst[1] and dst[2]\n assert_eq(load(contract_address, src).unwrap(), values[1]); // dst[1]\n assert_eq(load(contract_address, src + 1).unwrap(), values[2]); // dst[2]\n assert_eq(load(contract_address, src + 2).unwrap(), values[2]); // src[2] (unchanged)\n }\n\n #[test(should_fail_with = \"copy empty slot\")]\n unconstrained fn cannot_copy_empty_values() {\n let contract_address = setup();\n\n copy(contract_address, SLOT, SLOT, 1);\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_store_other_contract() {\n let contract_address = setup();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n let value = MockStruct::new(5, 6);\n store(other_contract_address, SLOT, value);\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_load_other_contract() {\n let contract_address = setup();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n let _: Option = load(other_contract_address, SLOT);\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_delete_other_contract() {\n let contract_address = setup();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n delete(other_contract_address, SLOT);\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_copy_other_contract() {\n let contract_address = setup();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n copy(other_contract_address, SLOT, SLOT, 0);\n }\n}\n" - }, - "136": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr", - "source": "use dep::protocol_types::address::AztecAddress;\n\n#[oracle(notifyEnqueuedPublicFunctionCall)]\nunconstrained fn notify_enqueued_public_function_call_oracle(\n _contract_address: AztecAddress,\n _calldata_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n) {}\n\nunconstrained fn notify_enqueued_public_function_call_wrapper(\n contract_address: AztecAddress,\n calldata_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n) {\n notify_enqueued_public_function_call_oracle(\n contract_address,\n calldata_hash,\n side_effect_counter,\n is_static_call,\n )\n}\n\npub fn notify_enqueued_public_function_call(\n contract_address: AztecAddress,\n calldata_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n) {\n // Safety: Notifies the simulator that a public call has been enqueued, allowing it to prepare hints for the AVM to process this call.\n unsafe {\n notify_enqueued_public_function_call_wrapper(\n contract_address,\n calldata_hash,\n side_effect_counter,\n is_static_call,\n )\n }\n}\n\n#[oracle(notifySetPublicTeardownFunctionCall)]\nunconstrained fn notify_set_public_teardown_function_call_oracle(\n _contract_address: AztecAddress,\n _calldata_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n) {}\n\nunconstrained fn notify_set_public_teardown_function_call_wrapper(\n contract_address: AztecAddress,\n calldata_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n) {\n notify_set_public_teardown_function_call_oracle(\n contract_address,\n calldata_hash,\n side_effect_counter,\n is_static_call,\n )\n}\n\npub fn notify_set_public_teardown_function_call(\n contract_address: AztecAddress,\n calldata_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n) {\n // Safety: Notifies the simulator that a teardown call has been set, allowing it to prepare hints for the AVM to process this call.\n unsafe {\n notify_set_public_teardown_function_call_wrapper(\n contract_address,\n calldata_hash,\n side_effect_counter,\n is_static_call,\n )\n }\n}\n\npub fn notify_set_min_revertible_side_effect_counter(counter: u32) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe { notify_set_min_revertible_side_effect_counter_oracle_wrapper(counter) };\n}\n\npub unconstrained fn notify_set_min_revertible_side_effect_counter_oracle_wrapper(counter: u32) {\n notify_set_min_revertible_side_effect_counter_oracle(counter);\n}\n\n#[oracle(notifySetMinRevertibleSideEffectCounter)]\nunconstrained fn notify_set_min_revertible_side_effect_counter_oracle(_counter: u32) {}\n" - }, - "137": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/oracle/execution.nr", - "source": "use dep::protocol_types::address::AztecAddress;\n\n#[oracle(getContractAddress)]\nunconstrained fn get_contract_address_oracle() -> AztecAddress {}\n\n#[oracle(getBlockNumber)]\nunconstrained fn get_block_number_oracle() -> u32 {}\n\n#[oracle(getChainId)]\nunconstrained fn get_chain_id_oracle() -> Field {}\n\n#[oracle(getVersion)]\nunconstrained fn get_version_oracle() -> Field {}\n\npub unconstrained fn get_contract_address() -> AztecAddress {\n get_contract_address_oracle()\n}\n\npub unconstrained fn get_block_number() -> u32 {\n get_block_number_oracle()\n}\n\npub unconstrained fn get_chain_id() -> Field {\n get_chain_id_oracle()\n}\n\npub unconstrained fn get_version() -> Field {\n get_version_oracle()\n}\n" - }, - "138": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/oracle/execution_cache.nr", - "source": "/// Stores values represented as slice in execution cache to be later obtained by its hash.\npub fn store(values: [Field], hash: Field) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call. When loading the values, however, the caller must check that the values are indeed the preimage.\n unsafe { store_in_execution_cache_oracle_wrapper(values, hash) };\n}\n\nunconstrained fn store_in_execution_cache_oracle_wrapper(values: [Field], hash: Field) {\n store_in_execution_cache_oracle(values, hash);\n}\n\npub unconstrained fn load(hash: Field) -> [Field; N] {\n load_from_execution_cache_oracle(hash)\n}\n\n#[oracle(storeInExecutionCache)]\nunconstrained fn store_in_execution_cache_oracle(_values: [Field], _hash: Field) {}\n\n#[oracle(loadFromExecutionCache)]\nunconstrained fn load_from_execution_cache_oracle(_hash: Field) -> [Field; N] {}\n" - }, - "139": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr", - "source": "use protocol_types::{\n address::AztecAddress, contract_class_id::ContractClassId, contract_instance::ContractInstance,\n traits::FromField,\n};\n\n// NOTE: this is for use in private only\n#[oracle(getContractInstance)]\nunconstrained fn get_contract_instance_oracle(_address: AztecAddress) -> ContractInstance {}\n\n// NOTE: this is for use in private only\nunconstrained fn get_contract_instance_internal(address: AztecAddress) -> ContractInstance {\n get_contract_instance_oracle(address)\n}\n\n// NOTE: this is for use in private only\npub fn get_contract_instance(address: AztecAddress) -> ContractInstance {\n // Safety: The to_address function combines all values in the instance object to produce an address,\n // so by checking that we get the expected address we validate the entire struct.\n let instance = unsafe { get_contract_instance_internal(address) };\n assert_eq(instance.to_address(), address);\n\n instance\n}\n\nstruct GetContractInstanceResult {\n exists: bool,\n member: Field,\n}\n\n// These oracles each return a ContractInstance member\n// plus a boolean indicating whether the instance was found.\n#[oracle(avmOpcodeGetContractInstanceDeployer)]\nunconstrained fn get_contract_instance_deployer_oracle_avm(\n _address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {}\n#[oracle(avmOpcodeGetContractInstanceClassId)]\nunconstrained fn get_contract_instance_class_id_oracle_avm(\n _address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {}\n#[oracle(avmOpcodeGetContractInstanceInitializationHash)]\nunconstrained fn get_contract_instance_initialization_hash_oracle_avm(\n _address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {}\n\nunconstrained fn get_contract_instance_deployer_internal_avm(\n address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {\n get_contract_instance_deployer_oracle_avm(address)\n}\nunconstrained fn get_contract_instance_class_id_internal_avm(\n address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {\n get_contract_instance_class_id_oracle_avm(address)\n}\nunconstrained fn get_contract_instance_initialization_hash_internal_avm(\n address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {\n get_contract_instance_initialization_hash_oracle_avm(address)\n}\n\npub fn get_contract_instance_deployer_avm(address: AztecAddress) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let GetContractInstanceResult { exists, member } =\n unsafe { get_contract_instance_deployer_internal_avm(address)[0] };\n if exists {\n Option::some(AztecAddress::from_field(member))\n } else {\n Option::none()\n }\n}\npub fn get_contract_instance_class_id_avm(address: AztecAddress) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let GetContractInstanceResult { exists, member } =\n unsafe { get_contract_instance_class_id_internal_avm(address)[0] };\n if exists {\n Option::some(ContractClassId::from_field(member))\n } else {\n Option::none()\n }\n}\npub fn get_contract_instance_initialization_hash_avm(address: AztecAddress) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let GetContractInstanceResult { exists, member } =\n unsafe { get_contract_instance_initialization_hash_internal_avm(address)[0] };\n if exists {\n Option::some(member)\n } else {\n Option::none()\n }\n}\n" - }, - "144": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr", - "source": "use protocol_types::abis::validation_requests::KeyValidationRequest;\n\n#[oracle(getKeyValidationRequest)]\nunconstrained fn get_key_validation_request_oracle(\n _pk_m_hash: Field,\n _key_index: Field,\n) -> KeyValidationRequest {}\n\npub unconstrained fn get_key_validation_request(\n pk_m_hash: Field,\n key_index: Field,\n) -> KeyValidationRequest {\n get_key_validation_request_oracle(pk_m_hash, key_index)\n}\n" - }, - "145": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/oracle/keys.nr", - "source": "use dep::protocol_types::{\n address::{AztecAddress, PartialAddress},\n point::Point,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, TpkM},\n};\n\n#[oracle(getPublicKeysAndPartialAddress)]\nunconstrained fn get_public_keys_and_partial_address_oracle(_address: AztecAddress) -> [Field; 13] {}\n\npub unconstrained fn get_public_keys_and_partial_address(\n address: AztecAddress,\n) -> (PublicKeys, PartialAddress) {\n let result = get_public_keys_and_partial_address_oracle(address);\n\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: result[0], y: result[1], is_infinite: result[2] as bool } },\n ivpk_m: IvpkM {\n inner: Point { x: result[3], y: result[4], is_infinite: result[5] as bool },\n },\n ovpk_m: OvpkM {\n inner: Point { x: result[6], y: result[7], is_infinite: result[8] as bool },\n },\n tpk_m: TpkM {\n inner: Point { x: result[9], y: result[10], is_infinite: result[11] as bool },\n },\n };\n\n let partial_address = PartialAddress::from_field(result[12]);\n\n (keys, partial_address)\n}\n" - }, - "146": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/oracle/logs.nr", - "source": "use crate::messages::encoding::MAX_MESSAGE_CONTENT_LEN;\nuse protocol_types::{abis::event_selector::EventSelector, address::AztecAddress};\n\n/// The below only exists to broadcast the raw log, so we can provide it to the base rollup later to be constrained.\npub unconstrained fn notify_created_contract_class_log(\n contract_address: AztecAddress,\n message: [Field; N],\n length: u32,\n counter: u32,\n) {\n notify_created_contract_class_log_private_oracle(contract_address, message, length, counter)\n}\n\n#[oracle(notifyCreatedContractClassLog)]\nunconstrained fn notify_created_contract_class_log_private_oracle(\n contract_address: AztecAddress,\n message: [Field; N],\n length: u32,\n counter: u32,\n) {}\n\npub unconstrained fn store_private_event_log(\n contract_address: AztecAddress,\n recipient: AztecAddress,\n event_selector: EventSelector,\n msg_content: BoundedVec,\n tx_hash: Field,\n log_index_in_tx: Field,\n tx_index_in_block: Field,\n) {\n store_private_event_log_oracle(\n contract_address,\n recipient,\n event_selector,\n msg_content,\n tx_hash,\n log_index_in_tx,\n tx_index_in_block,\n )\n}\n\n#[oracle(storePrivateEventLog)]\nunconstrained fn store_private_event_log_oracle(\n contract_address: AztecAddress,\n recipient: AztecAddress,\n event_selector: EventSelector,\n msg_content: BoundedVec,\n tx_hash: Field,\n log_index_in_tx: Field,\n tx_index_in_block: Field,\n) {}\n" - }, - "147": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr", - "source": "use crate::messages::discovery::private_notes::MAX_NOTE_PACKED_LEN;\nuse dep::protocol_types::{\n address::AztecAddress,\n constants::{MAX_NOTE_HASHES_PER_TX, PUBLIC_LOG_SIZE_IN_FIELDS},\n};\n\n/// Finds new private logs that may have been sent to all registered accounts in PXE in the current contract and makes\n/// them available for later processing in Noir by storing them in a capsule array.\npub unconstrained fn fetch_tagged_logs(pending_tagged_log_array_base_slot: Field) {\n fetch_tagged_logs_oracle(pending_tagged_log_array_base_slot);\n}\n\n#[oracle(fetchTaggedLogs)]\nunconstrained fn fetch_tagged_logs_oracle(pending_tagged_log_array_base_slot: Field) {}\n\n/// Informs PXE of a note's existence so that it can later be retrieved by the `getNotes` oracle. The note will be\n/// scoped to `contract_address`, meaning other contracts will not be able to access it unless authorized.\n///\n/// The packed note is what `getNotes` will later return. PXE indexes notes by `storage_slot`, so this value\n/// is typically used to filter notes that correspond to different state variables. `note_hash` and `nullifier` are\n/// the inner hashes, i.e. the raw hashes returned by `NoteHash::compute_note_hash` and\n/// `NoteHash::compute_nullifier`. PXE will verify that the siloed unique note hash was inserted into the tree\n/// at `tx_hash`, and will store the nullifier to later check for nullification.\n///\n/// `recipient` is the account to which the note was sent to. Other accounts will not be able to access this note (e.g.\n/// other accounts will not be able to see one another's token balance notes, even in the same PXE) unless authorized.\n///\n/// Returns true if the note was successfully delivered and added to PXE's database.\npub unconstrained fn deliver_note(\n contract_address: AztecAddress,\n storage_slot: Field,\n nonce: Field,\n packed_note: BoundedVec,\n note_hash: Field,\n nullifier: Field,\n tx_hash: Field,\n recipient: AztecAddress,\n) -> bool {\n deliver_note_oracle(\n contract_address,\n storage_slot,\n nonce,\n packed_note,\n note_hash,\n nullifier,\n tx_hash,\n recipient,\n )\n}\n\n/// The contents of a public log, plus contextual information about the transaction in which the log was emitted. This\n/// is the data required in order to discover notes that are being delivered in a log.\n// TODO(#11639): this could also be used to fetch private logs, but the `BoundedVec` maximum length is that of a public\n// log.\npub struct LogWithTxData {\n // The log fields length is PUBLIC_LOG_SIZE_IN_FIELDS. + 1 because the contract address is prepended to the content.\n pub log_content: BoundedVec,\n pub tx_hash: Field,\n /// The array of new note hashes created by `tx_hash`\n pub unique_note_hashes_in_tx: BoundedVec,\n /// The first nullifier created by `tx_hash`\n pub first_nullifier_in_tx: Field,\n}\n\n/// Fetches a log from the node that has the corresponding `tag`. The log can be either a public or a private log, and\n/// the tag is the first field in the log's content. Returns `Option::none` if no such log exists. Throws if more than\n/// one log with that tag exists.\n/// Public logs have an extra field included at the beginning with the address of the contract that emitted them.\n// TODO(#11627): handle multiple logs with the same tag.\n// TODO(#10273): improve contract siloing of logs, don't introduce an extra field.\npub unconstrained fn get_log_by_tag(tag: Field) -> Option {\n get_log_by_tag_oracle(tag)\n}\n\n#[oracle(deliverNote)]\nunconstrained fn deliver_note_oracle(\n contract_address: AztecAddress,\n storage_slot: Field,\n nonce: Field,\n packed_note: BoundedVec,\n note_hash: Field,\n nullifier: Field,\n tx_hash: Field,\n recipient: AztecAddress,\n) -> bool {}\n\n#[oracle(getLogByTag)]\nunconstrained fn get_log_by_tag_oracle(tag: Field) -> Option {}\n" - }, - "149": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/oracle/notes.nr", - "source": "use crate::note::{\n note_interface::NoteType,\n retrieved_note::{RETRIEVED_NOTE_OVERHEAD, RetrievedNote, unpack_retrieved_note},\n};\n\nuse dep::protocol_types::{\n address::AztecAddress, indexed_tagging_secret::IndexedTaggingSecret, traits::Packable,\n};\n\n/// Notifies the simulator that a note has been created, so that it can be returned in future read requests in the same\n/// transaction. This note should only be added to the non-volatile database if found in an actual block.\npub fn notify_created_note(\n storage_slot: Field,\n note_type_id: Field,\n packed_note: [Field; N],\n note_hash: Field,\n counter: u32,\n) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe {\n notify_created_note_oracle_wrapper(\n storage_slot,\n note_type_id,\n packed_note,\n note_hash,\n counter,\n )\n };\n}\n\n/// Notifies the simulator that a note has been nullified, so that it is no longer returned in future read requests in\n/// the same transaction. This note should only be removed to the non-volatile database if its nullifier is found in an\n/// actual block.\npub fn notify_nullified_note(nullifier: Field, note_hash: Field, counter: u32) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to\n // call.\n unsafe { notify_nullified_note_oracle_wrapper(nullifier, note_hash, counter) };\n}\n\n/// Notifies the simulator that a non-note nullifier has been created, so that it can be used for note nonces.\npub fn notify_created_nullifier(nullifier: Field) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to\n // call.\n unsafe { notify_created_nullifier_oracle_wrapper(nullifier) };\n}\n\nunconstrained fn notify_created_note_oracle_wrapper(\n storage_slot: Field,\n note_type_id: Field,\n packed_note: [Field; N],\n note_hash: Field,\n counter: u32,\n) {\n notify_created_note_oracle(storage_slot, note_type_id, packed_note, note_hash, counter);\n}\n\n#[oracle(notifyCreatedNote)]\nunconstrained fn notify_created_note_oracle(\n _storage_slot: Field,\n _note_type_id: Field,\n _packed_note: [Field; N],\n _note_hash: Field,\n _counter: u32,\n) {}\n\nunconstrained fn notify_nullified_note_oracle_wrapper(\n nullifier: Field,\n note_hash: Field,\n counter: u32,\n) {\n notify_nullified_note_oracle(nullifier, note_hash, counter);\n}\n\n#[oracle(notifyNullifiedNote)]\nunconstrained fn notify_nullified_note_oracle(_nullifier: Field, _note_hash: Field, _counter: u32) {}\n\nunconstrained fn notify_created_nullifier_oracle_wrapper(nullifier: Field) {\n notify_created_nullifier_oracle(nullifier);\n}\n\n#[oracle(notifyCreatedNullifier)]\nunconstrained fn notify_created_nullifier_oracle(_nullifier: Field) {}\n\n#[oracle(getNotes)]\nunconstrained fn get_notes_oracle(\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 // This is always set to MAX_NOTES. We need to pass it to TS in order to correctly construct the BoundedVec\n _max_notes: u32,\n // This is always set to NOTE_PCKD_LEN + RETRIEVED_NOTE_OVERHEAD. We need to pass it to TS in order to be able to\n // correctly construct the BoundedVec there.\n _packed_retrieved_note_length: u32,\n) -> BoundedVec<[Field; NOTE_PCKD_LEN + RETRIEVED_NOTE_OVERHEAD], MAX_NOTES> {}\n\npub unconstrained 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) -> [Option>; MAX_NOTES]\nwhere\n Note: NoteType + Packable,\n{\n // N + 3 because of the contract address, nonce, and note_hash_counter that are stored out of the packed note.\n let packed_retrieved_notes: BoundedVec<[Field; NOTE_PCKD_LEN + RETRIEVED_NOTE_OVERHEAD], MAX_NOTES> = 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 MAX_NOTES,\n NOTE_PCKD_LEN + RETRIEVED_NOTE_OVERHEAD,\n );\n\n let mut notes = BoundedVec::<_, MAX_NOTES>::new();\n for i in 0..packed_retrieved_notes.len() {\n let retrieved_note = unpack_retrieved_note(packed_retrieved_notes.get(i));\n notes.push(retrieved_note);\n }\n\n // At last we convert the bounded vector to an array of options. We do this because that is what the filter\n // function needs to have on the output and we've decided to have the same type on the input and output of\n // the filter and preprocessor functions.\n //\n // We have decided to have the same type on the input and output of the filter and preprocessor functions because\n // it allows us to chain multiple filters and preprocessors together.\n //\n // So why do we want the array of options on the output of the filter function?\n //\n // Filter returns an array of options rather than a BoundedVec for performance reasons. Using an array of options\n // allows setting values at known indices in the output array which is much more efficient than pushing to a\n // BoundedVec where the write position depends on previous iterations. The array can then be efficiently converted\n // to a BoundedVec using utils/array/collapse.nr::collapse function from Aztec.nr. This avoids expensive dynamic\n // memory access patterns that would be required when building up a BoundedVec incrementally. For preprocessor\n // functions we could use BoundedVec return value as there the optimization does not matter since it is applied in\n // an unconstrained context. We, however, use the same return value type to be able to use the same function as\n // both a preprocessor and a filter.\n let mut notes_array = [Option::none(); MAX_NOTES];\n for i in 0..notes.len() {\n if i < notes.len() {\n notes_array[i] = Option::some(notes.get_unchecked(i));\n }\n }\n\n notes_array\n}\n\n/// Returns true if the nullifier exists. Note that a `true` value can be constrained by proving existence of the\n/// nullifier, but a `false` value should not be relied upon since other transactions may emit this nullifier before the\n/// current transaction is included in a block. While this might seem of little use at first, certain design patterns\n/// benefit from this abstraction (see e.g. `PrivateMutable`).\npub unconstrained fn check_nullifier_exists(inner_nullifier: Field) -> bool {\n check_nullifier_exists_oracle(inner_nullifier)\n}\n\n#[oracle(checkNullifierExists)]\nunconstrained fn check_nullifier_exists_oracle(_inner_nullifier: Field) -> bool {}\n\n/// Returns the derived app tagging secret ready to be included in a log for a given sender and recipient pair,\n/// siloed for the current contract address.\npub unconstrained fn get_app_tag_as_sender(sender: AztecAddress, recipient: AztecAddress) -> Field {\n get_indexed_tagging_secret_as_sender_oracle(sender, recipient).compute_tag(recipient)\n}\n\n#[oracle(getIndexedTaggingSecretAsSender)]\nunconstrained fn get_indexed_tagging_secret_as_sender_oracle(\n _sender: AztecAddress,\n _recipient: AztecAddress,\n) -> IndexedTaggingSecret {}\n\n/// Notifies the simulator that a tag has been used in a note, and to therefore increment the associated index so that\n/// future notes get a different tag and can be discovered by the recipient.\n/// This change should only be persisted in a non-volatile database if the tagged log is found in an actual block -\n/// otherwise e.g. a reverting transaction can cause the sender to accidentally skip indices and later produce notes\n/// that are not found by the recipient.\npub fn increment_app_tagging_secret_index_as_sender(sender: AztecAddress, recipient: AztecAddress) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe {\n increment_app_tagging_secret_index_as_sender_wrapper(sender, recipient);\n }\n}\n\nunconstrained fn increment_app_tagging_secret_index_as_sender_wrapper(\n sender: AztecAddress,\n recipient: AztecAddress,\n) {\n increment_app_tagging_secret_index_as_sender_oracle(sender, recipient);\n}\n\n#[oracle(incrementAppTaggingSecretIndexAsSender)]\nunconstrained fn increment_app_tagging_secret_index_as_sender_oracle(\n _sender: AztecAddress,\n _recipient: AztecAddress,\n) {}\n" - }, - "151": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/oracle/shared_secret.nr", - "source": "use protocol_types::{address::aztec_address::AztecAddress, point::Point};\n\n// TODO(#12656): return an app-siloed secret + document this\n#[oracle(getSharedSecret)]\nunconstrained fn get_shared_secret_oracle(address: AztecAddress, ephPk: Point) -> Point {}\n\n/// Returns an app-siloed shared secret between `address` and someone who knows the secret key behind an\n/// ephemeral public key `ephPk`. The app-siloing means that contracts cannot retrieve secrets that belong to\n/// other contracts, and therefore cannot e.g. decrypt their messages. This is an important security consideration\n/// given that both the `address` and `ephPk` are public information.\n///\n/// The shared secret `S` is computed as:\n/// `let S = (ivsk + h) * ephPk`\n/// where `ivsk + h` is the 'preaddress' i.e. the preimage of the address, also called the address secret.\n/// TODO(#12656): app-silo this secret\npub unconstrained fn get_shared_secret(address: AztecAddress, ephPk: Point) -> Point {\n get_shared_secret_oracle(address, ephPk)\n}\n" - }, - "153": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/oracle/storage.nr", - "source": "use dep::protocol_types::{address::AztecAddress, traits::{Packable, ToField}};\n\n#[oracle(storageRead)]\nunconstrained fn storage_read_oracle(\n address: Field,\n storage_slot: Field,\n block_number: Field,\n length: Field,\n) -> [Field; N] {}\n\npub unconstrained fn raw_storage_read(\n address: AztecAddress,\n storage_slot: Field,\n block_number: u32,\n) -> [Field; N] {\n storage_read_oracle(\n address.to_field(),\n storage_slot,\n block_number as Field,\n N as Field,\n )\n}\n\npub unconstrained fn storage_read(\n address: AztecAddress,\n storage_slot: Field,\n block_number: u32,\n) -> T\nwhere\n T: Packable,\n{\n T::unpack(raw_storage_read(address, storage_slot, block_number))\n}\n\nmod tests {\n use crate::oracle::storage::{raw_storage_read, storage_read};\n use dep::protocol_types::{address::AztecAddress, traits::{FromField, Packable}};\n\n use crate::test::mocks::mock_struct::MockStruct;\n use std::test::OracleMock;\n\n global address: AztecAddress = AztecAddress::from_field(29);\n global slot: Field = 7;\n global block_number: u32 = 17;\n\n #[test]\n unconstrained fn test_raw_storage_read() {\n let written = MockStruct { a: 13, b: 42 };\n\n let _ = OracleMock::mock(\"storageRead\").returns(written.pack());\n\n let read: [Field; 2] = raw_storage_read(address, slot, block_number);\n assert_eq(read[0], 13);\n assert_eq(read[1], 42);\n }\n\n #[test]\n unconstrained fn test_storage_read() {\n let written = MockStruct { a: 13, b: 42 };\n\n let _ = OracleMock::mock(\"storageRead\").returns(written.pack());\n\n let read: MockStruct = storage_read(address, slot, block_number);\n assert_eq(read.a, 13);\n assert_eq(read.b, 42);\n }\n}\n" - }, - "155": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/state_vars/map.nr", - "source": "use crate::state_vars::storage::Storage;\nuse dep::protocol_types::{storage::map::derive_storage_slot_in_map, traits::ToField};\n\n// docs:start:map\npub struct Map {\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V,\n}\n// docs:end:map\n\n// Map reserves a single storage slot regardless of what it stores because nothing is stored at said slot: it is only\n// used to derive the storage slots of nested state variables, which is expected to never result in collisions or slots\n// being close to one another due to these being hashes. This mirrors the strategy adopted by Solidity mappings.\nimpl Storage<1> for Map {\n fn get_storage_slot(self) -> Field {\n self.storage_slot\n }\n}\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\n where\n K: ToField,\n {\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" - }, - "16": { - "path": "std/embedded_curve_ops.nr", - "source": "use crate::cmp::Eq;\nuse crate::hash::Hash;\nuse crate::ops::arith::{Add, Neg, Sub};\n\n/// A point on the embedded elliptic curve\n/// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field.\n/// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false.\npub struct EmbeddedCurvePoint {\n pub x: Field,\n pub y: Field,\n pub is_infinite: bool,\n}\n\nimpl EmbeddedCurvePoint {\n /// Elliptic curve point doubling operation\n /// returns the doubled point of a point P, i.e P+P\n pub fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n /// Returns the null element of the curve; 'the point at infinity'\n pub fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n\n /// Returns the curve's generator point.\n pub fn generator() -> EmbeddedCurvePoint {\n // Generator point for the grumpkin curve (y^2 = x^3 - 17)\n EmbeddedCurvePoint {\n x: 1,\n y: 17631683881184975370165255887551781615748388533673675138860, // sqrt(-16)\n is_infinite: false,\n }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n /// Points subtraction operation, using addition and negation\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n /// Negates a point P, i.e returns -P, by negating the y coordinate.\n /// If the point is at infinity, then the result is also at infinity.\n fn neg(self) -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: self.x, y: -self.y, is_infinite: self.is_infinite }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n /// Checks whether two points are equal\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite)\n | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\nimpl Hash for EmbeddedCurvePoint {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n if self.is_infinite {\n self.is_infinite.hash(state);\n } else {\n self.x.hash(state);\n self.y.hash(state);\n }\n }\n}\n\n/// Scalar for the embedded curve represented as low and high limbs\n/// By definition, the scalar field of the embedded curve is base field of the proving system curve.\n/// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs.\npub struct EmbeddedCurveScalar {\n pub lo: Field,\n pub hi: Field,\n}\n\nimpl EmbeddedCurveScalar {\n pub fn new(lo: Field, hi: Field) -> Self {\n EmbeddedCurveScalar { lo, hi }\n }\n\n #[field(bn254)]\n pub fn from_field(scalar: Field) -> EmbeddedCurveScalar {\n let (a, b) = crate::field::bn254::decompose(scalar);\n EmbeddedCurveScalar { lo: a, hi: b }\n }\n\n //Bytes to scalar: take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value\n #[field(bn254)]\n pub(crate) fn from_bytes(bytes: [u8; 64], offset: u32) -> EmbeddedCurveScalar {\n let mut v = 1;\n let mut lo = 0 as Field;\n let mut hi = 0 as Field;\n for i in 0..16 {\n lo = lo + (bytes[offset + 31 - i] as Field) * v;\n hi = hi + (bytes[offset + 15 - i] as Field) * v;\n v = v * 256;\n }\n let sig_s = crate::embedded_curve_ops::EmbeddedCurveScalar { lo, hi };\n sig_s\n }\n}\n\nimpl Eq for EmbeddedCurveScalar {\n fn eq(self, other: Self) -> bool {\n (other.hi == self.hi) & (other.lo == self.lo)\n }\n}\n\nimpl Hash for EmbeddedCurveScalar {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n self.hi.hash(state);\n self.lo.hash(state);\n }\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// docs:start:multi_scalar_mul\npub fn multi_scalar_mul(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> EmbeddedCurvePoint\n// docs:end:multi_scalar_mul\n{\n multi_scalar_mul_array_return(points, scalars)[0]\n}\n\n#[foreign(multi_scalar_mul)]\npub(crate) fn multi_scalar_mul_array_return(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> [EmbeddedCurvePoint; 1] {}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint\n// docs:end:fixed_base_scalar_mul\n{\n multi_scalar_mul([EmbeddedCurvePoint::generator()], [scalar])\n}\n\n/// This function only assumes that the points are on the curve\n/// It handles corner cases around the infinity point causing some overhead compared to embedded_curve_add_not_nul and embedded_curve_add_unsafe\n// docs:start:embedded_curve_add\npub fn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n // docs:end:embedded_curve_add\n if crate::runtime::is_unconstrained() {\n // `embedded_curve_add_unsafe` requires the inputs not to be the infinity point, so we check it here.\n // This is because `embedded_curve_add_unsafe` uses the `embedded_curve_add` opcode.\n // For efficiency, the backend does not check the inputs for the infinity point, but it assumes that they are not the infinity point\n // so that it can apply the ec addition formula directly.\n if point1.is_infinite {\n point2\n } else if point2.is_infinite {\n point1\n } else {\n embedded_curve_add_unsafe(point1, point2)\n }\n } else {\n // In a constrained context, we also need to check the inputs are not the infinity point because we also use `embedded_curve_add_unsafe`\n // However we also need to identify the case where the two inputs are the same, because then\n // the addition formula does not work and we need to use the doubling formula instead.\n // In unconstrained context, we can check directly if the input values are the same when solving the opcode, so it is not an issue.\n\n // x_coordinates_match is true if both abscissae are the same\n let x_coordinates_match = point1.x == point2.x;\n // y_coordinates_match is true if both ordinates are the same\n let y_coordinates_match = point1.y == point2.y;\n // double_predicate is true if both abscissae and ordinates are the same\n let double_predicate = (x_coordinates_match & y_coordinates_match);\n // If the abscissae are the same, but not the ordinates, then one point is the opposite of the other\n let infinity_predicate = (x_coordinates_match & !y_coordinates_match);\n let point1_1 = EmbeddedCurvePoint {\n x: point1.x + (x_coordinates_match as Field),\n y: point1.y,\n is_infinite: false,\n };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n // point1_1 is guaranteed to have a different abscissa than point2:\n // - if x_coordinates_match is 0, that means point1.x != point2.x, and point1_1.x = point1.x + 0\n // - if x_coordinates_match is 1, that means point1.x = point2.x, but point1_1.x = point1.x + 1 in this case\n // Because the abscissa is different, the addition formula is guaranteed to succeed, so we can safely use `embedded_curve_add_unsafe`\n // Note that this computation may be garbage: if x_coordinates_match is 1, or if one of the input is the point at infinity.\n let mut result = embedded_curve_add_unsafe(point1_1, point2_1);\n\n // `embedded_curve_add_unsafe` is doing a doubling if the input is the same variable, because in this case it is guaranteed (at 'compile time') that the input is the same.\n let double = embedded_curve_add_unsafe(point1, point1);\n // `embedded_curve_add_unsafe` would not perform doubling, even if the inputs point1 and point2 are the same, because it cannot know this without adding some logic (and some constraints)\n // However we did this logic when we computed `double_predicate`, so we set the result to 2*point1 if point1 and point2 are the same\n result = if double_predicate { double } else { result };\n\n // Same logic as above for unconstrained context, we set the proper result when one of the inputs is the infinity point\n if point1.is_infinite {\n result = point2;\n }\n if point2.is_infinite {\n result = point1;\n }\n\n // Finally, we set the is_infinity flag of the result:\n // Opposite points should sum into the infinity point, however, if one of them is point at infinity, their coordinates are not meaningful\n // so we should not use the fact that the inputs are opposite in this case:\n let mut result_is_infinity =\n infinity_predicate & (!point1.is_infinite & !point2.is_infinite);\n // However, if both of them are at infinity, then the result is also at infinity\n result.is_infinite = result_is_infinity | (point1.is_infinite & point2.is_infinite);\n result\n }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(\n _point1: EmbeddedCurvePoint,\n _point2: EmbeddedCurvePoint,\n) -> [EmbeddedCurvePoint; 1] {}\n\n/// This function assumes that:\n/// The points are on the curve, and\n/// The points don't share an x-coordinate, and\n/// Neither point is the infinity point.\n/// If it is used with correct input, the function ensures the correct non-zero result is returned.\n/// Except for points on the curve, the other assumptions are checked by the function. It will cause assertion failure if they are not respected.\npub fn embedded_curve_add_not_nul(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n assert(point1.x != point2.x);\n assert(!point1.is_infinite);\n assert(!point2.is_infinite);\n embedded_curve_add_unsafe(point1, point2)\n}\n\n/// Unsafe ec addition\n/// If the inputs are the same, it will perform a doubling, but only if point1 and point2 are the same variable.\n/// If they have the same value but are different variables, the result will be incorrect because in this case\n/// it assumes (but does not check) that the points' x-coordinates are not equal.\n/// It also assumes neither point is the infinity point.\npub fn embedded_curve_add_unsafe(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n embedded_curve_add_array_return(point1, point2)[0]\n}\n" - }, - "163": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr", - "source": "use crate::{\n context::{PrivateContext, PublicContext, UtilityContext},\n state_vars::storage::Storage,\n utils::with_hash::WithHash,\n};\nuse dep::protocol_types::{constants::INITIALIZATION_SLOT_SEPARATOR, traits::Packable};\n\n/// Stores an immutable value in public state which can be read from public, private and unconstrained execution\n/// contexts.\n///\n/// Leverages `WithHash` to enable efficient private reads of public storage. `WithHash` wrapper allows for\n/// efficient reads by verifying large values through a single hash check and then proving inclusion only of the hash\n/// in the public storage. This reduces the number of required tree inclusion proofs from O(M) to O(1).\n///\n/// This is valuable when T packs to multiple fields, as it maintains \"almost constant\" verification overhead\n/// regardless of the original data size.\n///\n/// # Optimizing private reads in your contract\n/// Given that reading T from public immutable in private has \"almost constant\" constraints cost for different sizes\n/// of T it is recommended to group multiple values into a single struct when they are being read together. This can\n/// typically be some kind of configuration set up during contract initialization. E.g.:\n///\n/// ```noir\n/// use dep::aztec::protocol_types::{address::AztecAddress, traits::Packable};\n/// use std::meta::derive;\n///\n/// #[derive(Eq, Packable)]\n/// pub struct Config \\{\n/// pub address_1: AztecAddress,\n/// pub value_1: u128,\n/// pub value_2: u64,\n/// ...\n/// }\n/// ```\n///\n// docs:start:public_immutable_struct\npub struct PublicImmutable {\n context: Context,\n storage_slot: Field,\n}\n// docs:end:public_immutable_struct\n\n/// `WithHash` stores both the packed value (using N fields) and its hash (1 field), requiring N = M + 1 total\n/// fields.\nimpl Storage for PublicImmutable\nwhere\n WithHash: Packable,\n{\n fn get_storage_slot(self) -> Field {\n self.storage_slot\n }\n}\n\nimpl PublicImmutable {\n // docs:start:public_immutable_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 PublicImmutable { context, storage_slot }\n }\n // docs:end:public_immutable_struct_new\n}\n\nimpl PublicImmutable {\n // docs:start:public_immutable_struct_write\n pub fn initialize(self, value: T)\n where\n T: Packable + Eq,\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 init_field: Field = self.context.storage_read(initialization_slot);\n assert(init_field == 0, \"PublicImmutable already initialized\");\n\n // We populate the initialization slot with a non-zero value to indicate that the struct is initialized\n self.context.storage_write(initialization_slot, 0xdead);\n self.context.storage_write(self.storage_slot, WithHash::new(value));\n }\n // docs:end:public_immutable_struct_write\n\n // Note that we don't access the context, but we do call oracles that are only available in public\n // docs:start:public_immutable_struct_read\n pub fn read(self) -> T\n where\n T: Packable + Eq,\n {\n WithHash::public_storage_read(*self.context, self.storage_slot)\n }\n // docs:end:public_immutable_struct_read\n}\n\nimpl PublicImmutable {\n pub unconstrained fn read(self) -> T\n where\n T: Packable + Eq,\n {\n WithHash::utility_public_storage_read(self.context, self.storage_slot)\n }\n}\n\nimpl PublicImmutable {\n pub fn read(self) -> T\n where\n T: Packable + Eq,\n {\n WithHash::historical_public_storage_read(\n self.context.get_block_header(),\n self.context.this_address(),\n self.storage_slot,\n )\n }\n}\n" - }, - "164": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr", - "source": "use crate::context::{PublicContext, UtilityContext};\nuse crate::state_vars::storage::Storage;\nuse dep::protocol_types::traits::Packable;\n\n// docs:start:public_mutable_struct\npub struct PublicMutable {\n context: Context,\n storage_slot: Field,\n}\n// docs:end:public_mutable_struct\n\nimpl Storage for PublicMutable\nwhere\n T: Packable,\n{\n fn get_storage_slot(self) -> Field {\n self.storage_slot\n }\n}\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\n where\n T: Packable,\n {\n self.context.storage_read(self.storage_slot)\n }\n // docs:end:public_mutable_struct_read\n\n // docs:start:public_mutable_struct_write\n pub fn write(self, value: T)\n where\n T: Packable,\n {\n self.context.storage_write(self.storage_slot, value);\n }\n // docs:end:public_mutable_struct_write\n}\n\nimpl PublicMutable {\n pub unconstrained fn read(self) -> T\n where\n T: Packable,\n {\n self.context.storage_read(self.storage_slot)\n }\n}\n" - }, - "17": { - "path": "std/field/bn254.nr", - "source": "use crate::field::field_less_than;\nuse crate::runtime::is_unconstrained;\n\n// The low and high decomposition of the field modulus\nglobal PLO: Field = 53438638232309528389504892708671455233;\nglobal PHI: Field = 64323764613183177041862057485226039389;\n\npub(crate) global TWO_POW_128: Field = 0x100000000000000000000000000000000;\n\n// Decomposes a single field into two 16 byte fields.\nfn compute_decomposition(x: Field) -> (Field, Field) {\n // Here's we're taking advantage of truncating 128 bit limbs from the input field\n // and then subtracting them from the input such the field division is equivalent to integer division.\n let low = (x as u128) as Field;\n let high = (x - low) / TWO_POW_128;\n\n (low, high)\n}\n\npub(crate) unconstrained fn decompose_hint(x: Field) -> (Field, Field) {\n compute_decomposition(x)\n}\n\nunconstrained fn lte_hint(x: Field, y: Field) -> bool {\n if x == y {\n true\n } else {\n field_less_than(x, y)\n }\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 // Safety: borrow is enforced to be boolean due to its type.\n // if borrow is 0, it asserts that (alo > blo && ahi >= bhi)\n // if borrow is 1, it asserts that (alo <= blo && ahi > bhi)\n unsafe {\n let borrow = lte_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\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 // Safety: decomposition is properly checked below\n unsafe {\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}\n\npub fn assert_gt(a: Field, b: Field) {\n if is_unconstrained() {\n assert(\n // Safety: already unconstrained\n unsafe { field_less_than(b, a) },\n );\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 // Safety: unsafe in unconstrained\n unsafe {\n field_less_than(b, a)\n }\n } else if a == b {\n false\n } else {\n // Safety: Take a hint of the comparison and verify it\n unsafe {\n if field_less_than(a, b) {\n assert_gt(b, a);\n false\n } else {\n assert_gt(a, b);\n true\n }\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::{assert_gt, decompose, gt, lte_hint, PHI, PLO, TWO_POW_128};\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 unconstrained fn check_lte_hint() {\n assert(lte_hint(0, 1));\n assert(lte_hint(0, 0x100));\n assert(lte_hint(0x100, TWO_POW_128 - 1));\n assert(!lte_hint(0 - 1, 0));\n\n assert(lte_hint(0, 0));\n assert(lte_hint(0x100, 0x100));\n assert(lte_hint(0 - 1, 0 - 1));\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" - }, - "178": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/utils/array/append.nr", - "source": "/// Appends two `BoundedVec`s together, returning one that contains all of the elements of the first one followed by all\n/// of the elements of the second one. The resulting `BoundedVec` can have any arbitrary maximum length, but it must be\n/// large enough to fit all of the elements of both the first and second vectors.\npub fn append(\n a: BoundedVec,\n b: BoundedVec,\n) -> BoundedVec {\n let mut dst = BoundedVec::new();\n\n dst.extend_from_bounded_vec(a);\n dst.extend_from_bounded_vec(b);\n\n dst\n}\n\nmod test {\n use super::append;\n\n #[test]\n unconstrained fn append_empty_vecs() {\n let a: BoundedVec<_, 3> = BoundedVec::new();\n let b: BoundedVec<_, 14> = BoundedVec::new();\n\n let result: BoundedVec = append(a, b);\n\n assert_eq(result.len(), 0);\n assert_eq(result.storage(), std::mem::zeroed());\n }\n\n #[test]\n unconstrained fn append_non_empty_vecs() {\n let a: BoundedVec<_, 3> = BoundedVec::from_array([1, 2, 3]);\n let b: BoundedVec<_, 14> = BoundedVec::from_array([4, 5, 6]);\n\n let result: BoundedVec = append(a, b);\n\n assert_eq(result.len(), 6);\n assert_eq(result.storage(), [1, 2, 3, 4, 5, 6, std::mem::zeroed(), std::mem::zeroed()]);\n }\n\n #[test(should_fail_with = \"out of bounds\")]\n unconstrained fn append_non_empty_vecs_insufficient_max_len() {\n let a: BoundedVec<_, 3> = BoundedVec::from_array([1, 2, 3]);\n let b: BoundedVec<_, 14> = BoundedVec::from_array([4, 5, 6]);\n\n let _: BoundedVec = append(a, b);\n }\n}\n" - }, - "18": { - "path": "std/field/mod.nr", - "source": "pub mod bn254;\nuse crate::{runtime::is_unconstrained, static_assert};\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n /// Asserts that `self` can be represented in `bit_size` bits.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^{bit_size}`.\n // docs:start:assert_max_bit_size\n pub fn assert_max_bit_size(self) {\n // docs:end:assert_max_bit_size\n static_assert(\n BIT_SIZE < modulus_num_bits() as u32,\n \"BIT_SIZE must be less than modulus_num_bits\",\n );\n self.__assert_max_bit_size(BIT_SIZE);\n }\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n /// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n /// This slice will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n /// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n /// wrap around due to overflow when verifying the decomposition.\n #[builtin(to_le_bits)]\n fn _to_le_bits(self: Self) -> [u1; N] {}\n\n /// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n /// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n /// wrap around due to overflow when verifying the decomposition.\n #[builtin(to_be_bits)]\n fn _to_be_bits(self: Self) -> [u1; N] {}\n\n /// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n /// This slice will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_le_bits\n pub fn to_le_bits(self: Self) -> [u1; N] {\n // docs:end:to_le_bits\n let bits = self._to_le_bits();\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[N - 1 - i] != p[N - 1 - i]) {\n assert(p[N - 1 - i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_be_bits\n pub fn to_be_bits(self: Self) -> [u1; N] {\n // docs:end:to_be_bits\n let bits = self._to_be_bits();\n\n if !is_unconstrained() {\n // Ensure that the decomposition does not overflow the modulus\n let p = modulus_be_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[i] != p[i]) {\n assert(p[i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its little endian byte decomposition as a `[u8;N]` array\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_le_bytes\n pub fn to_le_bytes(self: Self) -> [u8; N] {\n // docs:end:to_le_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_le_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[N - 1 - i] != p[N - 1 - i]) {\n assert(bytes[N - 1 - i] < p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n /// Decomposes `self` into its big endian byte decomposition as a `[u8;N]` array of length required to represent the field modulus\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_be_bytes\n pub fn to_be_bytes(self: Self) -> [u8; N] {\n // docs:end:to_be_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_be_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_be_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[i] != p[i]) {\n assert(bytes[i] < p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n // docs:start:to_le_radix\n pub fn to_le_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n self.__to_le_radix(radix)\n }\n // docs:end:to_le_radix\n\n // docs:start:to_be_radix\n pub fn to_be_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n crate::assert_constant(radix);\n }\n self.__to_be_radix(radix)\n }\n // docs:end:to_be_radix\n\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32) -> [u8; N] {}\n\n // `_radix` must be less than 256\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32) -> [u8; N] {}\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: [u1; 32] = exponent.to_le_bits();\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 `elem` {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 /// Convert a little endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_le_bytes(bytes: [u8; N]) -> Field {\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[i] as Field) * v;\n v = v * 256;\n }\n result\n }\n\n /// Convert a big endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_be_bytes(bytes: [u8; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[N - 1 - i] as Field) * v;\n v = v * 256;\n }\n result\n }\n}\n\n#[builtin(modulus_num_bits)]\npub comptime fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub comptime fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub comptime fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub comptime fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub comptime fn modulus_le_bytes() -> [u8] {}\n\n/// An unconstrained only built in to efficiently compare fields.\n#[builtin(field_less_than)]\nunconstrained fn __field_less_than(x: Field, y: Field) -> bool {}\n\npub(crate) unconstrained fn field_less_than(x: Field, y: Field) -> bool {\n __field_less_than(x, y)\n}\n\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 if is_unconstrained() {\n // Safety: unconstrained context\n unsafe {\n field_less_than(x, y)\n }\n } else {\n let x_bytes: [u8; 32] = x.to_le_bytes();\n let y_bytes: [u8; 32] = y.to_le_bytes();\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..32 {\n if (!done) {\n let x_byte = x_bytes[32 - 1 - i] as u8;\n let y_byte = y_bytes[32 - 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\nmod tests {\n use crate::{panic::panic, runtime};\n use super::field_less_than;\n\n #[test]\n // docs:start:to_be_bits_example\n fn test_to_be_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_be_bits();\n assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]);\n }\n // docs:end:to_be_bits_example\n\n #[test]\n // docs:start:to_le_bits_example\n fn test_to_le_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_le_bits();\n assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]);\n }\n // docs:end:to_le_bits_example\n\n #[test]\n // docs:start:to_be_bytes_example\n fn test_to_be_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_be_bytes();\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_bytes_example\n\n #[test]\n // docs:start:to_le_bytes_example\n fn test_to_le_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_le_bytes();\n assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_bytes_example\n\n #[test]\n // docs:start:to_be_radix_example\n fn test_to_be_radix() {\n // 259, in base 256, big endian, is [1, 3].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_be_radix(256);\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 1, 3]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_radix_example\n\n #[test]\n // docs:start:to_le_radix_example\n fn test_to_le_radix() {\n // 259, in base 256, little endian, is [3, 1].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_le_radix(256);\n assert_eq(bytes, [3, 1, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_radix_example\n\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n // TODO: Update this test to account for the Brillig restriction that the radix must be greater than 2\n //#[test]\n //fn test_to_le_radix_brillig_1() {\n // // this test should only fail in constrained mode\n // if runtime::is_unconstrained() {\n // let field = 1;\n // let out: [u8; 8] = field.to_le_radix(1);\n // crate::println(out);\n // let expected = [0; 8];\n // assert(out == expected, \"unexpected result\");\n // }\n //}\n\n #[test(should_fail_with = \"radix must be a power of 2\")]\n fn test_to_le_radix_3() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(3);\n } else {\n panic(f\"radix must be a power of 2\");\n }\n }\n\n #[test]\n fn test_to_le_radix_brillig_3() {\n // this test should only fail in constrained mode\n if runtime::is_unconstrained() {\n let field = 1;\n let out: [u8; 8] = field.to_le_radix(3);\n let mut expected = [0; 8];\n expected[0] = 1;\n assert(out == expected, \"unexpected result\");\n }\n }\n\n #[test(should_fail_with = \"radix must be less than or equal to 256\")]\n fn test_to_le_radix_512() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(512);\n } else {\n panic(f\"radix must be less than or equal to 256\")\n }\n }\n\n // TODO: Update this test to account for the Brillig restriction that the radix must be less than 512\n //#[test]\n //fn test_to_le_radix_brillig_512() {\n // // this test should only fail in constrained mode\n // if runtime::is_unconstrained() {\n // let field = 1;\n // let out: [u8; 8] = field.to_le_radix(512);\n // let mut expected = [0; 8];\n // expected[0] = 1;\n // assert(out == expected, \"unexpected result\");\n // }\n //}\n\n #[test]\n unconstrained fn test_field_less_than() {\n assert(field_less_than(0, 1));\n assert(field_less_than(0, 0x100));\n assert(field_less_than(0x100, 0 - 1));\n assert(!field_less_than(0 - 1, 0));\n }\n}\n" - }, - "181": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/utils/array/subarray.nr", - "source": "/// Returns `DST_LEN` elements from a source array, starting at `offset`. `DST_LEN` must not be larger than the number\n/// of elements past `offset`.\n///\n/// Examples:\n/// ```\n/// let foo: [Field; 2] = subarray([1, 2, 3, 4, 5], 2);\n/// assert_eq(foo, [3, 4]);\n///\n/// let bar: [Field; 5] = subarray([1, 2, 3, 4, 5], 2); // fails - we can't return 5 elements since only 3 remain\n/// ```\npub fn subarray(\n src: [T; SRC_LEN],\n offset: u32,\n) -> [T; DST_LEN] {\n assert(offset + DST_LEN <= SRC_LEN, \"DST_LEN too large for offset\");\n\n let mut dst: [T; DST_LEN] = std::mem::zeroed();\n for i in 0..DST_LEN {\n dst[i] = src[i + offset];\n }\n\n dst\n}\n\nmod test {\n use super::subarray;\n\n #[test]\n unconstrained fn subarray_into_empty() {\n // In all of these cases we're setting DST_LEN to be 0, so we always get back an emtpy array.\n assert_eq(subarray::([], 0), []);\n assert_eq(subarray([1, 2, 3, 4, 5], 0), []);\n assert_eq(subarray([1, 2, 3, 4, 5], 2), []);\n }\n\n #[test]\n unconstrained fn subarray_complete() {\n assert_eq(subarray::([], 0), []);\n assert_eq(subarray([1, 2, 3, 4, 5], 0), [1, 2, 3, 4, 5]);\n }\n\n #[test]\n unconstrained fn subarray_different_end_sizes() {\n // We implicitly select how many values to read in the size of the return array\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2, 3, 4, 5]);\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2, 3, 4]);\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2, 3]);\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2]);\n }\n\n #[test(should_fail_with = \"DST_LEN too large for offset\")]\n unconstrained fn subarray_offset_too_large() {\n // With an offset of 1 we can only request up to 4 elements\n let _: [_; 5] = subarray([1, 2, 3, 4, 5], 1);\n }\n\n #[test(should_fail)]\n unconstrained fn subarray_bad_return_value() {\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [3, 3, 4, 5]);\n }\n}\n" - }, - "182": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/utils/array/subbvec.nr", - "source": "use crate::utils::array;\n\n/// Returns `DST_MAX_LEN` elements from a source BoundedVec, starting at `offset`. `offset` must not be larger than the\n/// original length, and `DST_LEN` must not be larger than the total number of elements past `offset` (including the\n/// zeroed elements past `len()`).\n///\n/// Only elements at the beginning of the vector can be removed: it is not possible to also remove elements at the end\n/// of the vector by passing a value for `DST_LEN` that is smaller than `len() - offset`.\n///\n/// Examples:\n/// ```\n/// let foo = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n/// assert_eq(subbvec(foo, 2), BoundedVec::<_, 8>::from_array([3, 4, 5]));\n///\n/// let bar: BoundedVec<_, 1> = subbvec(foo, 2); // fails - we can't return just 1 element since 3 remain\n/// let baz: BoundedVec<_, 10> = subbvec(foo, 3); // fails - we can't return 10 elements since only 7 remain\n/// ```\npub fn subbvec(\n bvec: BoundedVec,\n offset: u32,\n) -> BoundedVec {\n // from_parts_unchecked does not verify that the elements past len are zeroed, but that is not an issue in our case\n // because we're constructing the new storage array as a subarray of the original one (which should have zeroed\n // storage past len), guaranteeing correctness. This is because `subarray` does not allow extending arrays past\n // their original length.\n BoundedVec::from_parts_unchecked(array::subarray(bvec.storage(), offset), bvec.len() - offset)\n}\n\nmod test {\n use super::subbvec;\n\n #[test]\n unconstrained fn subbvec_empty() {\n let bvec = BoundedVec::::from_array([]);\n assert_eq(subbvec(bvec, 0), bvec);\n }\n\n #[test]\n unconstrained fn subbvec_complete() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n assert_eq(subbvec(bvec, 0), bvec);\n\n let smaller_capacity = BoundedVec::<_, 5>::from_array([1, 2, 3, 4, 5]);\n assert_eq(subbvec(bvec, 0), smaller_capacity);\n }\n\n #[test]\n unconstrained fn subbvec_partial() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n assert_eq(subbvec(bvec, 2), BoundedVec::<_, 8>::from_array([3, 4, 5]));\n assert_eq(subbvec(bvec, 2), BoundedVec::<_, 3>::from_array([3, 4, 5]));\n }\n\n #[test]\n unconstrained fn subbvec_into_empty() {\n let bvec: BoundedVec<_, 10> = BoundedVec::from_array([1, 2, 3, 4, 5]);\n assert_eq(subbvec(bvec, 5), BoundedVec::<_, 5>::from_array([]));\n }\n\n #[test(should_fail)]\n unconstrained fn subbvec_offset_past_len() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n let _: BoundedVec<_, 1> = subbvec(bvec, 6);\n }\n\n #[test(should_fail)]\n unconstrained fn subbvec_insufficient_dst_len() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n // We're not providing enough space to hold all of the items inside the original BoundedVec. subbvec can cause\n // for the capacity to reduce, but not the length (other than by len - offset).\n let _: BoundedVec<_, 1> = subbvec(bvec, 2);\n }\n\n #[test(should_fail_with = \"DST_LEN too large for offset\")]\n unconstrained fn subbvec_dst_len_causes_enlarge() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n // subbvec does not supprt capacity increases\n let _: BoundedVec<_, 11> = subbvec(bvec, 0);\n }\n\n #[test(should_fail_with = \"DST_LEN too large for offset\")]\n unconstrained fn subbvec_dst_len_too_large_for_offset() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n // This effectively requests a capacity increase, since there'd be just one element plus the 5 empty slots,\n // which is less than 7.\n let _: BoundedVec<_, 7> = subbvec(bvec, 4);\n }\n}\n" - }, - "184": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/utils/conversion/bytes_to_fields.nr", - "source": "use std::static_assert;\n\n// These functions are used to facilitate the conversion of log ciphertext between byte and field representations.\n//\n// `bytes_to_fields` uses fixed-size arrays since encryption contexts have compile-time size information.\n// `bytes_from_fields` uses BoundedVec for flexibility in unconstrained contexts where sizes are dynamic.\n//\n// Together they provide bidirectional conversion between bytes and fields when processing encrypted logs.\n\n/// Converts the input bytes into an array of fields. A Field is ~254 bits meaning that each field can store 31 whole\n/// bytes. Use `bytes_from_fields` to obtain the original bytes array.\n///\n/// The input bytes are chunked into chunks of 31 bytes. Each 31-byte chunk is viewed as big-endian, and is converted\n/// into a Field.\n/// For example, [1, 10, 3, ..., 0] (31 bytes) is encoded as [1 * 256^30 + 10 * 256^29 + 3 * 256^28 + ... + 0]\n/// Note: N must be a multiple of 31 bytes\npub fn bytes_to_fields(bytes: [u8; N]) -> [Field; N / 31] {\n // Assert that N is a multiple of 31\n static_assert(N % 31 == 0, \"N must be a multiple of 31\");\n\n let mut fields = [0; N / 31];\n\n // Since N is a multiple of 31, we can simply process all chunks fully\n for i in 0..N / 31 {\n let mut field = 0;\n for j in 0..31 {\n // Shift the existing value left by 8 bits and add the new byte\n field = field * 256 + bytes[i * 31 + j] as Field;\n }\n fields[i] = field;\n }\n\n fields\n}\n\n/// Converts an input BoundedVec of fields into a BoundedVec of bytes in big-endian order. Arbitrary Field arrays\n/// are not allowed: this is assumed to be an array obtained via `bytes_to_fields`, i.e. one that actually represents\n/// bytes. To convert a Field array into bytes, use `fields_to_bytes`.\n///\n/// Each input field must contain at most 31 bytes (this is constrained to be so).\n/// Each field is converted into 31 big-endian bytes, and the resulting 31-byte chunks are concatenated\n/// back together in the order of the original fields.\npub fn bytes_from_fields(fields: BoundedVec) -> BoundedVec {\n let mut bytes = BoundedVec::new();\n\n for i in 0..fields.len() {\n let field = fields.get(i);\n\n // We expect that the field contains at most 31 bytes of information.\n field.assert_max_bit_size::<248>();\n\n // Now we can safely convert the field to 31 bytes.\n let field_as_bytes: [u8; 31] = field.to_be_bytes();\n\n for j in 0..31 {\n bytes.push(field_as_bytes[j]);\n }\n }\n\n bytes\n}\n\nmod tests {\n use crate::utils::array::subarray;\n use super::{bytes_from_fields, bytes_to_fields};\n\n #[test]\n unconstrained fn random_bytes_to_fields_and_back(input: [u8; 93]) {\n let fields = bytes_to_fields(input);\n\n // At this point in production, the log flies through the system and we get a BoundedVec on the other end.\n // So we need to convert the field array to a BoundedVec to be able to feed it to the `bytes_from_fields`\n // function.\n let fields_as_bounded_vec = BoundedVec::<_, 6>::from_array(fields);\n\n let bytes_back = bytes_from_fields(fields_as_bounded_vec);\n\n // Compare the original input with the round-tripped result\n assert_eq(bytes_back.len(), input.len());\n assert_eq(subarray(bytes_back.storage(), 0), input);\n }\n\n #[test(should_fail_with = \"N must be a multiple of 31\")]\n unconstrained fn bytes_to_fields_input_length_not_multiple_of_31() {\n // Try to convert 32 bytes (not a multiple of 31) to fields\n let _fields = bytes_to_fields([0; 32]);\n }\n\n}\n" - }, - "185": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/utils/conversion/fields_to_bytes.nr", - "source": "// These functions are used to facilitate the conversion of log plaintext represented as fields into bytes and back.\n//\n// `fields_to_bytes` uses fixed-size arrays since encryption contexts have compile-time size information.\n// `fields_from_bytes` uses BoundedVec for flexibility in unconstrained contexts where sizes are dynamic.\n//\n// Together they provide bidirectional conversion between fields and bytes.\n\n/// Converts an input array of fields into a single array of bytes. Use `fields_from_bytes` to obtain the original\n/// field array.\n/// Each field is converted to a 32-byte big-endian array.\n///\n/// For example, if you have a field array [123, 456], it will be converted to a 64-byte array:\n/// [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,123, // First field (32 bytes)\n/// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,200] // Second field (32 bytes)\n///\n/// Since a field is ~254 bits, you'll end up with a subtle 2-bit \"gap\" at the big end, every 32 bytes. Be careful\n/// that such a gap doesn't leak information! This could happen if you for example expected the output to be\n/// indistinguishable from random bytes.\npub fn fields_to_bytes(fields: [Field; N]) -> [u8; 32 * N] {\n let mut bytes = [0; 32 * N];\n\n for i in 0..N {\n let field_as_bytes: [u8; 32] = fields[i].to_be_bytes();\n\n for j in 0..32 {\n bytes[i * 32 + j] = field_as_bytes[j];\n }\n }\n\n bytes\n}\n\n/// Converts an input BoundedVec of bytes into a BoundedVec of fields. Arbitrary byte arrays are not allowed: this\n/// is assumed to be an array obtained via `fields_to_bytes`, i.e. one that actually represents fields. To convert\n/// a byte array into Fields, use `bytes_to_fields`.\n///\n/// The input bytes are chunked into chunks of 32 bytes. Each 32-byte chunk is viewed as big-endian, and is converted\n/// into a Field.\n/// For example, [1, 10, 3, ..., 0] (32 bytes) is encoded as [1 * 256^31 + 10 * 256^30 + 3 * 256^29 + ... + 0]\n/// Note 1: N must be a multiple of 32 bytes\n/// Note 2: The max value check code was taken from std::field::to_be_bytes function.\npub fn fields_from_bytes(bytes: BoundedVec) -> BoundedVec {\n // Assert that input length is a multiple of 32\n assert(bytes.len() % 32 == 0, \"Input length must be a multiple of 32\");\n\n let mut fields = BoundedVec::new();\n\n let p = std::field::modulus_be_bytes();\n\n // Since input length is a multiple of 32, we can simply process all chunks fully\n for i in 0..bytes.len() / 32 {\n let mut field = 0;\n\n // Process each byte in the 32-byte chunk\n let mut ok = false;\n\n for j in 0..32 {\n let next_byte = bytes.get(i * 32 + j);\n field = field * 256 + next_byte as Field;\n\n if !ok {\n if next_byte != p[j] {\n assert(next_byte < p[j], \"Value does not fit in field\");\n ok = true;\n }\n }\n }\n assert(ok, \"Value does not fit in field\");\n\n fields.push(field);\n }\n\n fields\n}\n\nmod tests {\n use crate::utils::array::subarray;\n use super::{fields_from_bytes, fields_to_bytes};\n\n #[test]\n unconstrained fn random_fields_to_bytes_and_back(input: [Field; 3]) {\n // Convert to bytes\n let bytes = fields_to_bytes(input);\n\n // At this point in production, the log flies through the system and we get a BoundedVec on the other end.\n // So we need to convert the field array to a BoundedVec to be able to feed it to the `fields_from_bytes`\n // function.\n // 113 is an arbitrary max length that is larger than the input length of 96.\n let bytes_as_bounded_vec = BoundedVec::<_, 113>::from_array(bytes);\n\n // Convert back to fields\n let fields_back = fields_from_bytes(bytes_as_bounded_vec);\n\n // Compare the original input with the round-tripped result\n assert_eq(fields_back.len(), input.len());\n assert_eq(subarray(fields_back.storage(), 0), input);\n }\n\n #[test(should_fail_with = \"Input length must be a multiple of 32\")]\n unconstrained fn to_fields_assert() {\n // 143 is an arbitrary max length that is larger than 33\n let input = BoundedVec::<_, 143>::from_array([\n 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n 25, 26, 27, 28, 29, 30, 31, 32, 33,\n ]);\n\n // This should fail since 33 is not a multiple of 32\n let _fields = fields_from_bytes(input);\n }\n\n #[test]\n unconstrained fn fields_from_bytes_max_value() {\n let max_field_as_bytes: [u8; 32] = (-1).to_be_bytes();\n let input = BoundedVec::<_, 32>::from_array(max_field_as_bytes);\n\n let fields = fields_from_bytes(input);\n\n // The result should be a largest value storable in a field (-1 since we are modulo-ing)\n assert_eq(fields.get(0), -1);\n }\n\n // In this test we verify that overflow check works by taking the max allowed value, bumping a random byte\n // and then feeding it to `fields_from_bytes` as input.\n #[test(should_fail_with = \"Value does not fit in field\")]\n unconstrained fn fields_from_bytes_overflow(random_value: u8) {\n let index_of_byte_to_bump = random_value % 32;\n\n // Obtain the byte representation of the maximum field value\n let max_field_value_as_bytes: [u8; 32] = (-1).to_be_bytes();\n\n let byte_to_bump = max_field_value_as_bytes[index_of_byte_to_bump as u32];\n\n // Skip test execution if the selected byte is already at maximum value (255).\n // This is acceptable since we are using fuzz testing to generate many test cases.\n if byte_to_bump != 255 {\n let mut input = BoundedVec::<_, 32>::from_array(max_field_value_as_bytes);\n\n // Increment the selected byte to exceed the field's maximum value\n input.set(index_of_byte_to_bump as u32, byte_to_bump + 1);\n\n // Attempt the conversion, which should fail due to the value exceeding the field's capacity\n let _fields = fields_from_bytes(input);\n }\n }\n\n}\n" - }, - "187": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/utils/field.nr", - "source": "use std::option::Option;\n\nglobal KNOWN_NON_RESIDUE: Field = 5; // This is a non-residue in Noir's native Field.\n\nglobal C1: u32 = 28;\nglobal C3: Field = 40770029410420498293352137776570907027550720424234931066070132305055;\nglobal C5: Field = 19103219067921713944291392827692070036145651957329286315305642004821462161904;\n\n// Power function of two Field arguments of arbitrary size.\n// Adapted from std::field::pow_32.\npub fn pow(x: Field, y: Field) -> Field {\n let mut r = 1 as Field;\n let b: [u1; 254] = y.to_le_bits();\n\n for i in 0..254 {\n r *= r;\n r *= (b[254 - 1 - i] as Field) * x + (1 - b[254 - 1 - i] as Field);\n }\n\n r\n}\n\n// Boolean indicating whether Field element is a square, i.e. whether there exists a y in Field s.t. x = y*y.\nunconstrained fn is_square(x: Field) -> bool {\n let v = pow(x, -1 / 2);\n v * (v - 1) == 0\n}\n\n// Tonelli-Shanks algorithm for computing the square root of a Field element.\n// Requires C1 = max{c: 2^c divides (p-1)}, where p is the order of Field\n// as well as C3 = (C2 - 1)/2, where C2 = (p-1)/(2^c1),\n// and C5 = ZETA^C2, where ZETA is a non-square element of Field.\n// These are pre-computed above as globals.\nunconstrained fn tonelli_shanks_sqrt(x: Field) -> Field {\n let mut z = pow(x, C3);\n let mut t = z * z * x;\n z *= x;\n let mut b = t;\n let mut c = C5;\n\n for i in 0..(C1 - 1) {\n for _j in 1..(C1 - i - 1) {\n b *= b;\n }\n\n z *= if b == 1 { 1 } else { c };\n\n c *= c;\n\n t *= if b == 1 { 1 } else { c };\n\n b = t;\n }\n\n z\n}\n\n// NB: this doesn't return an option, because in the case of there _not_ being a square root, we still want to return a field element that allows us to then assert in the _constrained_ sqrt function that there is no sqrt.\npub unconstrained fn __sqrt(x: Field) -> (bool, Field) {\n let is_sq = is_square(x);\n if is_sq {\n let sqrt = tonelli_shanks_sqrt(x);\n (true, sqrt)\n } else {\n // Demonstrate that x is not a square (a.k.a. a \"quadratic non-residue\").\n // Facts:\n // The Legendre symbol (\"LS\") of x, is x^((p-1)/2) (mod p).\n // - If x is a square, LS(x) = 1\n // - If x is not a square, LS(x) = -1\n // - If x = 0, LS(x) = 0.\n //\n // Hence:\n // sq * sq = sq // 1 * 1 = 1\n // non-sq * non-sq = sq // -1 * -1 = 1\n // sq * non-sq = non-sq // -1 * 1 = -1\n //\n // See: https://en.wikipedia.org/wiki/Legendre_symbol\n let demo_x_not_square = x * KNOWN_NON_RESIDUE;\n let not_sqrt = tonelli_shanks_sqrt(demo_x_not_square);\n (false, not_sqrt)\n }\n}\n\n// Returns (false, 0) if there is no square root.\n// Returns (true, sqrt) if there is a square root.\npub fn sqrt(x: Field) -> Option {\n // Safety: if the hint returns the square root of x, then we simply square it\n // check the result equals x. If x is not square, we return a value that\n // enables us to prove that fact (see the `else` clause below).\n let (is_sq, maybe_sqrt) = unsafe { __sqrt(x) };\n\n if is_sq {\n let sqrt = maybe_sqrt;\n validate_sqrt_hint(x, sqrt);\n Option::some(sqrt)\n } else {\n let not_sqrt_hint = maybe_sqrt;\n validate_not_sqrt_hint(x, not_sqrt_hint);\n Option::none()\n }\n}\n\nfn validate_sqrt_hint(x: Field, hint: Field) {\n assert(hint * hint == x, f\"The claimed_sqrt {hint} is not the sqrt of x {x}\");\n}\n\nfn validate_not_sqrt_hint(x: Field, hint: Field) {\n // We need this assertion, because x = 0 would pass the other assertions in this\n // function, and we don't want people to be able to prove that 0 is not square!\n assert(x != 0, \"0 has a square root; you cannot claim it is not square\");\n // Demonstrate that x is not a square (a.k.a. a \"quadratic non-residue\").\n //\n // Facts:\n // The Legendre symbol (\"LS\") of x, is x^((p-1)/2) (mod p).\n // - If x is a square, LS(x) = 1\n // - If x is not a square, LS(x) = -1\n // - If x = 0, LS(x) = 0.\n //\n // Hence:\n // 1. sq * sq = sq // 1 * 1 = 1\n // 2. non-sq * non-sq = sq // -1 * -1 = 1\n // 3. sq * non-sq = non-sq // -1 * 1 = -1\n //\n // See: https://en.wikipedia.org/wiki/Legendre_symbol\n //\n // We want to demonstrate that this below multiplication falls under bullet-point (2):\n let demo_x_not_square = x * KNOWN_NON_RESIDUE;\n // I.e. we want to demonstrate that `demo_x_not_square` has Legendre symbol 1\n // (i.e. that it is a square), so we prove that it is square below.\n // Why do we want to prove that it has LS 1?\n // Well, since it was computed with a known-non-residue, its squareness implies we're\n // in case 2 (something multiplied by a known-non-residue yielding a result which\n // has a LS of 1), which implies that x must be a non-square. The unconstrained\n // function gave us the sqrt of demo_x_not_square, so all we need to do is\n // assert its squareness:\n assert(\n hint * hint == demo_x_not_square,\n f\"The hint {hint} does not demonstrate that {x} is not a square\",\n );\n}\n\n#[test]\nfn test_sqrt() {\n let x = 9;\n let maybe_sqrt = sqrt(x);\n assert(maybe_sqrt.is_some());\n let sqrt = maybe_sqrt.unwrap_unchecked();\n assert((sqrt == 3) | (sqrt == -3));\n}\n\n#[test]\nfn test_non_square() {\n let x = 5;\n let maybe_sqrt = sqrt(x);\n assert(maybe_sqrt.is_none());\n}\n\n#[test]\nunconstrained fn test_known_non_residue_is_actually_a_non_residue_in_the_field() {\n assert(!is_square(KNOWN_NON_RESIDUE));\n}\n\n#[test]\nfn test_sqrt_0() {\n let x = 0;\n let sqrt = sqrt(x).unwrap();\n assert(sqrt == 0);\n}\n\n#[test]\nfn test_sqrt_1() {\n let x = 1;\n let sqrt = sqrt(x).unwrap();\n assert((sqrt == 1) | (sqrt == -1));\n}\n\n#[test(should_fail_with = \"The claimed_sqrt 0x04 is not the sqrt of x 0x09\")]\nfn test_bad_sqrt_hint_fails() {\n validate_sqrt_hint(9, 4);\n}\n\n#[test(should_fail_with = \"The hint 0x04 does not demonstrate that 0x0a is not a square\")]\nfn test_bad_not_sqrt_hint_fails() {\n validate_not_sqrt_hint(10, 4);\n}\n\n#[test(should_fail_with = \"0 has a square root; you cannot claim it is not square\")]\nfn test_0_not_sqrt_hint_fails() {\n validate_not_sqrt_hint(0, 0);\n}\n\n#[test]\nunconstrained fn test_is_square() {\n assert(is_square(25));\n}\n\n#[test]\nunconstrained fn test_is_not_square() {\n assert(!is_square(10));\n}\n" - }, - "189": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/utils/point.nr", - "source": "use crate::utils::field::sqrt;\nuse dep::protocol_types::point::Point;\n\n// I am storing the modulus minus 1 divided by 2 here because full modulus would throw \"String literal too large\" error\n// Full modulus is 21888242871839275222246405745257275088548364400416034343698204186575808495617\nglobal BN254_FR_MODULUS_DIV_2: Field =\n 10944121435919637611123202872628637544274182200208017171849102093287904247808;\n\n/// Converts a point to a byte array.\n///\n/// We don't serialize the point at infinity flag because this function is used in situations where we do not want\n/// to waste the extra byte (encrypted log).\npub fn point_to_bytes(p: Point) -> [u8; 32] {\n // Note that there is 1 more free bit in the 32 bytes (254 bits currently occupied by the x coordinate, 1 bit for\n // the \"sign\") so it's possible to use that last bit as an \"is_infinite\" flag if desired in the future.\n assert(!p.is_infinite, \"Cannot serialize point at infinity as bytes.\");\n\n let mut result: [u8; 32] = p.x.to_be_bytes();\n\n if get_sign_of_point(p) {\n // y is <= (modulus - 1) / 2 so we set the sign bit to 1\n // Here we leverage that field fits into 254 bits (log2(Fr.MODULUS) < 254) and given that we serialize Fr to 32\n // bytes and we use big-endian the 2 most significant bits are never populated. Hence we can use one of\n // the bits as a sign bit.\n result[0] += 128;\n }\n\n result\n}\n\n/**\n * Returns: true if p.y <= MOD_DIV_2, else false.\n */\npub fn get_sign_of_point(p: Point) -> bool {\n // We store only a \"sign\" of the y coordinate because the rest can be derived from the x coordinate. To get\n // the sign we check if the y coordinate is less or equal than the curve's order minus 1 divided by 2.\n // Ideally we'd do `y <= MOD_DIV_2`, but there's no `lte` function, so instead we do `!(y > MOD_DIV_2)`, which is\n // equivalent, and then rewrite that as `!(MOD_DIV_2 < y)`, since we also have no `gt` function.\n !BN254_FR_MODULUS_DIV_2.lt(p.y)\n}\n\npub fn point_from_x_coord(x: Field) -> Point {\n // y ^ 2 = x ^ 3 - 17\n let rhs = x * x * x - 17;\n let y = sqrt(rhs).unwrap();\n Point { x, y, is_infinite: false }\n}\n\n/// Uses the x coordinate and sign flag (+/-) to reconstruct the point.\n/// The y coordinate can be derived from the x coordinate and the \"sign\" flag by solving the grumpkin curve\n/// equation for y.\n/// @param x - The x coordinate of the point\n/// @param sign - The \"sign\" of the y coordinate - determines whether y <= (Fr.MODULUS - 1) / 2\npub fn point_from_x_coord_and_sign(x: Field, sign: bool) -> Point {\n // y ^ 2 = x ^ 3 - 17\n let rhs = x * x * x - 17;\n let y = sqrt(rhs).unwrap();\n\n // If y > MOD_DIV_2 and we want positive sign (or vice versa), negate y\n let y_is_positive = !BN254_FR_MODULUS_DIV_2.lt(y);\n let final_y = if y_is_positive == sign { y } else { -y };\n\n Point { x, y: final_y, is_infinite: false }\n}\n\nmod test {\n use crate::utils::point::{point_from_x_coord_and_sign, point_to_bytes};\n use dep::protocol_types::point::Point;\n\n #[test]\n unconstrained fn test_point_to_bytes_positive_sign() {\n let p = Point {\n x: 0x1af41f5de96446dc3776a1eb2d98bb956b7acd9979a67854bec6fa7c2973bd73,\n y: 0x07fc22c7f2c7057571f137fe46ea9c95114282bc95d37d71ec4bfb88de457d4a,\n is_infinite: false,\n };\n\n let compressed_point = point_to_bytes(p);\n\n let expected_compressed_point_positive_sign = [\n 154, 244, 31, 93, 233, 100, 70, 220, 55, 118, 161, 235, 45, 152, 187, 149, 107, 122,\n 205, 153, 121, 166, 120, 84, 190, 198, 250, 124, 41, 115, 189, 115,\n ];\n assert_eq(expected_compressed_point_positive_sign, compressed_point);\n }\n\n #[test]\n unconstrained fn test_point_to_bytes_negative_sign() {\n let p = Point {\n x: 0x247371652e55dd74c9af8dbe9fb44931ba29a9229994384bd7077796c14ee2b5,\n y: 0x26441aec112e1ae4cee374f42556932001507ad46e255ffb27369c7e3766e5c0,\n is_infinite: false,\n };\n\n let compressed_point = point_to_bytes(p);\n\n let expected_compressed_point_negative_sign = [\n 36, 115, 113, 101, 46, 85, 221, 116, 201, 175, 141, 190, 159, 180, 73, 49, 186, 41, 169,\n 34, 153, 148, 56, 75, 215, 7, 119, 150, 193, 78, 226, 181,\n ];\n\n assert_eq(expected_compressed_point_negative_sign, compressed_point);\n }\n\n #[test]\n unconstrained fn test_point_from_x_coord_and_sign() {\n // Test positive y coordinate\n let x = 0x1af41f5de96446dc3776a1eb2d98bb956b7acd9979a67854bec6fa7c2973bd73;\n let sign = true;\n let p = point_from_x_coord_and_sign(x, sign);\n\n assert_eq(p.x, x);\n assert_eq(p.y, 0x07fc22c7f2c7057571f137fe46ea9c95114282bc95d37d71ec4bfb88de457d4a);\n assert_eq(p.is_infinite, false);\n\n // Test negative y coordinate\n let x2 = 0x247371652e55dd74c9af8dbe9fb44931ba29a9229994384bd7077796c14ee2b5;\n let sign2 = false;\n let p2 = point_from_x_coord_and_sign(x2, sign2);\n\n assert_eq(p2.x, x2);\n assert_eq(p2.y, 0x26441aec112e1ae4cee374f42556932001507ad46e255ffb27369c7e3766e5c0);\n assert_eq(p2.is_infinite, false);\n }\n}\n" - }, - "19": { - "path": "std/hash/mod.nr", - "source": "// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\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#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\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#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\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();\n sum += crate::field::bytes32_to_field(blake2s(input_bytes));\n }\n\n sum\n}\n\n#[foreign(poseidon2_permutation)]\npub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: std::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\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.)\npub trait 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.\npub trait BuildHasher\nwhere\n H: Hasher,\n{\n fn build_hasher(self) -> H;\n}\n\npub struct 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)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\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)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\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)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\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\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n" - }, - "193": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/utils/with_hash.nr", - "source": "use crate::{\n context::{PublicContext, UtilityContext},\n history::public_storage::PublicStorageHistoricalRead,\n oracle,\n};\nuse dep::protocol_types::{\n address::AztecAddress, block_header::BlockHeader, hash::poseidon2_hash, traits::Packable,\n};\n\n/// A struct that allows for efficient reading of value `T` from public storage in private.\n///\n/// The efficient reads are achieved by verifying large values through a single hash check\n/// and then proving inclusion only of the hash in public storage. This reduces the number\n/// of required tree inclusion proofs from `N` to 1.\n///\n/// # Type Parameters\n/// - `T`: The underlying type being wrapped, must implement `Packable`\n/// - `N`: The number of field elements required to pack values of type `T`\npub struct WithHash {\n value: T,\n packed: [Field; N],\n hash: Field,\n}\n\nimpl WithHash\nwhere\n T: Packable + Eq,\n{\n pub fn new(value: T) -> Self {\n let packed = value.pack();\n Self { value, packed, hash: poseidon2_hash(packed) }\n }\n\n pub fn get_value(self) -> T {\n self.value\n }\n\n pub fn get_hash(self) -> Field {\n self.hash\n }\n\n pub fn public_storage_read(context: PublicContext, storage_slot: Field) -> T {\n context.storage_read(storage_slot)\n }\n\n pub unconstrained fn utility_public_storage_read(\n context: UtilityContext,\n storage_slot: Field,\n ) -> T {\n context.storage_read(storage_slot)\n }\n\n pub fn historical_public_storage_read(\n header: BlockHeader,\n address: AztecAddress,\n storage_slot: Field,\n ) -> T {\n let historical_block_number = header.global_variables.block_number as u32;\n\n // We could simply produce historical inclusion proofs for each field in `packed`, but that would require one\n // full sibling path per storage slot (since due to kernel siloing the storage is not contiguous). Instead, we\n // get an oracle to provide us the values, and instead we prove inclusion of their hash, which is both a much\n // smaller proof (a single slot), and also independent of the size of T (except in that we need to pack and hash T).\n let hint = WithHash::new(\n // Safety: We verify that a hash of the hint/packed data matches the stored hash.\n unsafe {\n oracle::storage::storage_read(address, storage_slot, historical_block_number)\n },\n );\n\n let hash = header.public_storage_historical_read(storage_slot + N as Field, address);\n\n if hash != 0 {\n assert_eq(hash, hint.get_hash(), \"Hint values do not match hash\");\n } else {\n // The hash slot can only hold a zero if it is uninitialized. Therefore, the hints must then be zero\n // (i.e. the default value for public storage) as well.\n assert_eq(\n hint.get_value(),\n T::unpack(std::mem::zeroed()),\n \"Non-zero hint for zero hash\",\n );\n };\n\n hint.get_value()\n }\n}\n\nimpl Packable for WithHash\nwhere\n T: Packable,\n{\n fn pack(self) -> [Field; N + 1] {\n let mut result: [Field; N + 1] = std::mem::zeroed();\n for i in 0..N {\n result[i] = self.packed[i];\n }\n result[N] = self.hash;\n\n result\n }\n\n fn unpack(packed: [Field; N + 1]) -> Self {\n let mut value_packed: [Field; N] = std::mem::zeroed();\n for i in 0..N {\n value_packed[i] = packed[i];\n }\n let hash = packed[N];\n\n Self { value: T::unpack(value_packed), packed: value_packed, hash }\n }\n}\n\nmod test {\n use crate::{\n oracle::random::random,\n test::{\n helpers::{cheatcodes, test_environment::TestEnvironment},\n mocks::mock_struct::MockStruct,\n },\n utils::with_hash::WithHash,\n };\n use dep::protocol_types::hash::poseidon2_hash;\n use dep::protocol_types::traits::{Packable, ToField};\n use dep::std::{mem, test::OracleMock};\n\n global storage_slot: Field = 47;\n\n #[test]\n unconstrained fn create_and_recover() {\n let value = MockStruct { a: 5, b: 3 };\n let value_with_hash = WithHash::new(value);\n let recovered = WithHash::unpack(value_with_hash.pack());\n\n assert_eq(recovered.value, value);\n assert_eq(recovered.packed, value.pack());\n assert_eq(recovered.hash, poseidon2_hash(value.pack()));\n }\n\n #[test]\n unconstrained fn read_uninitialized_value() {\n let mut env = TestEnvironment::new();\n\n let block_header = env.private().historical_header;\n let address = env.contract_address();\n\n let result = WithHash::::historical_public_storage_read(\n block_header,\n address,\n storage_slot,\n );\n\n // We should get zeroed value\n let expected: MockStruct = mem::zeroed();\n assert_eq(result, expected);\n }\n\n #[test]\n unconstrained fn read_initialized_value() {\n let mut env = TestEnvironment::new();\n\n let value = MockStruct { a: 5, b: 3 };\n let value_with_hash = WithHash::new(value);\n\n // We write the value with hash to storage\n cheatcodes::direct_storage_write(\n env.contract_address(),\n storage_slot,\n value_with_hash.pack(),\n );\n\n // We advance block by 1 because env.private() currently returns context at latest_block - 1\n env.advance_block_by(1);\n\n let result = WithHash::::historical_public_storage_read(\n env.private().historical_header,\n env.contract_address(),\n storage_slot,\n );\n\n assert_eq(result, value);\n }\n\n #[test(should_fail_with = \"Non-zero hint for zero hash\")]\n unconstrained fn test_bad_hint_uninitialized_value() {\n let mut env = TestEnvironment::new();\n\n env.advance_block_to(6);\n\n let value_packed = MockStruct { a: 1, b: 1 }.pack();\n\n let block_header = env.private().historical_header;\n let address = env.contract_address();\n\n // Mock the oracle to return a non-zero hint/packed value\n let _ = OracleMock::mock(\"storageRead\")\n .with_params((\n address.to_field(), storage_slot, block_header.global_variables.block_number as u32,\n value_packed.len(),\n ))\n .returns(value_packed)\n .times(1);\n\n // This should revert because the hint value is non-zero and the hash is zero (default value of storage)\n let _ = WithHash::::historical_public_storage_read(\n block_header,\n address,\n storage_slot,\n );\n }\n\n #[test(should_fail_with = \"Hint values do not match hash\")]\n unconstrained fn test_bad_hint_initialized_value() {\n let mut env = TestEnvironment::new();\n\n let value_packed = MockStruct { a: 5, b: 3 }.pack();\n\n // We write the value to storage\n cheatcodes::direct_storage_write(env.contract_address(), storage_slot, value_packed);\n\n // Now we write incorrect hash to the hash storage slot\n let incorrect_hash = random();\n let hash_storage_slot = storage_slot + (value_packed.len() as Field);\n cheatcodes::direct_storage_write(\n env.contract_address(),\n hash_storage_slot,\n [incorrect_hash],\n );\n\n // We advance block by 1 because env.private() currently returns context at latest_block - 1\n env.advance_block_by(1);\n\n let _ = WithHash::::historical_public_storage_read(\n env.private().historical_header,\n env.contract_address(),\n storage_slot,\n );\n }\n}\n" - }, - "200": { - "path": "/mnt/user-data/saleel/nargo/github.com/noir-lang/poseidon/v0.1.0/src/poseidon2.nr", - "source": "use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct 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 #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n 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) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\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 }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> 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\npub struct 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 { _state: &[] }\n }\n}\n" - }, - "217": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/noir-protocol-circuits/crates/types/src/abis/event_selector.nr", - "source": "use crate::traits::{Deserialize, Empty, FromField, Serialize, ToField};\n\npub struct EventSelector {\n // 1st 4-bytes (big-endian leftmost) of abi-encoding of an event.\n inner: u32,\n}\n\nimpl Eq for EventSelector {\n fn eq(self, other: EventSelector) -> bool {\n other.inner == self.inner\n }\n}\n\nimpl Serialize<1> for EventSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for EventSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self { inner: fields[0] as u32 }\n }\n}\n\nimpl FromField for EventSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for EventSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for EventSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl EventSelector {\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 = crate::hash::poseidon2_hash_bytes(bytes);\n\n // `hash` is automatically truncated to fit within 32 bits.\n EventSelector::from_field(hash)\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n" - }, - "219": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr", - "source": "use crate::traits::{Deserialize, Empty, FromField, Serialize, ToField};\n\npub struct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n pub 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 { inner: fields[0] as u32 }\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 = crate::hash::poseidon2_hash_bytes(bytes);\n\n // `hash` is automatically truncated to fit within 32 bits.\n FunctionSelector::from_field(hash)\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n\n#[test]\nfn test_is_valid_selector() {\n let selector = FunctionSelector::from_signature(\"IS_VALID()\");\n assert_eq(selector.to_field(), 0x73cdda47);\n}\n\n#[test]\nfn test_long_selector() {\n let selector =\n FunctionSelector::from_signature(\"foo_and_bar_and_baz_and_foo_bar_baz_and_bar_foo\");\n assert_eq(selector.to_field(), 0x7590a997);\n}\n" - }, - "262": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr", - "source": "use crate::{\n address::{\n partial_address::PartialAddress, salted_initialization_hash::SaltedInitializationHash,\n },\n constants::{\n AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1, MAX_FIELD_VALUE,\n MAX_PROTOCOL_CONTRACTS,\n },\n contract_class_id::ContractClassId,\n hash::poseidon2_hash_with_separator,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, ToPoint, TpkM},\n traits::{Deserialize, Empty, FromField, Packable, Serialize, ToField},\n utils::field::{pow, sqrt},\n};\n\n// We do below because `use crate::point::Point;` does not work\nuse dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\n\nuse crate::public_keys::AddressPoint;\nuse std::{\n embedded_curve_ops::{EmbeddedCurveScalar, fixed_base_scalar_mul as derive_public_key},\n ops::Add,\n};\n\n// Aztec address\npub struct AztecAddress {\n pub 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 { inner: 0 }\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\n/// We implement the Packable trait for AztecAddress because it can be stored in contract's storage (and there\n/// the implementation of Packable is required).\nimpl Packable for AztecAddress {\n fn pack(self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n self.serialize()\n }\n\n fn unpack(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n Self::deserialize(fields)\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn to_address_point(self) -> AddressPoint {\n // We compute the address point by taking our address, setting it to x, and then solving for y in the\n // equation which defines our bn curve:\n // y^2 = x^3 - 17; x = address\n let x = self.inner;\n let y_squared = pow(x, 3) - 17;\n\n // TODO (#8970): Handle cases where we cannot recover a point from an address\n let mut y = sqrt(y_squared);\n\n // If we get a negative y coordinate (any y where y > MAX_FIELD_VALUE / 2), we pin it to the\n // positive one (any value where y <= MAX_FIELD_VALUE / 2) by subtracting it from the Field modulus\n // note: The field modulus is MAX_FIELD_VALUE + 1\n if (!(y.lt(MAX_FIELD_VALUE / 2) | y.eq(MAX_FIELD_VALUE / 2))) {\n y = (MAX_FIELD_VALUE + 1) - y;\n }\n\n AddressPoint { inner: Point { x: self.inner, y, is_infinite: false } }\n }\n\n pub fn compute(public_keys: PublicKeys, partial_address: PartialAddress) -> AztecAddress {\n let public_keys_hash = public_keys.hash();\n\n let pre_address = poseidon2_hash_with_separator(\n [public_keys_hash.to_field(), partial_address.to_field()],\n GENERATOR_INDEX__CONTRACT_ADDRESS_V1,\n );\n\n let address_point = derive_public_key(EmbeddedCurveScalar::from_field(pre_address)).add(\n public_keys.ivpk_m.to_point(),\n );\n\n // Note that our address is only the x-coordinate of the full address_point. This is okay because when people want to encrypt something and send it to us\n // they can recover our full point using the x-coordinate (our address itself). To do this, they recompute the y-coordinate according to the equation y^2 = x^3 - 17.\n // When they do this, they may get a positive y-coordinate (a value that is less than or equal to MAX_FIELD_VALUE / 2) or\n // a negative y-coordinate (a value that is more than MAX_FIELD_VALUE), and we cannot dictate which one they get and hence the recovered point may sometimes be different than the one\n // our secret can decrypt. Regardless though, they should and will always encrypt using point with the positive y-coordinate by convention.\n // This ensures that everyone encrypts to the same point given an arbitrary x-coordinate (address). This is allowed because even though our original point may not have a positive y-coordinate,\n // with our original secret, we will be able to derive the secret to the point with the flipped (and now positive) y-coordinate that everyone encrypts to.\n AztecAddress::from_field(address_point.x)\n }\n\n pub fn compute_from_class_id(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash,\n public_keys: PublicKeys,\n ) -> Self {\n let partial_address = PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n salted_initialization_hash,\n );\n\n AztecAddress::compute(public_keys, partial_address)\n }\n\n pub fn is_protocol_contract(self) -> bool {\n self.inner.lt(MAX_PROTOCOL_CONTRACTS as 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\n#[test]\nfn compute_address_from_partial_and_pub_keys() {\n let public_keys = PublicKeys {\n npk_m: NpkM {\n inner: Point {\n x: 0x22f7fcddfa3ce3e8f0cc8e82d7b94cdd740afa3e77f8e4a63ea78a239432dcab,\n y: 0x0471657de2b6216ade6c506d28fbc22ba8b8ed95c871ad9f3e3984e90d9723a7,\n is_infinite: false,\n },\n },\n ivpk_m: IvpkM {\n inner: Point {\n x: 0x111223493147f6785514b1c195bb37a2589f22a6596d30bb2bb145fdc9ca8f1e,\n y: 0x273bbffd678edce8fe30e0deafc4f66d58357c06fd4a820285294b9746c3be95,\n is_infinite: false,\n },\n },\n ovpk_m: OvpkM {\n inner: Point {\n x: 0x09115c96e962322ffed6522f57194627136b8d03ac7469109707f5e44190c484,\n y: 0x0c49773308a13d740a7f0d4f0e6163b02c5a408b6f965856b6a491002d073d5b,\n is_infinite: false,\n },\n },\n tpk_m: TpkM {\n inner: Point {\n x: 0x00d3d81beb009873eb7116327cf47c612d5758ef083d4fda78e9b63980b2a762,\n y: 0x2f567d22d2b02fe1f4ad42db9d58a36afd1983e7e2909d1cab61cafedad6193a,\n is_infinite: false,\n },\n },\n };\n\n let partial_address = PartialAddress::from_field(\n 0x0a7c585381b10f4666044266a02405bf6e01fa564c8517d4ad5823493abd31de,\n );\n\n let address = AztecAddress::compute(public_keys, partial_address);\n\n // The following value was generated by `derivation.test.ts`.\n // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data.\n let expected_computed_address_from_partial_and_pubkeys =\n 0x24e4646f58b9fbe7d38e317db8d5636c423fbbdfbe119fc190fe9c64747e0c62;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkeys);\n}\n\n#[test]\nfn compute_preaddress_from_partial_and_pub_keys() {\n let pre_address = poseidon2_hash_with_separator([1, 2], GENERATOR_INDEX__CONTRACT_ADDRESS_V1);\n let expected_computed_preaddress_from_partial_and_pubkey =\n 0x23ce9be3fa3c846b0f9245cc796902e731d04f086e8a42473bb29e405fc98075;\n assert(pre_address == expected_computed_preaddress_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" - }, - "279": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr", - "source": "/// Utility function to console.log data in the acir simulator.\n/// Example:\n/// debug_log(\"blah blah this is a debug string\");\npub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n\n/// Utility function to console.log data in the acir simulator. This variant receives a format string in which the\n/// `${k}` tokens will be replaced with the k-eth value in the `args` array.\n/// Examples:\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]);\npub fn debug_log_format(msg: str, args: [Field; N]) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe { debug_log_oracle_wrapper(msg, args) };\n}\n\npub unconstrained fn debug_log_oracle_wrapper(\n msg: str,\n args: [Field; N],\n) {\n debug_log_oracle(msg, args.as_slice());\n}\n\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#[oracle(debugLog)]\nunconstrained fn debug_log_oracle(_msg: str, args: [Field]) {}\n" - }, - "280": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr", - "source": "use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n contract_class_log::ContractClassLog,\n function_selector::FunctionSelector,\n note_hash::ScopedNoteHash,\n nullifier::ScopedNullifier,\n private_log::{PrivateLog, PrivateLogData},\n side_effect::{OrderedValue, scoped::Scoped},\n },\n address::{AztecAddress, EthAddress},\n constants::{\n CONTRACT_CLASS_LOG_SIZE_IN_FIELDS, FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__NOTE_HASH_NONCE,\n GENERATOR_INDEX__OUTER_NULLIFIER, GENERATOR_INDEX__SILOED_NOTE_HASH,\n GENERATOR_INDEX__UNIQUE_NOTE_HASH, TWO_POW_64,\n },\n merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n poseidon2::Poseidon2Sponge,\n traits::{FromField, Hash, ToField},\n utils::{arrays::array_concat, field::{field_from_bytes, field_from_bytes_32_trunc}},\n};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256::digest(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(\n function_leaf,\n function_leaf_index,\n function_leaf_sibling_path,\n )\n}\n\npub fn compute_note_hash_nonce(first_nullifier_in_tx: Field, note_index_in_tx: u32) -> Field {\n // Hashing the first nullifier with note index in tx is guaranteed to be unique (because all nullifiers are also\n // unique).\n poseidon2_hash_with_separator(\n [first_nullifier_in_tx, note_index_in_tx as Field],\n GENERATOR_INDEX__NOTE_HASH_NONCE,\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, siloed_note_hash: Field) -> Field {\n let inputs = [nonce, siloed_note_hash];\n poseidon2_hash_with_separator(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, note_hash: Field) -> Field {\n poseidon2_hash_with_separator(\n [app.to_field(), note_hash],\n GENERATOR_INDEX__SILOED_NOTE_HASH,\n )\n}\n\n/// Computes unique note hashes from siloed note hashes\npub fn compute_unique_siloed_note_hash(\n siloed_note_hash: Field,\n first_nullifier: Field,\n note_index_in_tx: u32,\n) -> Field {\n if siloed_note_hash == 0 {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, note_index_in_tx);\n compute_unique_note_hash(nonce, siloed_note_hash)\n }\n}\n\n/// Siloing in the context of Aztec refers to the process of hashing a note hash with a contract address (this way\n/// the note hash is scoped to a specific contract). This is used to prevent intermingling of notes between contracts.\npub fn silo_note_hash(note_hash: ScopedNoteHash) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_note_hash(note_hash.contract_address, note_hash.value())\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n poseidon2_hash_with_separator(\n [app.to_field(), nullifier],\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_private_log_field(contract_address: AztecAddress, field: Field) -> Field {\n poseidon2_hash([contract_address.to_field(), field])\n}\n\npub fn silo_private_log(private_log: Scoped) -> PrivateLog {\n if private_log.contract_address.is_zero() {\n private_log.inner.log\n } else {\n let mut fields = private_log.inner.log.fields;\n fields[0] = compute_siloed_private_log_field(private_log.contract_address, fields[0]);\n PrivateLog::new(fields, private_log.inner.log.length)\n }\n}\n\npub fn compute_siloed_contract_class_log_field(\n contract_address: AztecAddress,\n first_field: Field,\n) -> Field {\n poseidon2_hash([contract_address.to_field(), first_field])\n}\n\npub fn silo_contract_class_log(contract_class_log: ContractClassLog) -> ContractClassLog {\n if contract_class_log.contract_address.is_zero() {\n contract_class_log\n } else {\n let mut log = contract_class_log;\n log.log.fields[0] = compute_siloed_contract_class_log_field(\n contract_class_log.contract_address,\n log.log.fields[0],\n );\n log\n }\n}\n\npub fn compute_contract_class_log_hash(log: [Field; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS]) -> Field {\n poseidon2_hash(log)\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n poseidon2_hash([left, right])\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: [u8; 160] = std::mem::zeroed();\n\n let inputs =\n [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..5 {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes: [u8; 32] = inputs[i].to_be_bytes();\n for j in 0..32 {\n bytes[32 * i + j] = item_bytes[j];\n }\n }\n\n sha256_to_field(bytes)\n}\n\npub fn silo_l2_to_l1_message(\n msg: ScopedL2ToL1Message,\n rollup_version_id: Field,\n chain_id: Field,\n) -> 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 // 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: [u8; 32] = input[offset].to_be_bytes();\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\npub fn verification_key_hash(key: [Field; N]) -> Field {\n crate::hash::poseidon2_hash(key)\n}\n\n#[inline_always]\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n poseidon::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[no_predicates]\npub fn poseidon2_hash_with_separator(inputs: [Field; N], separator: T) -> Field\nwhere\n T: ToField,\n{\n let inputs_with_separator = array_concat([separator.to_field()], inputs);\n poseidon2_hash(inputs_with_separator)\n}\n\n// Performs a fixed length hash with a subarray of the given input.\n// Useful for SpongeBlob in which we aborb M things and want to check it vs a hash of M elts of an N-len array.\n// Using stdlib poseidon, this will always absorb an extra 1 as a 'variable' hash, and not match spongeblob.squeeze()\n// or any ts implementation. Also checks that any remaining elts not hashed are empty.\n#[no_predicates]\npub fn poseidon2_hash_subarray(input: [Field; N], in_len: u32) -> Field {\n let mut sponge = poseidon2_absorb_chunks(input, in_len, false);\n sponge.squeeze()\n}\n\n// NB the below is the same as poseidon::poseidon2::Poseidon2::hash(), but replacing a range check with a bit check,\n// and absorbing in chunks of 3 below.\n#[no_predicates]\npub fn poseidon2_cheaper_variable_hash(input: [Field; N], in_len: u32) -> Field {\n let mut sponge = poseidon2_absorb_chunks(input, in_len, true);\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 in_len != N {\n sponge.absorb(1);\n }\n sponge.squeeze()\n}\n\n// The below fn reduces gates of a conditional poseidon2 hash by approx 3x (thank you ~* Giant Brain Dev @IlyasRidhuan *~ for the idea)\n// Why? Because when we call stdlib poseidon, we call absorb for each item. When absorbing is conditional, it seems the compiler does not know\n// what cache_size will be when calling absorb, so it assigns the permutation gates for /each i/ rather than /every 3rd i/, which is actually required.\n// The below code forces the compiler to:\n// - absorb normally up to 2 times to set cache_size to 1\n// - absorb in chunks of 3 to ensure perm. only happens every 3rd absorb\n// - absorb normally up to 2 times to add any remaining values to the hash\n// In fixed len hashes, the compiler is able to tell that it will only need to perform the permutation every 3 absorbs.\n// NB: it also replaces unnecessary range checks (i < thing) with a bit check (&= i != thing), which alone reduces the gates of a var. hash by half.\n\n#[no_predicates]\nfn poseidon2_absorb_chunks(\n input: [Field; N],\n in_len: u32,\n variable: bool,\n) -> Poseidon2Sponge {\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::new(iv);\n // Even though shift is always 1 here, if we input in_len = 0 we get an underflow\n // since we cannot isolate computation branches. The below is just to avoid that.\n let shift = if in_len == 0 { 0 } else { 1 };\n if in_len != 0 {\n // cache_size = 0, init absorb\n sponge.cache[0] = input[0];\n sponge.cache_size = 1;\n // shift = num elts already added to make cache_size 1 = 1 for a fresh sponge\n // M = max_chunks = (N - 1 - (N - 1) % 3) / 3: (must be written as a fn of N to compile)\n // max_remainder = (N - 1) % 3;\n // max_chunks = (N - 1 - max_remainder) / 3;\n sponge = poseidon2_absorb_chunks_loop::(\n sponge,\n input,\n in_len,\n variable,\n shift,\n );\n }\n sponge\n}\n\n// NB: If it's not required to check that the non-absorbed elts of 'input' are 0s, set skip_0_check=true\n#[no_predicates]\npub fn poseidon2_absorb_chunks_existing_sponge(\n in_sponge: Poseidon2Sponge,\n input: [Field; N],\n in_len: u32,\n skip_0_check: bool,\n) -> Poseidon2Sponge {\n let mut sponge = in_sponge;\n // 'shift' is to account for already added inputs\n let mut shift = 0;\n // 'stop' is to avoid an underflow when inputting in_len = 0\n let mut stop = false;\n for i in 0..3 {\n if shift == in_len {\n stop = true;\n }\n if (sponge.cache_size != 1) & (!stop) {\n sponge.absorb(input[i]);\n shift += 1;\n }\n }\n sponge = if stop {\n sponge\n } else {\n // max_chunks = (N - (N % 3)) / 3;\n poseidon2_absorb_chunks_loop::(\n sponge,\n input,\n in_len,\n skip_0_check,\n shift,\n )\n };\n sponge\n}\n\n// The below is the loop to absorb elts into a poseidon sponge in chunks of 3\n// shift - the num of elts already absorbed to ensure the sponge's cache_size = 1\n// M - the max number of chunks required to absorb N things (must be comptime to compile)\n// NB: The 0 checks ('Found non-zero field...') are messy, but having a separate loop over N to check\n// for 0s costs 3N gates. Current approach is approx 2N gates.\n#[no_predicates]\nfn poseidon2_absorb_chunks_loop(\n in_sponge: Poseidon2Sponge,\n input: [Field; N],\n in_len: u32,\n variable: bool,\n shift: u32,\n) -> Poseidon2Sponge {\n assert(in_len <= N, \"Given in_len to absorb is larger than the input array len\");\n // When we have an existing sponge, we may have a shift of 0, and the final 'k+2' below = N\n // The below avoids an overflow\n let skip_last = 3 * M == N;\n // Writing in_sponge: &mut does not compile\n let mut sponge = in_sponge;\n let mut should_add = true;\n // The num of things left over after absorbing in 3s\n let remainder = (in_len - shift) % 3;\n // The num of chunks of 3 to absorb (maximum M)\n let chunks = (in_len - shift - remainder) / 3;\n for i in 0..M {\n // Now we loop through cache size = 1 -> 3\n should_add &= i != chunks;\n // This is the index at the start of the chunk (for readability)\n let k = 3 * i + shift;\n if should_add {\n // cache_size = 1, 2 => just assign\n sponge.cache[1] = input[k];\n sponge.cache[2] = input[k + 1];\n // cache_size = 3 => duplex + perm\n for j in 0..3 {\n sponge.state[j] += sponge.cache[j];\n }\n sponge.state = std::hash::poseidon2_permutation(sponge.state, 4);\n sponge.cache[0] = input[k + 2];\n // cache_size is now 1 again, repeat loop\n } else if (!variable) & (i != chunks) {\n // if we are hashing a fixed len array which is a subarray, we check the remaining elts are 0\n // NB: we don't check at i == chunks, because that chunk contains elts to be absorbed or checked below\n let last_0 = if (i == M - 1) & (skip_last) {\n 0\n } else {\n input[k + 2]\n };\n let all_0 = (input[k] == 0) & (input[k + 1] == 0) & (last_0 == 0);\n assert(all_0, \"Found non-zero field after breakpoint\");\n }\n }\n // we have 'remainder' num of items left to absorb\n should_add = true;\n // below is to avoid overflows (i.e. if inlen is close to N)\n let mut should_check = !variable;\n for i in 0..3 {\n should_add &= i != remainder;\n should_check &= in_len - remainder + i != N;\n if should_add {\n // we want to absorb the final 'remainder' items\n sponge.absorb(input[in_len - remainder + i]);\n } else if should_check {\n assert(input[in_len - remainder + i] == 0, \"Found non-zero field after breakpoint\");\n }\n }\n sponge\n}\n\npub fn poseidon2_hash_with_separator_slice(inputs: [Field], separator: T) -> Field\nwhere\n T: ToField,\n{\n let in_len = inputs.len() + 1;\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::new(iv);\n sponge.absorb(separator.to_field());\n\n for i in 0..inputs.len() {\n sponge.absorb(inputs[i]);\n }\n\n sponge.squeeze()\n}\n\n#[no_predicates]\npub fn poseidon2_hash_bytes(inputs: [u8; N]) -> Field {\n let mut fields = [0; (N + 30) / 31];\n let mut field_index = 0;\n let mut current_field = [0; 31];\n for i in 0..inputs.len() {\n let index = i % 31;\n current_field[index] = inputs[i];\n if index == 30 {\n fields[field_index] = field_from_bytes(current_field, false);\n current_field = [0; 31];\n field_index += 1;\n }\n }\n if field_index != fields.len() {\n fields[field_index] = field_from_bytes(current_field, false);\n }\n poseidon2_hash(fields)\n}\n\n#[test]\nfn poseidon_chunks_matches_fixed() {\n let in_len = 501;\n let mut input: [Field; 4096] = [0; 4096];\n let mut fixed_input = [3; 501];\n assert(in_len == fixed_input.len()); // sanity check\n for i in 0..in_len {\n input[i] = 3;\n }\n let sub_chunk_hash = poseidon2_hash_subarray(input, in_len);\n let fixed_len_hash = poseidon::poseidon2::Poseidon2::hash(fixed_input, fixed_input.len());\n assert(sub_chunk_hash == fixed_len_hash);\n}\n\n#[test]\nfn poseidon_chunks_matches_variable() {\n let in_len = 501;\n let mut input: [Field; 4096] = [0; 4096];\n for i in 0..in_len {\n input[i] = 3;\n }\n let variable_chunk_hash = poseidon2_cheaper_variable_hash(input, in_len);\n let variable_len_hash = poseidon::poseidon2::Poseidon2::hash(input, in_len);\n assert(variable_chunk_hash == variable_len_hash);\n}\n\n#[test]\nfn existing_sponge_poseidon_chunks_matches_fixed() {\n let in_len = 501;\n let mut input: [Field; 4096] = [0; 4096];\n let mut fixed_input = [3; 501];\n assert(in_len == fixed_input.len()); // sanity check\n for i in 0..in_len {\n input[i] = 3;\n }\n // absorb 250 of the 501 things\n let empty_sponge = Poseidon2Sponge::new((in_len as Field) * TWO_POW_64);\n let first_sponge = poseidon2_absorb_chunks_existing_sponge(empty_sponge, input, 250, true);\n // now absorb the final 251 (since they are all 3s, im being lazy and not making a new array)\n let mut final_sponge = poseidon2_absorb_chunks_existing_sponge(first_sponge, input, 251, true);\n let fixed_len_hash = Poseidon2Sponge::hash(fixed_input, fixed_input.len());\n assert(final_sponge.squeeze() == fixed_len_hash);\n}\n\n#[test]\nfn poseidon_chunks_empty_inputs() {\n let in_len = 0;\n let mut input: [Field; 4096] = [0; 4096];\n let mut constructed_empty_sponge = poseidon2_absorb_chunks(input, in_len, true);\n let mut first_sponge =\n poseidon2_absorb_chunks_existing_sponge(constructed_empty_sponge, input, in_len, true);\n assert(first_sponge.squeeze() == constructed_empty_sponge.squeeze());\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, 20, 21, 22, 23, 24,\n 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\n 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,\n 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,\n 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,\n 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,\n 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,\n 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::digest(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 =\n 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(\n AztecAddress::from_field(1),\n EthAddress::from_field(3),\n 5,\n 2,\n 4,\n );\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n\n#[test]\nfn silo_l2_to_l1_message_matches_typescript() {\n let version = 4;\n let chainId = 5;\n\n let hash = silo_l2_to_l1_message(\n ScopedL2ToL1Message {\n message: L2ToL1Message { recipient: EthAddress::from_field(1), content: 2, counter: 0 },\n contract_address: AztecAddress::from_field(3),\n },\n version,\n chainId,\n );\n\n // The following value was generated by `l2_to_l1_message.test.ts`\n let hash_from_typescript = 0x00c6155d69febb9d5039b374dd4f77bf57b7c881709aa524a18acaa0bd57476a;\n\n assert_eq(hash, hash_from_typescript);\n}\n" - }, - "294": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/noir-protocol-circuits/crates/types/src/meta/mod.nr", - "source": "use super::traits::{Deserialize, Packable, Serialize};\n\n/// Returns the typed expression of a trait method implementation.\n///\n/// This helper function is preferred over directly inlining with `$typ::target_method()` in a quote,\n/// as direct inlining would result in missing import warnings in the generated code (specifically,\n/// warnings that the trait implementation is not in scope).\n///\n/// # Note\n/// A copy of this function exists in `aztec-nr/aztec/src/macros/utils.nr`. We maintain separate copies\n/// because importing it there from here would cause the `target_trait` to be interpreted in the context\n/// of this crate, making it impossible to compile code for traits from that crate (e.g. NoteType).\ncomptime fn get_trait_impl_method(\n typ: Type,\n target_trait: Quoted,\n target_method: Quoted,\n) -> TypedExpr {\n let trait_constraint = target_trait.as_trait_constraint();\n typ\n .get_trait_impl(trait_constraint)\n .expect(f\"Could not find impl for {target_trait} for type {typ}\")\n .methods()\n .filter(|m| m.name() == target_method)[0]\n .as_typed_expr()\n}\n\n/// Generates code that deserializes a struct, primitive type, array or string from a field array.\n///\n/// # Parameters\n/// - `name`: The name of the current field being processed, used to identify fields for replacement.\n/// - `typ`: The type of the struct or field being deserialized (e.g., a custom struct, array, or primitive).\n/// - `field_array_name`: The name of the field array containing serialized field data (e.g., `\"values\"`).\n/// - `num_already_consumed`: The number of fields already processed in previous recursion calls.\n/// - `should_unpack`: A boolean indicating whether the type should be unpacked (see description of `Packable`\n/// and `Serialize` trait for more information about the difference between packing and serialization).\n///\n/// # Returns\n/// A tuple containing:\n/// - `Quoted`: A code that deserializes a given struct, primitive type, array, or string from the field array.\n/// - `u32`: The total number of fields consumed during deserialization (used for recursion).\n///\n/// # Nested Struct Example\n/// Given the following setup:\n/// ```\n/// struct UintNote {\n/// value: u128,\n/// owner: AztecAddress,\n/// randomness: Field,\n/// }\n///\n/// struct AztecAddress {\n/// inner: Field,\n/// }\n/// ```\n///\n/// If `UintNote` is the input type, the function will generate the following deserialization code:\n/// ```\n/// UintNote {\n/// value: fields[0] as u128,\n/// owner: AztecAddress {\n/// inner: fields[1],\n/// },\n/// randomness: fields[2],\n/// }\n/// ```\n/// # Nested Struct Example with Unpacking\n/// - given the same setup as above and given that u128, AztecAddress and Field implement the `Packable` trait\n/// the result we get is:\n/// ```\n/// UintNote {\n/// value: aztec::protocol_types::traits::Packable::unpack([fields[0]]),\n/// owner: aztec::protocol_types::traits::Packable::unpack([fields[1]]),\n/// randomness: aztec::protocol_types::traits::Packable::unpack([fields[2]]),\n/// }\n/// ```\n///\n/// # Panics\n/// - If the deserialization logic encounters a type it does not support.\n/// - If an incorrect number of fields are consumed when deserializing a string.\npub comptime fn generate_deserialize_from_fields(\n name: Quoted,\n typ: Type,\n field_array_name: Quoted,\n num_already_consumed: u32,\n should_unpack: bool,\n) -> (Quoted, u32) {\n let mut result = quote {};\n // Counter for the number of fields consumed\n let mut consumed_counter: u32 = 0;\n\n // If the type implements `Packable`, its length will be assigned to the `maybe_packed_len_typ` variable.\n let maybe_packed_len_typ = std::meta::typ::fresh_type_variable();\n let packable_constraint = quote { Packable<$maybe_packed_len_typ> }.as_trait_constraint();\n\n if (should_unpack & typ.implements(packable_constraint)) {\n // Unpacking is enabled and the given type implements the `Packable` trait so we call the `unpack()`\n // method, add the resulting field array to `aux_vars` and each field to `fields`.\n let packed_len = maybe_packed_len_typ.as_constant().unwrap();\n\n // We copy the packed fields into a new array and pass that to the unpack function in a quote\n let mut packed_fields_quotes = &[];\n for i in 0..packed_len {\n let index_in_field_array = i + num_already_consumed;\n packed_fields_quotes =\n packed_fields_quotes.push_back(quote { $field_array_name[$index_in_field_array] });\n }\n let packed_fields = packed_fields_quotes.join(quote {,});\n\n // Now we call unpack on the type\n let unpack_method = get_trait_impl_method(typ, quote { Packable<_> }, quote { unpack });\n result = quote { $unpack_method([ $packed_fields ]) };\n\n consumed_counter = packed_len;\n } else if typ.is_field() | typ.as_integer().is_some() | typ.is_bool() {\n // The field is a primitive so we just reference it in the field array\n result = quote { $field_array_name[$num_already_consumed] as $typ };\n consumed_counter = 1;\n } else if typ.as_data_type().is_some() {\n // The field is a struct so we iterate over each struct field and recursively call\n // `generate_deserialize_from_fields`\n let (nested_def, generics) = typ.as_data_type().unwrap();\n let nested_name = nested_def.name();\n let mut deserialized_fields_list = &[];\n\n // Iterate over each field in the struct\n for field in nested_def.fields(generics) {\n let (field_name, field_type) = field;\n // Recursively call `generate_deserialize_from_fields` for each field in the struct\n let (deserialized_field, num_consumed_in_recursion) = generate_deserialize_from_fields(\n field_name,\n field_type,\n field_array_name,\n consumed_counter + num_already_consumed,\n should_unpack,\n );\n // We increment the consumed counter by the number of fields consumed in the recursion\n consumed_counter += num_consumed_in_recursion;\n // We add the deserialized field to the list of deserialized fields.\n // E.g. `value: u128 { lo: fields[0], hi: fields[1] }`\n deserialized_fields_list =\n deserialized_fields_list.push_back(quote { $field_name: $deserialized_field });\n }\n\n // We can construct the struct from the deserialized fields\n let deserialized_fields = deserialized_fields_list.join(quote {,});\n result = quote {\n $nested_name {\n $deserialized_fields\n }\n };\n } else if typ.as_array().is_some() {\n // The field is an array so we iterate over each element and recursively call\n // `generate_deserialize_from_fields`\n let (element_type, array_len) = typ.as_array().unwrap();\n let array_len = array_len.as_constant().unwrap();\n let mut array_fields_list = &[];\n\n // Iterate over each element in the array\n for _ in 0..array_len {\n // Recursively call `generate_deserialize_from_fields` for each element in the array\n let (deserialized_field, num_consumed_in_recursion) = generate_deserialize_from_fields(\n name,\n element_type,\n field_array_name,\n consumed_counter + num_already_consumed,\n should_unpack,\n );\n // We increment the consumed counter by the number of fields consumed in the recursion\n consumed_counter += num_consumed_in_recursion;\n // We add the deserialized field to the list of deserialized fields.\n array_fields_list = array_fields_list.push_back(deserialized_field);\n }\n\n // We can construct the array from the deserialized fields\n let array_fields = array_fields_list.join(quote {,});\n result = quote { [ $array_fields ] };\n } else if typ.as_str().is_some() {\n // The field is a string and we expect each byte of the string to be represented as 1 field in the field\n // array. So we iterate over the string length and deserialize each character as u8 in the recursive call\n // to `generate_deserialize_from_fields`.\n let length_type = typ.as_str().unwrap();\n let str_len = length_type.as_constant().unwrap();\n let mut byte_list = &[];\n\n // Iterate over each character in the string\n for _ in 0..str_len {\n // Recursively call `generate_deserialize_from_fields` for each character in the string\n let (deserialized_field, num_consumed_in_recursion) = generate_deserialize_from_fields(\n name,\n quote {u8}.as_type(),\n field_array_name,\n consumed_counter + num_already_consumed,\n should_unpack,\n );\n\n // We should consume just one field in the recursion so we sanity check that\n assert_eq(\n num_consumed_in_recursion,\n 1,\n \"Incorrect number of fields consumed in string deserialization\",\n );\n\n // We increment the consumed counter by 1 as we have consumed one field\n consumed_counter += 1;\n\n // We add the deserialized field to the list of deserialized fields.\n // E.g. `fields[6] as u8`\n byte_list = byte_list.push_back(deserialized_field);\n }\n\n // We construct the string from the deserialized fields\n let bytes = byte_list.join(quote {,});\n result = quote { [ $bytes ].as_str_unchecked() };\n } else {\n panic(\n f\"Unsupported type for serialization of argument {name} and type {typ}\",\n )\n }\n\n (result, consumed_counter)\n}\n\n/// Generates code that serializes a type into an array of fields. Also generates auxiliary variables if necessary\n/// for serialization. If `should_pack` is true, we check if the type implements the `Packable` trait and pack it\n/// if it does.\n///\n/// # Parameters\n/// - `name`: The base identifier (e.g., `self`, `some_var`).\n/// - `typ`: The type being serialized (e.g., a custom struct, array, or primitive type).\n/// - `should_pack`: A boolean indicating whether the type should be packed.\n///\n/// # Returns\n/// A tuple containing:\n/// - A flattened array of `Quoted` field references representing the serialized fields.\n/// - An array of `Quoted` auxiliary variables needed for serialization, such as byte arrays for strings.\n///\n/// # Examples\n///\n/// ## Struct\n/// Given the following struct:\n/// ```rust\n/// struct MockStruct {\n/// a: Field,\n/// b: Field,\n/// }\n/// ```\n///\n/// Serializing the struct:\n/// ```rust\n/// generate_serialize_to_fields(quote { my_mock_struct }, MockStruct, false)\n/// // Returns:\n/// // ([`my_mock_struct.a`, `my_mock_struct.b`], [])\n/// ```\n///\n/// ## Nested Struct\n/// For a more complex struct:\n/// ```rust\n/// struct NestedStruct {\n/// m1: MockStruct,\n/// m2: MockStruct,\n/// }\n/// ```\n///\n/// Serialization output:\n/// ```rust\n/// generate_serialize_to_fields(quote { self }, NestedStruct, false)\n/// // Returns:\n/// // ([`self.m1.a`, `self.m1.b`, `self.m2.a`, `self.m2.b`], [])\n/// ```\n///\n/// ## Array\n/// For an array type:\n/// ```rust\n/// generate_serialize_to_fields(quote { my_array }, [Field; 3], false)\n/// // Returns:\n/// // ([`my_array[0]`, `my_array[1]`, `my_array[2]`], [])\n/// ```\n///\n/// ## String\n/// For a string field, where each character is serialized as a `Field`:\n/// ```rust\n/// generate_serialize_to_fields(quote { my_string }, StringType, false)\n/// // Returns:\n/// // ([`my_string_as_bytes[0] as Field`, `my_string_as_bytes[1] as Field`, ...],\n/// // [`let my_string_as_bytes = my_string.as_bytes()`])\n/// ```\n///\n/// ## Nested Struct with packing enabled\n/// - u128 has a `Packable` implementation hence it will be packed.\n///\n/// For a more complex struct:\n/// ```rust\n/// struct MyStruct {\n/// value: u128,\n/// value2: Field,\n/// }\n/// ```\n///\n/// # Panics\n/// - If the type is unsupported for serialization.\n/// - If the provided `typ` contains invalid constants or incompatible structures.\npub comptime fn generate_serialize_to_fields(\n name: Quoted,\n typ: Type,\n should_pack: bool,\n) -> ([Quoted], [Quoted]) {\n let mut fields = &[];\n let mut aux_vars = &[];\n\n // If the type implements `Packable`, its length will be assigned to the `maybe_packed_len_typ` variable.\n let maybe_packed_len_typ = std::meta::typ::fresh_type_variable();\n let packable_constraint =\n quote { crate::traits::Packable<$maybe_packed_len_typ> }.as_trait_constraint();\n\n if (should_pack & typ.implements(packable_constraint)) {\n // Packing is enabled and the given type implements the `Packable` trait so we call the `pack()`\n // method, add the resulting field array to `aux_vars` and each field to `fields`.\n let packed_len = maybe_packed_len_typ.as_constant().unwrap();\n\n // We collapse the name to a one that gets tokenized as a single token (e.g. \"self.value\" -> \"self_value\").\n let name_at_one_token = collapse_to_one_token(name);\n let packed_struct_name = f\"{name_at_one_token}_aux_var\".quoted_contents();\n\n // We add the individual fields to the fields array\n let pack_method = get_trait_impl_method(\n typ,\n quote { crate::traits::Packable<$packed_len> },\n quote { pack },\n );\n let packed_struct = quote { let $packed_struct_name = $pack_method($name) };\n for i in 0..packed_len {\n fields = fields.push_back(quote { $packed_struct_name[$i] });\n }\n\n // We add the new auxiliary variable to the aux_vars array\n aux_vars = aux_vars.push_back(packed_struct);\n } else if typ.is_field() {\n // For field we just add the value to fields\n fields = fields.push_back(name);\n } else if typ.as_integer().is_some() | typ.is_bool() {\n // For integer and bool we just cast to Field and add the value to fields\n fields = fields.push_back(quote { $name as Field });\n } else if typ.as_data_type().is_some() {\n // For struct we pref\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.0.fields(nested_struct.1);\n let struct_flattened = params.map(|(param_name, param_type): (Quoted, Type)| {\n let maybe_prefixed_name = if name == quote {} {\n // Triggered when the param name is of a value available in the current scope (e.g. a function\n // argument) --> then we don't prefix the name with anything.\n param_name\n } else {\n // Triggered when we want to prefix the param name with the `name` from function input. This\n // can typically be `self` when implementing a method on a struct.\n quote { $name.$param_name }\n };\n generate_serialize_to_fields(quote {$maybe_prefixed_name}, param_type, should_pack)\n });\n let struct_flattened_fields = struct_flattened.fold(\n &[],\n |acc: [Quoted], (fields, _): (_, [Quoted])| acc.append(fields),\n );\n let struct_flattened_aux_vars = struct_flattened.fold(\n &[],\n |acc: [Quoted], (_, aux_vars): ([Quoted], _)| acc.append(aux_vars),\n );\n fields = fields.append(struct_flattened_fields);\n aux_vars = aux_vars.append(struct_flattened_aux_vars);\n } else if typ.as_array().is_some() {\n // For array we recursively call `generate_serialize_to_fields(...)` for each element\n let (element_type, array_len) = typ.as_array().unwrap();\n let array_len = array_len.as_constant().unwrap();\n for i in 0..array_len {\n let (element_fields, element_aux_vars) =\n generate_serialize_to_fields(quote { $name[$i] }, element_type, should_pack);\n fields = fields.append(element_fields);\n aux_vars = aux_vars.append(element_aux_vars);\n }\n } else if typ.as_str().is_some() {\n // For string we convert the value to bytes, we store the `as_bytes` in an auxiliary variables and\n // then we add each byte to fields as a Field\n let length_type = typ.as_str().unwrap();\n let str_len = length_type.as_constant().unwrap();\n let as_member = name.as_expr().unwrap().as_member_access();\n let var_name = if as_member.is_some() {\n as_member.unwrap().1\n } else {\n name\n };\n let as_bytes_name = f\"{var_name}_as_bytes\".quoted_contents();\n let as_bytes = quote { let $as_bytes_name = $name.as_bytes() };\n for i in 0..str_len {\n fields = fields.push_back(quote { $as_bytes_name[$i] as Field });\n }\n aux_vars = aux_vars.push_back(as_bytes);\n } else {\n panic(\n f\"Unsupported type for serialization of argument {name} and type {typ}\",\n )\n }\n\n (fields, aux_vars)\n}\n\n/// From a quote that gets tokenized to a multiple tokens we collapse it to a single token by replacing all `.` with `_`.\n/// E.g. \"self.values[0]\" -> \"self_values_0_\"\ncomptime fn collapse_to_one_token(q: Quoted) -> Quoted {\n let tokens = q.tokens();\n\n let mut single_token = quote {};\n for token in tokens {\n let new_token = if ((token == quote {.}) | (token == quote {[}) | (token == quote {]})) {\n quote {_}\n } else {\n token\n };\n single_token = f\"{single_token}{new_token}\".quoted_contents();\n }\n single_token\n}\n\npub(crate) comptime fn derive_serialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let (fields, aux_vars) = generate_serialize_to_fields(quote { self }, typ, false);\n let aux_vars_for_serialization = if aux_vars.len() > 0 {\n let joint = aux_vars.join(quote {;});\n quote { $joint; }\n } else {\n quote {}\n };\n\n let field_serializations = fields.join(quote {,});\n let serialized_len = fields.len();\n quote {\n impl Serialize<$serialized_len> for $typ {\n #[inline_always]\n fn serialize(self) -> [Field; $serialized_len] {\n $aux_vars_for_serialization\n [ $field_serializations ]\n }\n }\n }\n}\n\npub(crate) comptime fn derive_deserialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let (fields, _) = generate_serialize_to_fields(quote { self }, typ, false);\n let serialized_len = fields.len();\n let (deserialized, _) =\n generate_deserialize_from_fields(quote { self }, typ, quote { serialized }, 0, false);\n quote {\n impl Deserialize<$serialized_len> for $typ {\n #[inline_always]\n fn deserialize(serialized: [Field; $serialized_len]) -> Self {\n $deserialized\n }\n }\n }\n}\n\n/// Generates `Packable` implementation for a given struct and returns the packed length.\n///\n/// Note: We are having this function separate from `derive_packable` because we use this in the note macros to get\n/// the packed length of a note as well as the `Packable` implementation. We need the length to be able to register\n/// the note in the global `NOTES` map. There the length is used to generate partial note helper functions.\npub comptime fn derive_packable_and_get_packed_len(s: TypeDefinition) -> (Quoted, u32) {\n let packing_enabled = true;\n\n let typ = s.as_type();\n let (fields, aux_vars) = generate_serialize_to_fields(quote { self }, typ, packing_enabled);\n let aux_vars_for_packing = if aux_vars.len() > 0 {\n let joint = aux_vars.join(quote {;});\n quote { $joint; }\n } else {\n quote {}\n };\n\n let (unpacked, _) =\n generate_deserialize_from_fields(quote { self }, typ, quote { packed }, 0, packing_enabled);\n\n let field_packings = fields.join(quote {,});\n let packed_len = fields.len();\n let packable_trait: TraitConstraint = quote { Packable<$packed_len> }.as_trait_constraint();\n (\n quote {\n impl $packable_trait for $typ {\n fn pack(self) -> [Field; $packed_len] {\n $aux_vars_for_packing\n [ $field_packings ]\n }\n\n fn unpack(packed: [Field; $packed_len]) -> Self {\n $unpacked\n }\n }\n },\n packed_len,\n )\n}\n\npub(crate) comptime fn derive_packable(s: TypeDefinition) -> Quoted {\n let (packable_impl, _) = derive_packable_and_get_packed_len(s);\n packable_impl\n}\n\n#[derive(Packable, Serialize, Deserialize, Eq)]\npub struct Smol {\n a: Field,\n b: Field,\n}\n\n#[derive(Serialize, Deserialize, Eq)]\npub struct HasArray {\n a: [Field; 2],\n b: bool,\n}\n\n#[derive(Serialize, Deserialize, Eq)]\npub struct Fancier {\n a: Smol,\n b: [Field; 2],\n c: [u8; 3],\n d: str<16>,\n}\n\nfn main() {\n assert(false);\n}\n\n#[test]\nfn smol_test() {\n let smol = Smol { a: 1, b: 2 };\n let serialized = smol.serialize();\n assert(serialized == [1, 2], serialized);\n let deserialized = Smol::deserialize(serialized);\n assert(deserialized == smol);\n\n // None of the struct members implements the `Packable` trait so the packed and serialized data should be the same\n let packed = smol.pack();\n assert_eq(packed, serialized, \"Packed does not match serialized\");\n}\n\n#[test]\nfn has_array_test() {\n let has_array = HasArray { a: [1, 2], b: true };\n let serialized = has_array.serialize();\n assert(serialized == [1, 2, 1], serialized);\n let deserialized = HasArray::deserialize(serialized);\n assert(deserialized == has_array);\n}\n\n#[test]\nfn fancier_test() {\n let fancier =\n Fancier { a: Smol { a: 1, b: 2 }, b: [0, 1], c: [1, 2, 3], d: \"metaprogramming!\" };\n let serialized = fancier.serialize();\n assert(\n serialized\n == [\n 1, 2, 0, 1, 1, 2, 3, 0x6d, 0x65, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61,\n 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x21,\n ],\n serialized,\n );\n let deserialized = Fancier::deserialize(serialized);\n assert(deserialized == fancier);\n}\n" - }, - "296": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/noir-protocol-circuits/crates/types/src/point.nr", - "source": "pub use dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\nuse crate::{hash::poseidon2_hash, traits::{Deserialize, Empty, Hash, Packable, Serialize}};\n\npub global POINT_LENGTH: u32 = 3;\n\nimpl Serialize for Point {\n fn serialize(self: Self) -> [Field; POINT_LENGTH] {\n [self.x, self.y, self.is_infinite as Field]\n }\n}\n\nimpl Hash for Point {\n fn hash(self) -> Field {\n poseidon2_hash(self.serialize())\n }\n}\n\nimpl Empty for Point {\n /// Note: Does not return a valid point on curve - instead represents an empty/\"unpopulated\" point struct (e.g.\n /// empty/unpopulated value in an array of points).\n fn empty() -> Self {\n Point { x: 0, y: 0, is_infinite: false }\n }\n}\n\nimpl Deserialize for Point {\n fn deserialize(serialized: [Field; POINT_LENGTH]) -> Point {\n Point { x: serialized[0], y: serialized[1], is_infinite: serialized[2] as bool }\n }\n}\n// TODO(#11356): use compact representation here.\nimpl Packable for Point {\n fn pack(self) -> [Field; POINT_LENGTH] {\n self.serialize()\n }\n\n fn unpack(packed: [Field; POINT_LENGTH]) -> Self {\n Self::deserialize(packed)\n }\n}\n" - }, - "297": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/noir-protocol-circuits/crates/types/src/poseidon2.nr", - "source": "use crate::constants::TWO_POW_64;\n\n// NB: This is a clone of noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr\n// It exists as we sometimes need to perform custom absorption, but the stdlib version\n// has a private absorb() method (it's also designed to just be a hasher)\n// Can be removed when standalone noir poseidon lib exists: See noir#6679\n\ncomptime global RATE: u32 = 3;\n\npub struct Poseidon2Sponge {\n pub cache: [Field; 3],\n pub state: [Field; 4],\n pub cache_size: u32,\n pub squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2Sponge {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2Sponge::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2Sponge {\n let mut result =\n Poseidon2Sponge { 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) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = std::hash::poseidon2_permutation(self.state, 4);\n }\n\n pub fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\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 }\n }\n\n pub fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> Field {\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::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" - }, - "307": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/noir-protocol-circuits/crates/types/src/public_keys.nr", - "source": "use crate::{\n address::public_keys_hash::PublicKeysHash,\n constants::{\n DEFAULT_IVPK_M_X, DEFAULT_IVPK_M_Y, DEFAULT_NPK_M_X, DEFAULT_NPK_M_Y, DEFAULT_OVPK_M_X,\n DEFAULT_OVPK_M_Y, DEFAULT_TPK_M_X, DEFAULT_TPK_M_Y, GENERATOR_INDEX__PUBLIC_KEYS_HASH,\n },\n hash::poseidon2_hash_with_separator,\n point::POINT_LENGTH,\n traits::{Deserialize, Hash, Serialize},\n};\n\nuse dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\nuse std::default::Default;\n\npub global PUBLIC_KEYS_LENGTH: u32 = 12;\n\npub struct PublicKeys {\n pub npk_m: NpkM,\n pub ivpk_m: IvpkM,\n pub ovpk_m: OvpkM,\n pub tpk_m: TpkM,\n}\n\npub trait ToPoint {\n fn to_point(self) -> Point;\n}\n\npub struct NpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for NpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\nimpl Serialize for NpkM {\n fn serialize(self) -> [Field; POINT_LENGTH] {\n self.inner.serialize()\n }\n}\n\n// Note: If we store npk_m_hash directly we can remove this trait implementation. See #8091\nimpl Hash for NpkM {\n fn hash(self) -> Field {\n self.inner.hash()\n }\n}\n\npub struct IvpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for IvpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\nimpl Serialize for IvpkM {\n fn serialize(self) -> [Field; POINT_LENGTH] {\n self.inner.serialize()\n }\n}\n\npub struct OvpkM {\n pub inner: Point,\n}\n\nimpl Hash for OvpkM {\n fn hash(self) -> Field {\n self.inner.hash()\n }\n}\n\nimpl ToPoint for OvpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\nimpl Serialize for OvpkM {\n fn serialize(self) -> [Field; POINT_LENGTH] {\n self.inner.serialize()\n }\n}\n\npub struct TpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for TpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\nimpl Serialize for TpkM {\n fn serialize(self) -> [Field; POINT_LENGTH] {\n self.inner.serialize()\n }\n}\n\nimpl Default for PublicKeys {\n fn default() -> Self {\n PublicKeys {\n npk_m: NpkM {\n inner: Point { x: DEFAULT_NPK_M_X, y: DEFAULT_NPK_M_Y, is_infinite: false },\n },\n ivpk_m: IvpkM {\n inner: Point { x: DEFAULT_IVPK_M_X, y: DEFAULT_IVPK_M_Y, is_infinite: false },\n },\n ovpk_m: OvpkM {\n inner: Point { x: DEFAULT_OVPK_M_X, y: DEFAULT_OVPK_M_Y, is_infinite: false },\n },\n tpk_m: TpkM {\n inner: Point { x: DEFAULT_TPK_M_X, y: DEFAULT_TPK_M_Y, is_infinite: false },\n },\n }\n }\n}\n\nimpl Eq for PublicKeys {\n fn eq(self, other: PublicKeys) -> bool {\n (self.npk_m.inner == other.npk_m.inner)\n & (self.ivpk_m.inner == other.ivpk_m.inner)\n & (self.ovpk_m.inner == other.ovpk_m.inner)\n & (self.tpk_m.inner == other.tpk_m.inner)\n }\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(poseidon2_hash_with_separator(\n self.serialize(),\n GENERATOR_INDEX__PUBLIC_KEYS_HASH as Field,\n ))\n }\n}\n\nimpl Serialize for PublicKeys {\n fn serialize(self) -> [Field; PUBLIC_KEYS_LENGTH] {\n [\n self.npk_m.inner.x,\n self.npk_m.inner.y,\n self.npk_m.inner.is_infinite as Field,\n self.ivpk_m.inner.x,\n self.ivpk_m.inner.y,\n self.ivpk_m.inner.is_infinite as Field,\n self.ovpk_m.inner.x,\n self.ovpk_m.inner.y,\n self.ovpk_m.inner.is_infinite as Field,\n self.tpk_m.inner.x,\n self.tpk_m.inner.y,\n self.tpk_m.inner.is_infinite as Field,\n ]\n }\n}\n\nimpl Deserialize for PublicKeys {\n fn deserialize(serialized: [Field; PUBLIC_KEYS_LENGTH]) -> PublicKeys {\n PublicKeys {\n npk_m: NpkM {\n inner: Point {\n x: serialized[0],\n y: serialized[1],\n is_infinite: serialized[2] as bool,\n },\n },\n ivpk_m: IvpkM {\n inner: Point {\n x: serialized[3],\n y: serialized[4],\n is_infinite: serialized[5] as bool,\n },\n },\n ovpk_m: OvpkM {\n inner: Point {\n x: serialized[6],\n y: serialized[7],\n is_infinite: serialized[8] as bool,\n },\n },\n tpk_m: TpkM {\n inner: Point {\n x: serialized[9],\n y: serialized[10],\n is_infinite: serialized[11] as bool,\n },\n },\n }\n }\n}\n\npub struct AddressPoint {\n pub inner: Point,\n}\n\nimpl ToPoint for AddressPoint {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[test]\nunconstrained fn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: 1, y: 2, is_infinite: false } },\n ivpk_m: IvpkM { inner: Point { x: 3, y: 4, is_infinite: false } },\n ovpk_m: OvpkM { inner: Point { x: 5, y: 6, is_infinite: false } },\n tpk_m: TpkM { inner: Point { x: 7, y: 8, is_infinite: false } },\n };\n\n let actual = keys.hash();\n let expected_public_keys_hash =\n 0x0fecd9a32db731fec1fded1b9ff957a1625c069245a3613a2538bd527068b0ad;\n\n assert(actual.to_field() == expected_public_keys_hash);\n}\n\n#[test]\nunconstrained fn compute_default_hash() {\n let keys = PublicKeys::default();\n\n let actual = keys.hash();\n let test_data_default_hash = 0x1d3bf1fb93ae0e9cda83b203dd91c3bfb492a9aecf30ec90e1057eced0f0e62d;\n\n assert(actual.to_field() == test_data_default_hash);\n}\n\n#[test]\nunconstrained fn test_public_keys_serialization() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: 1, y: 2, is_infinite: false } },\n ivpk_m: IvpkM { inner: Point { x: 3, y: 4, is_infinite: false } },\n ovpk_m: OvpkM { inner: Point { x: 5, y: 6, is_infinite: false } },\n tpk_m: TpkM { inner: Point { x: 7, y: 8, is_infinite: false } },\n };\n\n let serialized = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys.npk_m.inner.x, deserialized.npk_m.inner.x);\n assert_eq(keys.npk_m.inner.y, deserialized.npk_m.inner.y);\n assert_eq(keys.ivpk_m.inner.x, deserialized.ivpk_m.inner.x);\n assert_eq(keys.ivpk_m.inner.y, deserialized.ivpk_m.inner.y);\n assert_eq(keys.ovpk_m.inner.x, deserialized.ovpk_m.inner.x);\n assert_eq(keys.ovpk_m.inner.y, deserialized.ovpk_m.inner.y);\n assert_eq(keys.tpk_m.inner.x, deserialized.tpk_m.inner.x);\n assert_eq(keys.tpk_m.inner.y, deserialized.tpk_m.inner.y);\n}\n" - }, - "318": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr", - "source": "use crate::{hash::poseidon2_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field\nwhere\n K: ToField,\n{\n poseidon2_hash([storage_slot, key.to_field()])\n}\n\nmod test {\n use crate::{address::AztecAddress, storage::map::derive_storage_slot_in_map, traits::FromField};\n\n #[test]\n fn test_derive_storage_slot_in_map_matches_typescript() {\n let map_slot = 0x132258fb6962c4387ba659d9556521102d227549a386d39f0b22d1890d59c2b5;\n let key = AztecAddress::from_field(\n 0x302dbc2f9b50a73283d5fb2f35bc01eae8935615817a0b4219a057b2ba8a5a3f,\n );\n\n let slot = derive_storage_slot_in_map(map_slot, key);\n\n // The following value was generated by `map_slot.test.ts`\n let slot_from_typescript =\n 0x15b9fe39449affd8b377461263e9d2b610b9ad40580553500b4e41d9cbd887ac;\n\n assert_eq(slot, slot_from_typescript);\n }\n}\n" - }, - "336": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/noir-protocol-circuits/crates/types/src/type_packing.nr", - "source": "use crate::traits::Packable;\n\nglobal BOOL_PACKED_LEN: u32 = 1;\nglobal U8_PACKED_LEN: u32 = 1;\nglobal U16_PACKED_LEN: u32 = 1;\nglobal U32_PACKED_LEN: u32 = 1;\nglobal U64_PACKED_LEN: u32 = 1;\nglobal U128_PACKED_LEN: u32 = 1;\nglobal FIELD_PACKED_LEN: u32 = 1;\nglobal I8_PACKED_LEN: u32 = 1;\nglobal I16_PACKED_LEN: u32 = 1;\nglobal I32_PACKED_LEN: u32 = 1;\nglobal I64_PACKED_LEN: u32 = 1;\n\nimpl Packable for bool {\n fn pack(self) -> [Field; BOOL_PACKED_LEN] {\n [self as Field]\n }\n\n fn unpack(fields: [Field; BOOL_PACKED_LEN]) -> bool {\n fields[0] as bool\n }\n}\n\nimpl Packable for u8 {\n fn pack(self) -> [Field; U8_PACKED_LEN] {\n [self as Field]\n }\n\n fn unpack(fields: [Field; U8_PACKED_LEN]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Packable for u16 {\n fn pack(self) -> [Field; U16_PACKED_LEN] {\n [self as Field]\n }\n\n fn unpack(fields: [Field; U16_PACKED_LEN]) -> Self {\n fields[0] as u16\n }\n}\n\nimpl Packable for u32 {\n fn pack(self) -> [Field; U32_PACKED_LEN] {\n [self as Field]\n }\n\n fn unpack(fields: [Field; U32_PACKED_LEN]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Packable for u64 {\n fn pack(self) -> [Field; U64_PACKED_LEN] {\n [self as Field]\n }\n\n fn unpack(fields: [Field; U64_PACKED_LEN]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Packable for u128 {\n fn pack(self) -> [Field; U128_PACKED_LEN] {\n [self as Field]\n }\n\n fn unpack(fields: [Field; U128_PACKED_LEN]) -> Self {\n fields[0] as u128\n }\n}\n\nimpl Packable for Field {\n fn pack(self) -> [Field; FIELD_PACKED_LEN] {\n [self]\n }\n\n fn unpack(fields: [Field; FIELD_PACKED_LEN]) -> Self {\n fields[0]\n }\n}\n\nimpl Packable for i8 {\n fn pack(self) -> [Field; I8_PACKED_LEN] {\n [self as Field]\n }\n\n fn unpack(fields: [Field; I8_PACKED_LEN]) -> Self {\n fields[0] as i8\n }\n}\n\nimpl Packable for i16 {\n fn pack(self) -> [Field; I16_PACKED_LEN] {\n [self as Field]\n }\n\n fn unpack(fields: [Field; I16_PACKED_LEN]) -> Self {\n fields[0] as i16\n }\n}\n\nimpl Packable for i32 {\n fn pack(self) -> [Field; I32_PACKED_LEN] {\n [self as Field]\n }\n\n fn unpack(fields: [Field; I32_PACKED_LEN]) -> Self {\n fields[0] as i32\n }\n}\n\nimpl Packable for i64 {\n fn pack(self) -> [Field; I64_PACKED_LEN] {\n [self as Field]\n }\n\n fn unpack(fields: [Field; I64_PACKED_LEN]) -> Self {\n fields[0] as i64\n }\n}\n\nimpl Packable for [T; N]\nwhere\n T: Packable,\n{\n fn pack(self) -> [Field; N * M] {\n let mut result: [Field; N * M] = std::mem::zeroed();\n let mut serialized: [Field; M] = std::mem::zeroed();\n for i in 0..N {\n serialized = self[i].pack();\n for j in 0..M {\n result[i * M + j] = serialized[j];\n }\n }\n result\n }\n\n fn unpack(fields: [Field; N * M]) -> Self {\n let mut reader = crate::utils::reader::Reader::new(fields);\n let mut result: [T; N] = std::mem::zeroed();\n reader.read_struct_array::(Packable::unpack, result)\n }\n}\n\n#[test]\nfn test_u16_packing() {\n let a: u16 = 10;\n assert_eq(a, u16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i8_packing() {\n let a: i8 = -10;\n assert_eq(a, i8::unpack(a.pack()));\n}\n\n#[test]\nfn test_i16_packing() {\n let a: i16 = -10;\n assert_eq(a, i16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i32_packing() {\n let a: i32 = -10;\n assert_eq(a, i32::unpack(a.pack()));\n}\n\n#[test]\nfn test_i64_packing() {\n let a: i64 = -10;\n assert_eq(a, i64::unpack(a.pack()));\n}\n" - }, - "337": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/noir-protocol-circuits/crates/types/src/type_serialization.nr", - "source": "use crate::traits::{Deserialize, Serialize};\n\nglobal BOOL_SERIALIZED_LEN: u32 = 1;\nglobal U8_SERIALIZED_LEN: u32 = 1;\nglobal U16_SERIALIZED_LEN: u32 = 1;\nglobal U32_SERIALIZED_LEN: u32 = 1;\nglobal U64_SERIALIZED_LEN: u32 = 1;\nglobal U128_SERIALIZED_LEN: u32 = 1;\nglobal FIELD_SERIALIZED_LEN: u32 = 1;\nglobal I8_SERIALIZED_LEN: u32 = 1;\nglobal I16_SERIALIZED_LEN: u32 = 1;\nglobal I32_SERIALIZED_LEN: u32 = 1;\nglobal I64_SERIALIZED_LEN: u32 = 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; U8_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 u16 {\n fn serialize(self) -> [Field; U16_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u16 {\n fn deserialize(fields: [Field; U16_SERIALIZED_LEN]) -> Self {\n fields[0] as u16\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; U128_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u128 {\n fn deserialize(fields: [Field; U128_SERIALIZED_LEN]) -> Self {\n fields[0] as u128\n }\n}\n\nimpl Serialize for Field {\n fn serialize(self) -> [Field; FIELD_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\nimpl Serialize for i8 {\n fn serialize(self) -> [Field; I8_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for i8 {\n fn deserialize(fields: [Field; I8_SERIALIZED_LEN]) -> Self {\n fields[0] as i8\n }\n}\n\nimpl Serialize for i16 {\n fn serialize(self) -> [Field; I16_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for i16 {\n fn deserialize(fields: [Field; I16_SERIALIZED_LEN]) -> Self {\n fields[0] as i16\n }\n}\n\nimpl Serialize for i32 {\n fn serialize(self) -> [Field; I32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for i32 {\n fn deserialize(fields: [Field; I32_SERIALIZED_LEN]) -> Self {\n fields[0] as i32\n }\n}\n\nimpl Serialize for i64 {\n fn serialize(self) -> [Field; I64_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for i64 {\n fn deserialize(fields: [Field; I64_SERIALIZED_LEN]) -> Self {\n fields[0] as i64\n }\n}\n\nimpl Serialize for [T; N]\nwhere\n T: Serialize,\n{\n fn serialize(self) -> [Field; N * M] {\n let mut result: [Field; N * M] = std::mem::zeroed();\n let mut serialized: [Field; M] = std::mem::zeroed();\n for i in 0..N {\n serialized = self[i].serialize();\n for j in 0..M {\n result[i * M + j] = serialized[j];\n }\n }\n result\n }\n}\n\nimpl Deserialize for [T; N]\nwhere\n T: Deserialize,\n{\n fn deserialize(fields: [Field; N * M]) -> Self {\n let mut reader = crate::utils::reader::Reader::new(fields);\n let mut result: [T; N] = std::mem::zeroed();\n reader.read_struct_array::(Deserialize::deserialize, result)\n }\n}\n\n#[test]\nfn test_u16_serialization() {\n let a: u16 = 10;\n assert_eq(a, u16::deserialize(a.serialize()));\n}\n\n#[test]\nfn test_i8_serialization() {\n let a: i8 = -10;\n assert_eq(a, i8::deserialize(a.serialize()));\n}\n\n#[test]\nfn test_i16_serialization() {\n let a: i16 = -10;\n assert_eq(a, i16::deserialize(a.serialize()));\n}\n\n#[test]\nfn test_i32_serialization() {\n let a: i32 = -10;\n assert_eq(a, i32::deserialize(a.serialize()));\n}\n\n#[test]\nfn test_i64_serialization() {\n let a: i64 = -10;\n assert_eq(a, i64::deserialize(a.serialize()));\n}\n" - }, - "353": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr", - "source": "pub mod assert_array_appended;\npub mod assert_array_prepended;\npub mod assert_combined_array;\npub mod assert_combined_transformed_array;\npub mod assert_exposed_sorted_transformed_value_array;\npub mod assert_sorted_array;\npub mod assert_sorted_transformed_value_array;\npub mod assert_split_sorted_transformed_value_arrays;\npub mod assert_split_transformed_value_arrays;\npub mod get_sorted_result;\npub mod get_sorted_tuple;\npub mod sort_by;\npub mod sort_by_counter;\n\n// Re-exports.\npub use assert_array_appended::{\n assert_array_appended, assert_array_appended_and_scoped, assert_array_appended_reversed,\n assert_array_appended_scoped,\n};\npub use assert_array_prepended::assert_array_prepended;\npub use assert_combined_array::{assert_combined_array, combine_arrays};\npub use assert_combined_transformed_array::{\n assert_combined_transformed_array, combine_and_transform_arrays,\n};\npub use assert_exposed_sorted_transformed_value_array::{\n assert_exposed_sorted_transformed_value_array,\n get_order_hints::{get_order_hints_asc, OrderHint},\n};\npub use assert_sorted_array::assert_sorted_array;\npub use assert_sorted_transformed_value_array::{\n assert_sorted_transformed_value_array, assert_sorted_transformed_value_array_capped_size,\n};\npub use assert_split_sorted_transformed_value_arrays::{\n assert_split_sorted_transformed_value_arrays_asc,\n get_split_order_hints::{get_split_order_hints_asc, SplitOrderHints},\n};\npub use assert_split_transformed_value_arrays::assert_split_transformed_value_arrays;\npub use get_sorted_result::{get_sorted_result, SortedResult};\npub use sort_by_counter::sort_by_counter_asc;\n\nuse crate::traits::{Empty, is_empty};\n\npub fn subarray(\n src: [Field; SRC_LEN],\n offset: u32,\n) -> [Field; DST_LEN] {\n assert(offset + DST_LEN <= SRC_LEN, \"offset too large\");\n\n let mut dst: [Field; DST_LEN] = std::mem::zeroed();\n for i in 0..DST_LEN {\n dst[i] = src[i + offset];\n }\n\n dst\n}\n\n// Helper function to convert a validated array to BoundedVec.\n// Important: Only use it for validated arrays: validate_array(array) should be true.\npub unconstrained fn array_to_bounded_vec(array: [T; N]) -> BoundedVec\nwhere\n T: Empty + Eq,\n{\n let len = array_length(array);\n BoundedVec::from_parts_unchecked(array, len)\n}\n\n// Helper function to find the index of the first element in an array that satisfies a given predicate. If the element\n// is not found, the function returns N as the index.\npub unconstrained fn find_index_hint(\n array: [T; N],\n find: fn[Env](T) -> bool,\n) -> u32 {\n let mut index = N;\n for i in 0..N {\n // We check `index == N` to ensure that we only update the index if we haven't found a match yet.\n if (index == N) & find(array[i]) {\n index = i;\n }\n }\n index\n}\n\n// Routine which validates that all zero values of an array form a contiguous region at the end, i.e.,\n// of the form: [*,*,*...,0,0,0,0] where any * is non-zero. Note that a full array of non-zero values is\n// valid.\npub fn validate_array(array: [T; N]) -> u32\nwhere\n T: Empty + Eq,\n{\n let mut seen_empty = false;\n let mut length = 0;\n for i in 0..N {\n if is_empty(array[i]) {\n seen_empty = true;\n } else {\n assert(seen_empty == false, \"invalid array\");\n length += 1;\n }\n }\n length\n}\n\n// Helper function to count the number of non-empty elements in a validated array.\n// Important: Only use it for validated arrays where validate_array(array) returns true,\n// which ensures that:\n// 1. All elements before the first empty element are non-empty\n// 2. All elements after and including the first empty element are empty\n// 3. The array forms a contiguous sequence of non-empty elements followed by empty elements\npub fn array_length(array: [T; N]) -> u32\nwhere\n T: Empty + Eq,\n{\n // We get the length by checking the index of the first empty element.\n\n // Safety: This is safe because we have validated the array (see function doc above) and the emptiness\n // of the element and non-emptiness of the previous element is checked below.\n let length = unsafe { find_index_hint(array, |elem: T| is_empty(elem)) };\n if length != 0 {\n assert(!is_empty(array[length - 1]));\n }\n if length != N {\n assert(is_empty(array[length]));\n }\n length\n}\n\n// Returns the number of consecutive elements at the start of the array for which the predicate returns false.\n// This function ensures that any element after the first matching element (predicate returns true) also matches the predicate.\npub fn array_length_until(array: [T; N], predicate: fn[Env](T) -> bool) -> u32 {\n let mut length = 0;\n let mut stop = false;\n for i in 0..N {\n if predicate(array[i]) {\n stop = true;\n } else {\n assert(\n stop == false,\n \"matching element found after already encountering a non-matching element\",\n );\n length += 1;\n }\n }\n length\n}\n\npub fn array_concat(array1: [T; N], array2: [T; M]) -> [T; N + M] {\n let mut result = [array1[0]; N + M];\n for i in 1..N {\n result[i] = array1[i];\n }\n for i in 0..M {\n result[i + N] = array2[i];\n }\n result\n}\n\n/// This function assumes that `array1` and `array2` contain no more than N non-empty elements between them,\n/// if this is not the case then elements from the end of `array2` will be dropped.\npub fn array_merge(array1: [T; N], array2: [T; N]) -> [T; N]\nwhere\n T: Empty + Eq,\n{\n // Safety: we constrain this array below\n let result = unsafe { array_merge_helper(array1, array2) };\n // We assume arrays have been validated. The only use cases so far are with previously validated arrays.\n let array1_len = array_length(array1);\n let mut add_from_left = true;\n for i in 0..N {\n add_from_left &= i != array1_len;\n if add_from_left {\n assert_eq(result[i], array1[i]);\n } else {\n assert_eq(result[i], array2[i - array1_len]);\n }\n }\n result\n}\n\nunconstrained fn array_merge_helper(array1: [T; N], array2: [T; N]) -> [T; N]\nwhere\n T: Empty + Eq,\n{\n let mut result: [T; N] = [T::empty(); N];\n let mut i = 0;\n for elem in array1 {\n if !is_empty(elem) {\n result[i] = elem;\n i += 1;\n }\n }\n for elem in array2 {\n if !is_empty(elem) {\n result[i] = elem;\n i += 1;\n }\n }\n result\n}\n\n// Helper fn to create a subarray from a given array\npub fn array_splice(array: [T; N], offset: u32) -> [T; M]\nwhere\n T: Empty,\n{\n assert(M + offset <= N, \"Subarray length larger than array length\");\n let mut result: [T; M] = [T::empty(); M];\n for i in 0..M {\n result[i] = array[offset + i];\n }\n result\n}\n\npub fn check_permutation(\n original_array: [T; N],\n permuted_array: [T; N],\n original_indexes: [u32; N],\n)\nwhere\n T: Eq + Empty,\n{\n let mut seen_value = [false; N];\n for i in 0..N {\n let index = original_indexes[i];\n let original_value = original_array[index];\n assert(permuted_array[i].eq(original_value), \"Invalid index\");\n assert(!seen_value[index], \"Duplicated index\");\n seen_value[index] = true;\n }\n}\n\n// Helper function to find the index of the last element in an array, allowing empty elements.\n// e.g. useful for removing trailing 0s from [1, 0, 2, 0, 0, 0] -> [1, 0, 2]\n// Nothing to do with validated arrays. Correctness constrained by padded_array_length.\npub unconstrained fn find_last_value_index(array: [T; N]) -> u32\nwhere\n T: Empty + Eq,\n{\n let mut index = N;\n for i in 0..N {\n let j = N - i - 1;\n // We check `index == N` to ensure that we only update the index if we haven't found a match yet.\n if (index == N) & !is_empty(array[j]) {\n index = j;\n }\n }\n index\n}\n\n// Routine which returns the length of an array right padded by empty elements\n// of the form: [*,*,*...,0,0,0,0] where * is any value (zeroes allowed).\n// See smoke_validate_array_trailing for examples.\n// Nothing to do with validated arrays. Correctness constrained by padded_array_length.\npub unconstrained fn unsafe_padded_array_length(array: [T; N]) -> u32\nwhere\n T: Empty + Eq,\n{\n let index = find_last_value_index(array);\n if index == N {\n 0\n } else {\n index + 1\n }\n}\n\n// Routine which validates that zero values of an array form a contiguous region at the end, i.e.,\n// of the form: [*,*,*...,0,0,0,0] where * is any value (zeroes allowed).\npub fn padded_array_length(array: [T; N]) -> u32\nwhere\n T: Empty + Eq,\n{\n // Safety: this value is constrained in the below loop.\n let length = unsafe { unsafe_padded_array_length(array) };\n // Check the elt just before length is non-zero:\n if length != 0 {\n assert(!is_empty(array[length - 1]), \"invalid right padded array\");\n }\n // Check all beyond length are zero:\n let mut check_zero = false;\n for i in 0..N {\n check_zero |= i == length;\n if check_zero {\n assert(is_empty(array[i]), \"invalid right padded array\");\n }\n }\n length\n}\n\n// Helper function to check if an array is padded with a given value from a given index.\n// Different to padded_array_length in that it allows the elements before the given index to be the same as the padded value.\npub fn array_padded_with(array: [T; N], from_index: u32, padded_with: T) -> bool\nwhere\n T: Eq,\n{\n let mut is_valid = true;\n let mut should_check = false;\n for i in 0..N {\n should_check |= i == from_index;\n is_valid &= !should_check | (array[i] == padded_with);\n }\n is_valid\n}\n\n#[test]\nfn smoke_validate_array() {\n let valid_array: [Field; 0] = [];\n assert(validate_array(valid_array) == 0);\n\n let valid_array = [0];\n assert(validate_array(valid_array) == 0);\n\n let valid_array = [3];\n assert(validate_array(valid_array) == 1);\n\n let valid_array = [1, 2, 3];\n assert(validate_array(valid_array) == 3);\n\n let valid_array = [1, 2, 3, 0];\n assert(validate_array(valid_array) == 3);\n\n let valid_array = [1, 2, 3, 0, 0];\n assert(validate_array(valid_array) == 3);\n}\n\n#[test]\nfn smoke_validate_array_trailing() {\n let valid_array: [Field; 0] = [];\n assert(padded_array_length(valid_array) == 0);\n\n let valid_array = [0];\n assert(padded_array_length(valid_array) == 0);\n\n let valid_array = [3];\n assert(padded_array_length(valid_array) == 1);\n\n let valid_array = [1, 0, 3];\n assert(padded_array_length(valid_array) == 3);\n\n let valid_array = [1, 0, 3, 0];\n assert(padded_array_length(valid_array) == 3);\n\n let valid_array = [1, 2, 3, 0, 0];\n assert(padded_array_length(valid_array) == 3);\n\n let valid_array = [0, 0, 3, 0, 0];\n assert(padded_array_length(valid_array) == 3);\n}\n\n#[test(should_fail_with = \"invalid array\")]\nfn smoke_validate_array_invalid_case0() {\n let invalid_array = [0, 1];\n let _ = validate_array(invalid_array);\n}\n\n#[test(should_fail_with = \"invalid array\")]\nfn smoke_validate_array_invalid_case1() {\n let invalid_array = [1, 0, 0, 1, 0];\n let _ = validate_array(invalid_array);\n}\n\n#[test(should_fail_with = \"invalid array\")]\nfn smoke_validate_array_invalid_case2() {\n let invalid_array = [0, 0, 0, 0, 1];\n let _ = validate_array(invalid_array);\n}\n\n#[test]\nfn test_empty_array_length() {\n assert_eq(array_length([0]), 0);\n assert_eq(array_length([0, 0, 0]), 0);\n}\n\n#[test]\nfn test_array_length() {\n assert_eq(array_length([123]), 1);\n assert_eq(array_length([123, 0, 0]), 1);\n assert_eq(array_length([123, 456]), 2);\n assert_eq(array_length([123, 456, 0]), 2);\n}\n\n#[test]\nfn test_array_length_invalid_arrays() {\n // Result can be misleading (but correct) for invalid arrays.\n assert_eq(array_length([0, 0, 123]), 0);\n assert_eq(array_length([0, 123, 0]), 0);\n assert_eq(array_length([0, 123, 456]), 0);\n assert_eq(array_length([123, 0, 456]), 1);\n}\n\n#[test]\nfn test_array_length_until() {\n let array = [11, 22, 33, 44, 55];\n assert_eq(array_length_until(array, |x| x == 55), 4);\n assert_eq(array_length_until(array, |x| x == 56), 5);\n assert_eq(array_length_until(array, |x| x > 40), 3);\n assert_eq(array_length_until(array, |x| x > 10), 0);\n}\n\n#[test(should_fail_with = \"matching element found after already encountering a non-matching element\")]\nfn test_array_length_until_non_consecutive_fails() {\n let array = [1, 1, 0, 1, 0];\n let _ = array_length_until(array, |x| x == 0);\n}\n\n#[test(should_fail_with = \"matching element found after already encountering a non-matching element\")]\nfn test_array_length_until_first_non_matching_fails() {\n let array = [1, 0, 0, 0, 0];\n let _ = array_length_until(array, |x| x == 1);\n}\n\n#[test]\nunconstrained fn find_index_greater_than_min() {\n let values = [10, 20, 30, 40];\n let min = 22;\n let index = find_index_hint(values, |v: Field| min.lt(v));\n assert_eq(index, 2);\n}\n\n#[test]\nunconstrained fn find_index_not_found() {\n let values = [10, 20, 30, 40];\n let min = 100;\n let index = find_index_hint(values, |v: Field| min.lt(v));\n assert_eq(index, 4);\n}\n\n#[test]\nfn test_array_concat() {\n let array0 = [1, 2, 3];\n let array1 = [4, 5];\n let concatenated = array_concat(array0, array1);\n assert_eq(concatenated, [1, 2, 3, 4, 5]);\n}\n\n#[test]\nfn check_permutation_basic_test() {\n let original_array = [1, 2, 3];\n let permuted_array = [3, 1, 2];\n let indexes = [2, 0, 1];\n check_permutation(original_array, permuted_array, indexes);\n}\n\n#[test(should_fail_with = \"Duplicated index\")]\nfn check_permutation_duplicated_index() {\n let original_array = [0, 1, 0];\n let permuted_array = [1, 0, 0];\n let indexes = [1, 0, 0];\n check_permutation(original_array, permuted_array, indexes);\n}\n\n#[test(should_fail_with = \"Invalid index\")]\nfn check_permutation_invalid_index() {\n let original_array = [0, 1, 2];\n let permuted_array = [1, 0, 0];\n let indexes = [1, 0, 2];\n check_permutation(original_array, permuted_array, indexes);\n}\n\n#[test]\nfn test_array_padded_with() {\n let array = [11, 22, 33, 44, 44];\n assert_eq(array_padded_with(array, 0, 44), false);\n assert_eq(array_padded_with(array, 1, 44), false);\n assert_eq(array_padded_with(array, 2, 44), false);\n assert_eq(array_padded_with(array, 3, 44), true);\n assert_eq(array_padded_with(array, 4, 44), true);\n assert_eq(array_padded_with(array, 4, 33), false);\n assert_eq(array_padded_with(array, 5, 44), true); // Index out of bounds.\n assert_eq(array_padded_with(array, 0, 11), false);\n}\n" - }, - "356": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr", - "source": "pub 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) -> [Field; K] {\n let mut result = [0; 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 pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array());\n result\n }\n\n pub fn read_struct_array(\n &mut self,\n deserialise: fn([Field; K]) -> T,\n mut result: [T; C],\n ) -> [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" - }, - "366": { - "path": "/mnt/user-data/saleel/nargo/github.com/noir-lang/sha256/v0.1.2/src/sha256.nr", - "source": "use std::hash::sha256_compression;\nuse std::runtime::is_unconstrained;\n\nuse constants::{\n BLOCK_BYTE_PTR, BLOCK_SIZE, HASH, INITIAL_STATE, INT_BLOCK, INT_BLOCK_SIZE, INT_SIZE,\n INT_SIZE_PTR, MSG_BLOCK, MSG_SIZE_PTR, STATE, TWO_POW_16, TWO_POW_24, TWO_POW_32, TWO_POW_8,\n};\n\nmod constants;\nmod tests;\n\n// Implementation of SHA-256 mapping a byte array of variable length to\n// 32 bytes.\n\n// Deprecated in favour of `sha256_var`\n// docs:start:sha256\npub fn sha256(input: [u8; N]) -> HASH\n// docs:end:sha256\n{\n digest(input)\n}\n\n// SHA-256 hash function\n#[no_predicates]\npub fn digest(msg: [u8; N]) -> HASH {\n sha256_var(msg, N as u64)\n}\n\n// Variable size SHA-256 hash\npub fn sha256_var(msg: [u8; N], message_size: u64) -> HASH {\n let message_size = message_size as u32;\n assert(message_size <= N);\n\n if std::runtime::is_unconstrained() {\n // Safety: SHA256 is running as an unconstrained function.\n unsafe {\n __sha256_var(msg, message_size)\n }\n } else {\n let mut msg_block: MSG_BLOCK = [0; INT_BLOCK_SIZE];\n // Intermediate hash, starting with the canonical initial value\n let mut h: STATE = INITIAL_STATE;\n // Pointer into msg_block on a 64 byte scale\n let mut msg_byte_ptr = 0;\n let num_blocks = N / BLOCK_SIZE;\n for i in 0..num_blocks {\n let msg_start = BLOCK_SIZE * i;\n let (new_msg_block, new_msg_byte_ptr) =\n unsafe { build_msg_block(msg, message_size, msg_start) };\n\n if msg_start < message_size {\n msg_block = new_msg_block;\n }\n\n // Verify the block we are compressing was appropriately constructed\n let new_msg_byte_ptr = verify_msg_block(msg, message_size, msg_block, msg_start);\n if msg_start < message_size {\n msg_byte_ptr = new_msg_byte_ptr;\n }\n\n // If the block is filled, compress it.\n // An un-filled block is handled after this loop.\n if (msg_start < message_size) & (msg_byte_ptr == BLOCK_SIZE) {\n h = sha256_compression(msg_block, h);\n }\n }\n\n let modulo = N % BLOCK_SIZE;\n // Handle setup of the final msg block.\n // This case is only hit if the msg is less than the block size,\n // or our message cannot be evenly split into blocks.\n if modulo != 0 {\n let msg_start = BLOCK_SIZE * num_blocks;\n let (new_msg_block, new_msg_byte_ptr) =\n unsafe { build_msg_block(msg, message_size, msg_start) };\n\n if msg_start < message_size {\n msg_block = new_msg_block;\n }\n\n let new_msg_byte_ptr = verify_msg_block(msg, message_size, msg_block, msg_start);\n if msg_start < message_size {\n msg_byte_ptr = new_msg_byte_ptr;\n verify_msg_block_padding(msg_block, msg_byte_ptr);\n }\n }\n\n // If we had modulo == 0 then it means the last block was full,\n // and we can reset the pointer to zero to overwrite it.\n if msg_byte_ptr == BLOCK_SIZE {\n msg_byte_ptr = 0;\n }\n\n // Pad the rest such that we have a [u32; 2] block at the end representing the length\n // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]).\n // Here we rely on the fact that everything beyond the available input is set to 0.\n let index = msg_byte_ptr / INT_SIZE;\n msg_block[index] = set_item_byte_then_zeros(msg_block[index], msg_byte_ptr, 1 << 7);\n\n msg_byte_ptr = msg_byte_ptr + 1;\n let last_block = msg_block;\n\n // If we don't have room to write the size, compress the block and reset it.\n if msg_byte_ptr > MSG_SIZE_PTR {\n h = sha256_compression(msg_block, h);\n // `attach_len_to_msg_block` will zero out everything after the `msg_byte_ptr`.\n msg_byte_ptr = 0;\n }\n\n msg_block = unsafe { attach_len_to_msg_block(msg_block, msg_byte_ptr, message_size) };\n\n verify_msg_len(msg_block, last_block, msg_byte_ptr, message_size);\n\n hash_final_block(msg_block, h)\n }\n}\n\n// Variable size SHA-256 hash\nunconstrained fn __sha256_var(msg: [u8; N], message_size: u32) -> HASH {\n let num_full_blocks = message_size / BLOCK_SIZE;\n // Intermediate hash, starting with the canonical initial value\n let mut h: STATE = INITIAL_STATE;\n // Pointer into msg_block on a 64 byte scale\n for i in 0..num_full_blocks {\n let (msg_block, _) = build_msg_block(msg, message_size, BLOCK_SIZE * i);\n h = sha256_compression(msg_block, h);\n }\n\n // Handle setup of the final msg block.\n // This case is only hit if the msg is less than the block size,\n // or our message cannot be evenly split into blocks.\n let modulo = message_size % BLOCK_SIZE;\n let (mut msg_block, mut msg_byte_ptr): (INT_BLOCK, u32) = if modulo != 0 {\n let msg_start = BLOCK_SIZE * num_full_blocks;\n let (new_msg_block, new_msg_byte_ptr) = build_msg_block(msg, message_size, msg_start);\n\n (new_msg_block, new_msg_byte_ptr)\n } else {\n // If we had modulo == 0 then it means the last block was full,\n // and we can reset the pointer to zero to overwrite it.\n ([0; INT_BLOCK_SIZE], 0)\n };\n\n // Pad the rest such that we have a [u32; 2] block at the end representing the length\n // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]).\n // Here we rely on the fact that everything beyond the available input is set to 0.\n let index = msg_byte_ptr / INT_SIZE;\n msg_block[index] = set_item_byte_then_zeros(msg_block[index], msg_byte_ptr, 1 << 7);\n\n // If we don't have room to write the size, compress the block and reset it.\n let (h, mut msg_byte_ptr): (STATE, u32) = if msg_byte_ptr >= MSG_SIZE_PTR {\n // `attach_len_to_msg_block` will zero out everything after the `msg_byte_ptr`.\n (sha256_compression(msg_block, h), 0)\n } else {\n (h, msg_byte_ptr + 1)\n };\n msg_block = attach_len_to_msg_block(msg_block, msg_byte_ptr, message_size);\n\n hash_final_block(msg_block, h)\n}\n\n// Take `BLOCK_SIZE` number of bytes from `msg` starting at `msg_start`.\n// Returns the block and the length that has been copied rather than padded with zeros.\nunconstrained fn build_msg_block(\n msg: [u8; N],\n message_size: u32,\n msg_start: u32,\n) -> (MSG_BLOCK, BLOCK_BYTE_PTR) {\n let mut msg_block: MSG_BLOCK = [0; INT_BLOCK_SIZE];\n\n // We insert `BLOCK_SIZE` bytes (or up to the end of the message)\n let block_input = if message_size < msg_start {\n // This function is sometimes called with `msg_start` past the end of the message.\n // In this case we return an empty block and zero pointer to signal that the result should be ignored.\n 0\n } else if message_size < msg_start + BLOCK_SIZE {\n message_size - msg_start\n } else {\n BLOCK_SIZE\n };\n\n // Figure out the number of items in the int array that we have to pack.\n // e.g. if the input is [0,1,2,3,4,5] then we need to pack it as 2 items: [0123, 4500]\n let mut int_input = block_input / INT_SIZE;\n if block_input % INT_SIZE != 0 {\n int_input = int_input + 1;\n };\n\n for i in 0..int_input {\n let mut msg_item: u32 = 0;\n // Always construct the integer as 4 bytes, even if it means going beyond the input.\n for j in 0..INT_SIZE {\n let k = i * INT_SIZE + j;\n let msg_byte = if k < block_input {\n msg[msg_start + k]\n } else {\n 0\n };\n msg_item = lshift8(msg_item, 1) + msg_byte as u32;\n }\n msg_block[i] = msg_item;\n }\n\n // Returning the index as if it was a 64 byte array.\n // We have to project it down to 16 items and bit shifting to get a byte back if we need it.\n (msg_block, block_input)\n}\n\n// Verify the block we are compressing was appropriately constructed by `build_msg_block`\n// and matches the input data. Returns the index of the first unset item.\n// If `message_size` is less than `msg_start` then this is called with the old non-empty block;\n// in that case we can skip verification, ie. no need to check that everything is zero.\nfn verify_msg_block(\n msg: [u8; N],\n message_size: u32,\n msg_block: MSG_BLOCK,\n msg_start: u32,\n) -> BLOCK_BYTE_PTR {\n let mut msg_byte_ptr = 0;\n let mut msg_end = msg_start + BLOCK_SIZE;\n if msg_end > N {\n msg_end = N;\n }\n // We might have to go beyond the input to pad the fields.\n if msg_end % INT_SIZE != 0 {\n msg_end = msg_end + INT_SIZE - msg_end % INT_SIZE;\n }\n\n // Reconstructed packed item.\n let mut msg_item: u32 = 0;\n\n // Inclusive at the end so that we can compare the last item.\n let mut i: u32 = 0;\n for k in msg_start..=msg_end {\n if k % INT_SIZE == 0 {\n // If we consumed some input we can compare against the block.\n if (msg_start < message_size) & (k > msg_start) {\n assert_eq(msg_block[i], msg_item as u32);\n i = i + 1;\n msg_item = 0;\n }\n }\n // Shift the accumulator\n msg_item = lshift8(msg_item, 1);\n // If we have input to consume, add it at the rightmost position.\n if k < message_size & k < msg_end {\n msg_item = msg_item + msg[k] as u32;\n msg_byte_ptr = msg_byte_ptr + 1;\n }\n }\n\n msg_byte_ptr\n}\n\n// Verify the block we are compressing was appropriately padded with zeros by `build_msg_block`.\n// This is only relevant for the last, potentially partially filled block.\nfn verify_msg_block_padding(msg_block: MSG_BLOCK, msg_byte_ptr: BLOCK_BYTE_PTR) {\n // Check all the way to the end of the block.\n verify_msg_block_zeros(msg_block, msg_byte_ptr, INT_BLOCK_SIZE);\n}\n\n// Verify that a region of ints in the message block are (partially) zeroed,\n// up to an (exclusive) maximum which can either be the end of the block\n// or just where the size is to be written.\nfn verify_msg_block_zeros(\n msg_block: MSG_BLOCK,\n mut msg_byte_ptr: BLOCK_BYTE_PTR,\n max_int_byte_ptr: u32,\n) {\n // This variable is used to get around the compiler under-constrained check giving a warning.\n // We want to check against a constant zero, but if it does not come from the circuit inputs\n // or return values the compiler check will issue a warning.\n let zero = msg_block[0] - msg_block[0];\n\n // First integer which is supposed to be (partially) zero.\n let mut int_byte_ptr = msg_byte_ptr / INT_SIZE;\n\n // Check partial zeros.\n let modulo = msg_byte_ptr % INT_SIZE;\n if modulo != 0 {\n let zeros = INT_SIZE - modulo;\n let mask = if zeros == 3 {\n TWO_POW_24\n } else if zeros == 2 {\n TWO_POW_16\n } else {\n TWO_POW_8\n };\n assert_eq(msg_block[int_byte_ptr] % mask, zero);\n int_byte_ptr = int_byte_ptr + 1;\n }\n\n // Check the rest of the items.\n for i in 0..max_int_byte_ptr {\n if i >= int_byte_ptr {\n assert_eq(msg_block[i], zero);\n }\n }\n}\n\n// Verify that up to the byte pointer the two blocks are equal.\n// At the byte pointer the new block can be partially zeroed.\nfn verify_msg_block_equals_last(\n msg_block: MSG_BLOCK,\n last_block: MSG_BLOCK,\n mut msg_byte_ptr: BLOCK_BYTE_PTR,\n) {\n // msg_byte_ptr is the position at which they are no longer have to be the same.\n // First integer which is supposed to be (partially) zero contains that pointer.\n let mut int_byte_ptr = msg_byte_ptr / INT_SIZE;\n\n // Check partial zeros.\n let modulo = msg_byte_ptr % INT_SIZE;\n if modulo != 0 {\n // Reconstruct the partially zero item from the last block.\n let last_field = last_block[int_byte_ptr];\n let mut msg_item: u32 = 0;\n // Reset to where they are still equal.\n msg_byte_ptr = msg_byte_ptr - modulo;\n for i in 0..INT_SIZE {\n msg_item = lshift8(msg_item, 1);\n if i < modulo {\n msg_item = msg_item + get_item_byte(last_field, msg_byte_ptr) as u32;\n msg_byte_ptr = msg_byte_ptr + 1;\n }\n }\n assert_eq(msg_block[int_byte_ptr], msg_item);\n }\n\n for i in 0..INT_SIZE_PTR {\n if i < int_byte_ptr {\n assert_eq(msg_block[i], last_block[i]);\n }\n }\n}\n\n// Set the rightmost `zeros` number of bytes to 0.\n#[inline_always]\nfn set_item_zeros(item: u32, zeros: u8) -> u32 {\n lshift8(rshift8(item, zeros), zeros)\n}\n\n// Replace one byte in the item with a value, and set everything after it to zero.\nfn set_item_byte_then_zeros(msg_item: u32, msg_byte_ptr: BLOCK_BYTE_PTR, msg_byte: u8) -> u32 {\n let zeros = INT_SIZE - msg_byte_ptr % INT_SIZE;\n let zeroed_item = set_item_zeros(msg_item, zeros as u8);\n let new_item = byte_into_item(msg_byte, msg_byte_ptr);\n zeroed_item + new_item\n}\n\n// Get a byte of a message item according to its overall position in the `BLOCK_SIZE` space.\nfn get_item_byte(mut msg_item: u32, msg_byte_ptr: BLOCK_BYTE_PTR) -> u8 {\n // How many times do we have to shift to the right to get to the position we want?\n let max_shifts = INT_SIZE - 1;\n let shifts = max_shifts - msg_byte_ptr % INT_SIZE;\n msg_item = rshift8(msg_item, shifts as u8);\n // At this point the byte we want is in the rightmost position.\n msg_item as u8\n}\n\n// Project a byte into a position in a field based on the overall block pointer.\n// For example putting 1 into pointer 5 would be 100, because overall we would\n// have [____, 0100] with indexes [0123,4567].\n#[inline_always]\nfn byte_into_item(msg_byte: u8, msg_byte_ptr: BLOCK_BYTE_PTR) -> u32 {\n let mut msg_item = msg_byte as u32;\n // How many times do we have to shift to the left to get to the position we want?\n let max_shifts = INT_SIZE - 1;\n let shifts = max_shifts - msg_byte_ptr % INT_SIZE;\n lshift8(msg_item, shifts as u8)\n}\n\n// Construct a field out of 4 bytes.\n#[inline_always]\nfn make_item(b0: u8, b1: u8, b2: u8, b3: u8) -> u32 {\n let mut item = b0 as u32;\n item = lshift8(item, 1) + b1 as u32;\n item = lshift8(item, 1) + b2 as u32;\n item = lshift8(item, 1) + b3 as u32;\n item\n}\n\n// Shift by 8 bits to the left between 0 and 4 times.\n// Checks `is_unconstrained()` to just use a bitshift if we're running in an unconstrained context,\n// otherwise multiplies by 256.\n#[inline_always]\nfn lshift8(item: u32, shifts: u8) -> u32 {\n if is_unconstrained() {\n // Brillig wouldn't shift 0<<4 without overflow.\n if shifts >= 4 {\n 0\n } else {\n item << (8 * shifts)\n }\n } else {\n // We can do a for loop up to INT_SIZE or an if-else.\n if shifts == 0 {\n item\n } else if shifts == 1 {\n item * TWO_POW_8\n } else if shifts == 2 {\n item * TWO_POW_16\n } else if shifts == 3 {\n item * TWO_POW_24\n } else {\n // Doesn't make sense, but it's most likely called on 0 anyway.\n 0\n }\n }\n}\n\n// Shift by 8 bits to the right between 0 and 4 times.\n// Checks `is_unconstrained()` to just use a bitshift if we're running in an unconstrained context,\n// otherwise divides by 256.\nfn rshift8(item: u32, shifts: u8) -> u32 {\n if is_unconstrained() {\n item >> (8 * shifts)\n } else {\n // Division wouldn't work on `Field`.\n if shifts == 0 {\n item\n } else if shifts == 1 {\n item / TWO_POW_8\n } else if shifts == 2 {\n item / TWO_POW_16\n } else if shifts == 3 {\n item / TWO_POW_24\n } else {\n 0\n }\n }\n}\n\n// Zero out all bytes between the end of the message and where the length is appended,\n// then write the length into the last 8 bytes of the block.\nunconstrained fn attach_len_to_msg_block(\n mut msg_block: MSG_BLOCK,\n mut msg_byte_ptr: BLOCK_BYTE_PTR,\n message_size: u32,\n) -> MSG_BLOCK {\n // We assume that `msg_byte_ptr` is less than 57 because if not then it is reset to zero before calling this function.\n // In any case, fill blocks up with zeros until the last 64 bits (i.e. until msg_byte_ptr = 56).\n // There can be one item which has to be partially zeroed.\n let modulo = msg_byte_ptr % INT_SIZE;\n if modulo != 0 {\n // Index of the block in which we find the item we need to partially zero.\n let i = msg_byte_ptr / INT_SIZE;\n let zeros = INT_SIZE - modulo;\n msg_block[i] = set_item_zeros(msg_block[i], zeros as u8);\n msg_byte_ptr = msg_byte_ptr + zeros;\n }\n\n // The rest can be zeroed without bit shifting anything.\n for i in (msg_byte_ptr / INT_SIZE)..INT_SIZE_PTR {\n msg_block[i] = 0;\n }\n\n // Set the last two 4 byte ints as the first/second half of the 8 bytes of the length.\n let len = 8 * message_size;\n let len_bytes: [u8; 8] = (len as Field).to_be_bytes();\n for i in 0..=1 {\n let shift = i * 4;\n msg_block[INT_SIZE_PTR + i] = make_item(\n len_bytes[shift],\n len_bytes[shift + 1],\n len_bytes[shift + 2],\n len_bytes[shift + 3],\n );\n }\n msg_block\n}\n\n// Verify that the message length was correctly written by `attach_len_to_msg_block`,\n// and that everything between the byte pointer and the size pointer was zeroed,\n// and that everything before the byte pointer was untouched.\nfn verify_msg_len(\n msg_block: MSG_BLOCK,\n last_block: MSG_BLOCK,\n msg_byte_ptr: BLOCK_BYTE_PTR,\n message_size: u32,\n) {\n // Check zeros up to the size pointer.\n verify_msg_block_zeros(msg_block, msg_byte_ptr, INT_SIZE_PTR);\n\n // Check that up to the pointer we match the last block.\n verify_msg_block_equals_last(msg_block, last_block, msg_byte_ptr);\n\n // We verify the message length was inserted correctly by reversing the byte decomposition.\n let mut reconstructed_len: u64 = 0;\n for i in INT_SIZE_PTR..INT_BLOCK_SIZE {\n reconstructed_len = reconstructed_len * TWO_POW_32;\n reconstructed_len = reconstructed_len + msg_block[i] as u64;\n }\n let len = 8 * message_size as u64;\n assert_eq(reconstructed_len, len);\n}\n\n// Perform the final compression, then transform the `STATE` into `HASH`.\nfn hash_final_block(msg_block: MSG_BLOCK, mut state: STATE) -> HASH {\n let mut out_h: HASH = [0; 32]; // Digest as sequence of bytes\n // Hash final padded block\n state = sha256_compression(msg_block, state);\n\n // Return final hash as byte array\n for j in 0..8 {\n let h_bytes: [u8; 4] = (state[j] as Field).to_be_bytes();\n for k in 0..4 {\n out_h[4 * j + k] = h_bytes[k];\n }\n }\n\n out_h\n}\n\nmod equivalence_test {\n\n #[test]\n fn test_implementations_agree(msg: [u8; 100], message_size: u64) {\n let message_size = message_size % 100;\n let unconstrained_sha = unsafe { super::__sha256_var(msg, message_size as u32) };\n let sha = super::sha256_var(msg, message_size);\n assert_eq(sha, unconstrained_sha);\n }\n}\n" - }, - "42": { - "path": "std/option.nr", - "source": "use crate::cmp::{Eq, Ord, Ordering};\nuse crate::default::Default;\nuse crate::hash::{Hash, Hasher};\n\npub struct 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::mem::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 {\n self._value\n } else {\n default\n }\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 pub 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 {\n self\n } else {\n other\n }\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 {\n self\n } else {\n default()\n }\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 {\n Option::none()\n } else {\n self\n }\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\nwhere\n T: Eq,\n{\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\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\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\nwhere\n T: Ord,\n{\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 if other._is_some {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n" - }, - "43": { - "path": "std/panic.nr", - "source": "pub fn panic(message: fmtstr) -> U {\n assert(false, message);\n crate::mem::zeroed()\n}\n" - }, - "50": { - "path": "/mnt/user-data/saleel/aztec-web-starter/contracts/src/main.nr", - "source": "use dep::aztec::macros::aztec;\n\n#[aztec]\npub contract EasyPrivateVoting {\n use dep::aztec:: macros::{\n functions::{initializer, internal, private, public, utility}, \n storage::storage\n };\n use dep::aztec::keys::getters::get_public_keys;\n use dep::aztec::prelude::{AztecAddress, Map, PublicImmutable, PublicMutable};\n use dep::aztec::protocol_types::traits::{Hash, ToField};\n\n #[storage]\n struct Storage {\n admin: PublicMutable, // admin can end vote\n tally: Map, Context>, // we will store candidate as key and number of votes as value\n vote_ended: PublicMutable, // vote_ended is boolean\n active_at_block: PublicImmutable, // when people can start voting\n }\n\n #[public]\n #[initializer]\n fn constructor(admin: AztecAddress) {\n storage.admin.write(admin);\n storage.vote_ended.write(false);\n storage.active_at_block.initialize(context.block_number() as u32);\n }\n\n #[private]\n fn cast_vote(candidate: Field) {\n let msg_sender_npk_m_hash = get_public_keys(context.msg_sender()).npk_m.hash();\n\n let secret = context.request_nsk_app(msg_sender_npk_m_hash); // get secret key of caller of function\n let nullifier = std::hash::pedersen_hash([context.msg_sender().to_field(), secret]); // derive nullifier from sender and secret\n context.push_nullifier(nullifier);\n EasyPrivateVoting::at(context.this_address()).add_to_tally_public(candidate).enqueue(\n &mut context,\n );\n }\n\n #[public]\n #[internal]\n fn add_to_tally_public(candidate: Field) {\n assert(storage.vote_ended.read() == false, \"Vote has ended\"); // assert that vote has not ended\n let new_tally = storage.tally.at(candidate).read() + 1;\n storage.tally.at(candidate).write(new_tally);\n }\n\n #[public]\n fn end_vote() {\n assert(storage.admin.read().eq(context.msg_sender()), \"Only admin can end votes\"); // assert that caller is admin\n storage.vote_ended.write(true);\n }\n\n #[utility]\n unconstrained fn get_vote(candidate: Field) -> Field {\n storage.tally.at(candidate).read()\n }\n}" - }, - "51": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/capsules/mod.nr", - "source": "use crate::oracle::capsules;\nuse protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}};\n\n/// A dynamically sized array backed by PXE's non-volatile database (called capsules). Values are persisted until\n/// deleted, so they can be e.g. stored during simulation of a transaction and later retrieved during witness\n/// generation. All values are scoped per contract address, so external contracts cannot access them.\npub struct CapsuleArray {\n contract_address: AztecAddress,\n /// The base slot is where the array length is stored in capsules. Array elements are stored in consecutive slots\n /// after the base slot. For example, with base slot 5: the length is at slot 5, the first element (index 0) is at\n /// slot 6, the second element (index 1) is at slot 7, and so on.\n base_slot: Field,\n}\n\nimpl CapsuleArray {\n /// Returns a CapsuleArray connected to a contract's capsules at a base slot. Array elements are stored in\n /// contiguous slots following the base slot, so there should be sufficient space between array base slots to\n /// accommodate elements. A reasonable strategy is to make the base slot a hash of a unique value.\n pub unconstrained fn at(contract_address: AztecAddress, base_slot: Field) -> Self {\n Self { contract_address, base_slot }\n }\n\n /// Returns the number of elements stored in the array.\n pub unconstrained fn len(self) -> u32 {\n // An uninitialized array defaults to a length of 0.\n capsules::load(self.contract_address, self.base_slot).unwrap_or(0) as u32\n }\n\n /// Stores a value at the end of the array.\n pub unconstrained fn push(self, value: T)\n where\n T: Serialize,\n {\n let current_length = self.len();\n\n // The slot corresponding to the index `current_length` is the first slot immediately after the end of the\n // array, which is where we want to place the new value.\n capsules::store(self.contract_address, self.slot_at(current_length), value);\n\n // Then we simply update the length.\n let new_length = current_length + 1;\n capsules::store(self.contract_address, self.base_slot, new_length);\n }\n\n /// Retrieves the value stored in the array at `index`. Throws if the index is out of bounds.\n pub unconstrained fn get(self, index: u32) -> T\n where\n T: Deserialize,\n {\n assert(index < self.len(), \"Attempted to read past the length of a CapsuleArray\");\n\n capsules::load(self.contract_address, self.slot_at(index)).unwrap()\n }\n\n /// Deletes the value stored in the array at `index`. Throws if the index is out of bounds.\n pub unconstrained fn remove(self, index: u32) {\n let current_length = self.len();\n assert(index < current_length, \"Attempted to delete past the length of a CapsuleArray\");\n\n // In order to be able to remove elements at arbitrary indices, we need to shift the entire contents of the\n // array past the removed element one slot backward so that we don't end up with a gap and preserve the\n // contiguous slots. We can skip this when deleting the last element however.\n if index != current_length - 1 {\n // The source and destination regions overlap, but `copy` supports this.\n capsules::copy(\n self.contract_address,\n self.slot_at(index + 1),\n self.slot_at(index),\n current_length - index - 1,\n );\n }\n\n // We can now delete the last element (which has either been copied to the slot immediately before it, or was\n // the element we meant to delete in the first place) and update the length.\n capsules::delete(self.contract_address, self.slot_at(current_length - 1));\n capsules::store(self.contract_address, self.base_slot, current_length - 1);\n }\n\n /// Iterates over the entire array, calling the callback with all values and their array index. The order in which\n /// values are processed is arbitrary.\n ///\n /// It is safe to delete the current element (and only the current element) from inside the callback via `remove`:\n /// ```noir\n /// array.for_each(|index, value| {\n /// if some_condition(value) {\n /// array.remove(index); // safe only for this index\n /// }\n /// }\n /// ```\n ///\n /// If all elements in the array need to iterated over and then removed, then using `for_each` results in optimal\n /// efficiency.\n ///\n /// It is **not** safe to push new elements into the array from inside the callback.\n pub unconstrained fn for_each(self, f: unconstrained fn[Env](u32, T) -> ())\n where\n T: Deserialize,\n {\n // Iterating over all elements is simple, but we want to do it in such a way that a) deleting the current\n // element is safe to do, and b) deleting *all* elements is optimally efficient. This is because CapsuleArrays\n // are typically used to hold pending tasks, so iterating them while clearing completed tasks (sometimes\n // unconditionally, resulting in a full clear) is a very common access pattern.\n //\n // The way we achieve this is by iterating backwards: each element can always be deleted since it won't change\n // any preceding (lower) indices, and if every element is deleted then every element will (in turn) be the last\n // element. This results in an optimal full clear since `remove` will be able to skip the `capsules::copy` call\n // to shift any elements past the deleted one (because there will be none).\n let mut i = self.len();\n while i > 0 {\n i -= 1;\n f(i, self.get(i));\n }\n }\n\n unconstrained fn slot_at(self, index: u32) -> Field {\n // Elements are stored immediately after the base slot, so we add 1 to it to compute the slot for the first\n // element.\n self.base_slot + 1 + index as Field\n }\n}\n\nmod test {\n use crate::test::helpers::test_environment::TestEnvironment;\n use super::CapsuleArray;\n use protocol_types::address::AztecAddress;\n\n global SLOT: Field = 1230;\n\n unconstrained fn setup() -> AztecAddress {\n TestEnvironment::new().utility().this_address()\n }\n\n #[test]\n unconstrained fn empty_array() {\n let contract_address = setup();\n\n let array: CapsuleArray = CapsuleArray::at(contract_address, SLOT);\n assert_eq(array.len(), 0);\n }\n\n #[test(should_fail_with = \"Attempted to read past the length of a CapsuleArray\")]\n unconstrained fn empty_array_read() {\n let contract_address = setup();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n let _: Field = array.get(0);\n }\n\n #[test]\n unconstrained fn array_push() {\n let contract_address = setup();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n array.push(5);\n\n assert_eq(array.len(), 1);\n assert_eq(array.get(0), 5);\n }\n\n #[test(should_fail_with = \"Attempted to read past the length of a CapsuleArray\")]\n unconstrained fn read_past_len() {\n let contract_address = setup();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n array.push(5);\n\n let _ = array.get(1);\n }\n\n #[test]\n unconstrained fn array_remove_last() {\n let contract_address = setup();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(5);\n array.remove(0);\n\n assert_eq(array.len(), 0);\n }\n\n #[test]\n unconstrained fn array_remove_some() {\n let contract_address = setup();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(7);\n array.push(8);\n array.push(9);\n\n assert_eq(array.len(), 3);\n assert_eq(array.get(0), 7);\n assert_eq(array.get(1), 8);\n assert_eq(array.get(2), 9);\n\n array.remove(1);\n\n assert_eq(array.len(), 2);\n assert_eq(array.get(0), 7);\n assert_eq(array.get(1), 9);\n }\n\n #[test]\n unconstrained fn array_remove_all() {\n let contract_address = setup();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(7);\n array.push(8);\n array.push(9);\n\n array.remove(1);\n array.remove(1);\n array.remove(0);\n\n assert_eq(array.len(), 0);\n }\n\n #[test]\n unconstrained fn for_each_called_with_all_elements() {\n let contract_address = setup();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n // We store all values that we were called with and check that all (value, index) tuples are present. Note that\n // we do not care about the order in which each tuple was passed to the closure.\n let called_with = &mut BoundedVec::<(u32, Field), 3>::new();\n array.for_each(|index, value| { called_with.push((index, value)); });\n\n assert_eq(called_with.len(), 3);\n assert(called_with.any(|(index, value)| (index == 0) & (value == 4)));\n assert(called_with.any(|(index, value)| (index == 1) & (value == 5)));\n assert(called_with.any(|(index, value)| (index == 2) & (value == 6)));\n }\n\n #[test]\n unconstrained fn for_each_remove_some() {\n let contract_address = setup();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n array.for_each(|index, _| {\n if index == 1 {\n array.remove(index);\n }\n });\n\n assert_eq(array.len(), 2);\n assert_eq(array.get(0), 4);\n assert_eq(array.get(1), 6);\n }\n\n #[test]\n unconstrained fn for_each_remove_all() {\n let contract_address = setup();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n array.for_each(|index, _| { array.remove(index); });\n\n assert_eq(array.len(), 0);\n }\n\n // TODO: uncomment this test once OracleMock::count is implemented in the stdlib.\n // #[test]\n // unconstrained fn for_each_remove_all_no_copy() {\n // let contract_address = setup();\n // let array = CapsuleArray::at(contract_address, SLOT);\n\n // array.push(4);\n // array.push(5);\n // array.push(6);\n\n // // We test that the copyCapsule was never called, which is the expensive operation we want to avoid.\n // let mock = OracleMock::mock(\"copyCapsule\");\n\n // array.for_each(|index, _| {\n // array.remove(index);\n // });\n\n // assert_eq(mock.count(), 0);\n // }\n}\n" - }, - "52": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr", - "source": "use dep::protocol_types::{\n abis::function_selector::FunctionSelector,\n address::AztecAddress,\n traits::{Deserialize, ToField},\n};\n\nuse crate::context::{gas::GasOpts, private_context::PrivateContext, public_context::PublicContext};\n\nuse crate::hash::{hash_args, hash_calldata};\nuse crate::oracle::execution_cache;\n\npub trait CallInterface {\n fn get_args(self) -> [Field];\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\n// PrivateCallInterface\n\npub struct PrivateCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n return_type: T,\n is_static: bool,\n}\n\nimpl PrivateCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n is_static: bool,\n ) -> Self {\n let args_hash = hash_args(args);\n Self {\n target_contract,\n selector,\n name,\n args_hash,\n args,\n return_type: std::mem::zeroed(),\n is_static,\n }\n }\n\n pub fn call(self, context: &mut PrivateContext) -> T\n where\n T: Deserialize,\n {\n execution_cache::store(self.args, self.args_hash);\n let returns_hash = context.call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n false,\n );\n let returns: T = returns_hash.get_preimage();\n returns\n }\n\n pub fn view(self, context: &mut PrivateContext) -> T\n where\n T: Deserialize,\n {\n execution_cache::store(self.args, self.args_hash);\n let returns_hash = context.call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n true,\n );\n returns_hash.get_preimage()\n }\n}\n\nimpl CallInterface for PrivateCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// PrivateVoidCallInterface\n\npub struct PrivateVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n return_type: (), // Unit type () indicates this interface is for functions that return nothing (void)\n is_static: bool,\n}\n\nimpl PrivateVoidCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n is_static: bool,\n ) -> Self {\n let args_hash = hash_args(args);\n Self { target_contract, selector, name, args_hash, args, return_type: (), is_static }\n }\n\n pub fn call(self, context: &mut PrivateContext) {\n execution_cache::store(self.args, self.args_hash);\n context\n .call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n false,\n )\n .assert_empty();\n }\n\n pub fn view(self, context: &mut PrivateContext) {\n execution_cache::store(self.args, self.args_hash);\n context\n .call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n true,\n )\n .assert_empty();\n }\n}\n\nimpl CallInterface for PrivateVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// PrivateStaticCallInterface\n\npub struct PrivateStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n return_type: T,\n is_static: bool,\n}\n\nimpl PrivateStaticCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n ) -> Self {\n let args_hash = hash_args(args);\n Self {\n target_contract,\n selector,\n name,\n args_hash,\n args,\n return_type: std::mem::zeroed(),\n is_static: true,\n }\n }\n\n pub fn view(self, context: &mut PrivateContext) -> T\n where\n T: Deserialize,\n {\n execution_cache::store(self.args, self.args_hash);\n let returns = context.call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n true,\n );\n returns.get_preimage()\n }\n}\n\nimpl CallInterface for PrivateStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// PrivateStaticVoidCallInterface\n\npub struct PrivateStaticVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n return_type: (), // Unit type () indicates this interface is for functions that return nothing (void)\n is_static: bool,\n}\n\nimpl PrivateStaticVoidCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n ) -> Self {\n let args_hash = hash_args(args);\n Self { target_contract, selector, name, args_hash, args, return_type: (), is_static: true }\n }\n\n pub fn view(self, context: &mut PrivateContext) {\n execution_cache::store(self.args, self.args_hash);\n context\n .call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n true,\n )\n .assert_empty();\n }\n}\n\nimpl CallInterface for PrivateStaticVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// PublicCallInterface\n\npub struct PublicCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n return_type: T,\n is_static: bool,\n}\n\nimpl PublicCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n is_static: bool,\n ) -> Self {\n Self {\n target_contract,\n selector,\n name,\n args,\n gas_opts: GasOpts::default(),\n return_type: std::mem::zeroed(),\n is_static,\n }\n }\n\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 unconstrained fn call(self, context: &mut PublicContext) -> T\n where\n T: Deserialize,\n {\n let returns = context.call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n Deserialize::deserialize(returns.as_array::())\n }\n\n pub unconstrained fn view(self, context: &mut PublicContext) -> T\n where\n T: Deserialize,\n {\n let returns = context.static_call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n Deserialize::deserialize(returns.as_array::())\n }\n\n pub fn enqueue(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n false,\n )\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n true,\n )\n }\n}\n\nimpl CallInterface for PublicCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// PublicVoidCallInterface\n\npub struct PublicVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n return_type: (), // Unit type () indicates this interface is for functions that return nothing (void)\n is_static: bool,\n gas_opts: GasOpts,\n}\n\nimpl PublicVoidCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n is_static: bool,\n ) -> Self {\n Self {\n target_contract,\n selector,\n name,\n args,\n return_type: (),\n is_static,\n gas_opts: GasOpts::default(),\n }\n }\n\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 unconstrained fn call(self, context: &mut PublicContext) {\n let returns = context.call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n assert(returns.len() == 0);\n }\n\n pub unconstrained fn view(self, context: &mut PublicContext) {\n let returns = context.static_call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n assert(returns.len() == 0);\n }\n\n pub fn enqueue(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n false,\n )\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n true,\n )\n }\n\n pub fn set_as_teardown(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.set_public_teardown_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n false,\n )\n }\n}\n\nimpl CallInterface for PublicVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// PublicStaticCallInterface\n\npub struct PublicStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n return_type: T,\n is_static: bool,\n gas_opts: GasOpts,\n}\n\nimpl PublicStaticCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n ) -> Self {\n Self {\n target_contract,\n selector,\n name,\n args,\n return_type: std::mem::zeroed(),\n is_static: true,\n gas_opts: GasOpts::default(),\n }\n }\n\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 unconstrained fn view(self, context: &mut PublicContext) -> T\n where\n T: Deserialize,\n {\n let returns = context.static_call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n Deserialize::deserialize(returns.as_array::())\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n true,\n )\n }\n}\n\nimpl CallInterface for PublicStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// PublicStaticVoidCallInterface\n\npub struct PublicStaticVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n return_type: (), // Unit type () indicates this interface is for functions that return nothing (void)\n is_static: bool,\n gas_opts: GasOpts,\n}\n\nimpl PublicStaticVoidCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n ) -> Self {\n Self {\n target_contract,\n selector,\n name,\n args,\n return_type: (),\n is_static: true,\n gas_opts: GasOpts::default(),\n }\n }\n\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 unconstrained fn view(self, context: &mut PublicContext) {\n let returns = context.static_call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n assert(returns.len() == 0);\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n true,\n )\n }\n}\n\nimpl CallInterface for PublicStaticVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// UtilityCallInterface\n\npub struct UtilityCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n return_type: T,\n}\n\nimpl UtilityCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n ) -> Self {\n let args_hash = hash_args(args);\n Self { target_contract, selector, name, args_hash, args, return_type: std::mem::zeroed() }\n }\n\n pub fn get_args(self) -> [Field] {\n self.args\n }\n\n pub fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n pub fn get_name(self) -> str {\n self.name\n }\n\n pub fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n}\n\n// UtilityVoidCallInterface\n\npub struct UtilityVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n return_type: (),\n}\n\nimpl UtilityVoidCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n ) -> Self {\n let args_hash = hash_args(args);\n Self { target_contract, selector, name, args_hash, args, return_type: () }\n }\n\n pub fn get_args(self) -> [Field] {\n self.args\n }\n\n pub fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n pub fn get_name(self) -> str {\n self.name\n }\n\n pub fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n}\n" - }, - "59": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/context/private_context.nr", - "source": "use crate::{\n context::{inputs::PrivateContextInputs, returns_hash::ReturnsHash},\n hash::{ArgsHasher, hash_args_array, hash_calldata_array},\n keys::constants::{NULLIFIER_INDEX, NUM_KEY_TYPES, OUTGOING_INDEX, sk_generators},\n messaging::process_l1_to_l2_message,\n oracle::{\n block_header::get_block_header_at,\n call_private_function::call_private_function_internal,\n enqueue_public_function_call::{\n notify_enqueued_public_function_call, notify_set_min_revertible_side_effect_counter,\n notify_set_public_teardown_function_call,\n },\n execution_cache,\n key_validation_request::get_key_validation_request,\n notes::{notify_created_nullifier, notify_nullified_note},\n },\n};\nuse dep::protocol_types::{\n abis::{\n call_context::CallContext,\n function_selector::FunctionSelector,\n gas_settings::GasSettings,\n log_hash::LogHash,\n max_block_number::MaxBlockNumber,\n note_hash::NoteHash,\n nullifier::Nullifier,\n private_call_request::PrivateCallRequest,\n private_circuit_public_inputs::PrivateCircuitPublicInputs,\n private_log::{PrivateLog, PrivateLogData},\n public_call_request::PublicCallRequest,\n read_request::ReadRequest,\n side_effect::Counted,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n },\n address::{AztecAddress, EthAddress},\n block_header::BlockHeader,\n constants::{\n MAX_CONTRACT_CLASS_LOGS_PER_CALL, MAX_ENQUEUED_CALLS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASHES_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PRIVATE_LOGS_PER_CALL,\n PRIVATE_LOG_SIZE_IN_FIELDS,\n },\n messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Empty, Hash, ToField},\n utils::arrays::array_concat,\n};\n\n// When finished, one can call .finish() to convert back to the abi\npub struct PrivateContext {\n // docs:start:private-context\n pub inputs: PrivateContextInputs,\n pub side_effect_counter: u32,\n\n pub min_revertible_side_effect_counter: u32,\n pub is_fee_payer: bool,\n\n pub args_hash: Field,\n pub return_hash: Field,\n\n pub max_block_number: MaxBlockNumber,\n\n pub note_hash_read_requests: BoundedVec,\n pub nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n pub note_hashes: BoundedVec,\n pub nullifiers: BoundedVec,\n\n pub private_call_requests: BoundedVec,\n pub public_call_requests: BoundedVec, MAX_ENQUEUED_CALLS_PER_CALL>,\n pub public_teardown_call_request: PublicCallRequest,\n pub 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 pub historical_header: BlockHeader,\n\n pub private_logs: BoundedVec,\n pub contract_class_logs_hashes: BoundedVec, MAX_CONTRACT_CLASS_LOGS_PER_CALL>,\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 pub 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 note_hashes: BoundedVec::new(),\n nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_requests: BoundedVec::new(),\n public_teardown_call_request: PublicCallRequest::empty(),\n l2_to_l1_msgs: BoundedVec::new(),\n private_logs: BoundedVec::new(),\n contract_class_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES],\n }\n }\n\n pub fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n pub fn this_address(self) -> AztecAddress {\n self.inputs.call_context.contract_address\n }\n\n pub fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n pub fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n pub fn gas_settings(self) -> GasSettings {\n self.inputs.tx_context.gas_settings\n }\n\n pub fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n pub fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n pub fn push_note_hash(&mut self, note_hash: Field) {\n self.note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n pub fn push_nullifier(&mut self, nullifier: Field) {\n notify_created_nullifier(nullifier);\n self.nullifiers.push(\n Nullifier { value: nullifier, note_hash: 0, counter: self.next_counter() },\n );\n }\n\n pub fn push_nullifier_for_note_hash(&mut self, nullifier: Field, nullified_note_hash: Field) {\n let nullifier_counter = self.next_counter();\n notify_nullified_note(nullifier, nullified_note_hash, nullifier_counter);\n self.nullifiers.push(\n Nullifier {\n value: nullifier,\n note_hash: nullified_note_hash,\n counter: nullifier_counter,\n },\n );\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 pub fn get_block_header(self) -> BlockHeader {\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_block_header_at(self, block_number: u32) -> BlockHeader {\n get_block_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n self.return_hash = returns_hasher.hash();\n execution_cache::store(returns_hasher.fields, self.return_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\n .key_validation_requests_and_generators\n .storage(),\n note_hashes: self.note_hashes.storage(),\n nullifiers: self.nullifiers.storage(),\n private_call_requests: self.private_call_requests.storage(),\n public_call_requests: self.public_call_requests.storage(),\n public_teardown_call_request: self.public_teardown_call_request,\n l2_to_l1_msgs: self.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 private_logs: self.private_logs.storage(),\n contract_class_logs_hashes: self.contract_class_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(\n \"Setting {0} as fee payer\",\n [self.this_address().to_field()],\n );\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 notify_set_min_revertible_side_effect_counter(self.min_revertible_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 =\n 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 as u32].unwrap_or(\n KeyValidationRequest::empty(),\n );\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\n // Typically we'd validate keys by showing that they are the preimage of `pk_m_hash`, but that'd require\n // the oracle returning the master secret keys, which could cause malicious contracts to leak it or learn\n // about secrets from other contracts. We therefore silo secret keys, and rely on the private kernel to\n // validate that we siloed secret key corresponds to correct siloing of the master secret key that hashes\n // to `pk_m_hash`.\n\n // Safety: Kernels verify that the key validation request is valid and below we verify that a request\n // for the correct public key has been received.\n let request = unsafe { get_key_validation_request(pk_m_hash, key_index) };\n assert_eq(request.pk_m.hash(), pk_m_hash, \"Obtained invalid key validation request\");\n\n self.key_validation_requests_and_generators.push(\n KeyValidationRequestAndGenerator {\n request,\n sk_app_generator: sk_generators[key_index as u32],\n },\n );\n self.last_key_validation_requests[key_index as u32] = 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.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(\n &mut self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field,\n ) {\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 leaf_index,\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_nullifier(nullifier)\n }\n // docs:end:consume_l1_to_l2_message\n\n pub fn emit_private_log(&mut self, log: [Field; PRIVATE_LOG_SIZE_IN_FIELDS], length: u32) {\n let counter = self.next_counter();\n let private_log =\n PrivateLogData { log: PrivateLog::new(log, length), note_hash_counter: 0, counter };\n self.private_logs.push(private_log);\n }\n\n pub fn emit_raw_note_log(\n &mut self,\n log: [Field; PRIVATE_LOG_SIZE_IN_FIELDS],\n length: u32,\n note_hash_counter: u32,\n ) {\n let counter = self.next_counter();\n let private_log =\n PrivateLogData { log: PrivateLog::new(log, length), note_hash_counter, counter };\n self.private_logs.push(private_log);\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 ) -> ReturnsHash {\n let args_hash = hash_args_array(args);\n execution_cache::store(args, args_hash);\n self.call_private_function_with_args_hash(\n contract_address,\n function_selector,\n args_hash,\n false,\n )\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 ) -> ReturnsHash {\n let args_hash = hash_args_array(args);\n execution_cache::store(args, args_hash);\n self.call_private_function_with_args_hash(\n contract_address,\n function_selector,\n args_hash,\n true,\n )\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n ) -> ReturnsHash {\n self.call_private_function_with_args_hash(contract_address, function_selector, 0, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n ) -> ReturnsHash {\n self.call_private_function_with_args_hash(contract_address, function_selector, 0, true)\n }\n\n pub fn call_private_function_with_args_hash(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n ) -> ReturnsHash {\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\n // Safety: The oracle simulates the private call and returns the value of the side effects counter after\n // execution of the call (which means that end_side_effect_counter - start_side_effect_counter is\n // the number of side effects that took place), along with the hash of the return values. We validate these\n // by requesting a private kernel iteration in which the return values are constrained to hash\n // to `returns_hash` and the side effects counter to increment from start to end.\n let (end_side_effect_counter, returns_hash) = unsafe {\n call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n )\n };\n\n self.private_call_requests.push(\n PrivateCallRequest {\n call_context: CallContext {\n msg_sender: self.this_address(),\n contract_address,\n function_selector,\n is_static_call,\n },\n args_hash,\n returns_hash,\n start_side_effect_counter,\n end_side_effect_counter,\n },\n );\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 // 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 self.side_effect_counter = end_side_effect_counter + 1;\n ReturnsHash::new(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 calldata = array_concat([function_selector.to_field()], args);\n let calldata_hash = hash_calldata_array(calldata);\n execution_cache::store(calldata, calldata_hash);\n self.call_public_function_with_calldata_hash(contract_address, calldata_hash, 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 calldata = array_concat([function_selector.to_field()], args);\n let calldata_hash = hash_calldata_array(calldata);\n execution_cache::store(calldata, calldata_hash);\n self.call_public_function_with_calldata_hash(contract_address, calldata_hash, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n ) {\n let calldata_hash = hash_calldata_array([function_selector.to_field()]);\n self.call_public_function_with_calldata_hash(contract_address, calldata_hash, 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 let calldata_hash = hash_calldata_array([function_selector.to_field()]);\n self.call_public_function_with_calldata_hash(contract_address, calldata_hash, true)\n }\n\n pub fn call_public_function_with_calldata_hash(\n &mut self,\n contract_address: AztecAddress,\n calldata_hash: Field,\n is_static_call: bool,\n ) {\n let counter = self.next_counter();\n\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n\n notify_enqueued_public_function_call(\n contract_address,\n calldata_hash,\n counter,\n is_static_call,\n );\n\n let call_request = PublicCallRequest {\n msg_sender: self.this_address(),\n contract_address,\n is_static_call,\n calldata_hash,\n };\n\n self.public_call_requests.push(Counted::new(call_request, counter));\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 calldata = array_concat([function_selector.to_field()], args);\n let calldata_hash = hash_calldata_array(calldata);\n execution_cache::store(calldata, calldata_hash);\n self.set_public_teardown_function_with_calldata_hash(contract_address, calldata_hash, false)\n }\n\n pub fn set_public_teardown_function_with_calldata_hash(\n &mut self,\n contract_address: AztecAddress,\n calldata_hash: Field,\n is_static_call: bool,\n ) {\n let counter = self.next_counter();\n\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n\n notify_set_public_teardown_function_call(\n contract_address,\n calldata_hash,\n counter,\n is_static_call,\n );\n\n self.public_teardown_call_request = PublicCallRequest {\n msg_sender: self.this_address(),\n contract_address,\n is_static_call,\n calldata_hash,\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 note_hashes: BoundedVec::new(),\n nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_requests: BoundedVec::new(),\n public_teardown_call_request: PublicCallRequest::empty(),\n l2_to_l1_msgs: BoundedVec::new(),\n historical_header: BlockHeader::empty(),\n private_logs: BoundedVec::new(),\n contract_class_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES],\n }\n }\n}\n" - }, - "6": { - "path": "std/collections/bounded_vec.nr", - "source": "use crate::{cmp::Eq, convert::From, runtime::is_unconstrained, static_assert};\n\n/// A `BoundedVec` is a growable storage similar to a `Vec` except that it\n/// is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented\n/// via slices and thus is not subject to the same restrictions slices are (notably, nested\n/// slices - and thus nested vectors as well - are disallowed).\n///\n/// Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by\n/// pushing an additional element is also more efficient - the length only needs to be increased\n/// by one.\n///\n/// For these reasons `BoundedVec` should generally be preferred over `Vec` when there\n/// is a reasonable maximum bound that can be placed on the vector.\n///\n/// Example:\n///\n/// ```noir\n/// let mut vector: BoundedVec = BoundedVec::new();\n/// for i in 0..5 {\n/// vector.push(i);\n/// }\n/// assert(vector.len() == 5);\n/// assert(vector.max_len() == 10);\n/// ```\npub struct BoundedVec {\n storage: [T; MaxLen],\n len: u32,\n}\n\nimpl BoundedVec {\n /// Creates a new, empty vector of length zero.\n ///\n /// Since this container is backed by an array internally, it still needs an initial value\n /// to give each element. To resolve this, each element is zeroed internally. This value\n /// is guaranteed to be inaccessible unless `get_unchecked` is used.\n ///\n /// Example:\n ///\n /// ```noir\n /// let empty_vector: BoundedVec = BoundedVec::new();\n /// assert(empty_vector.len() == 0);\n /// ```\n ///\n /// Note that whenever calling `new` the maximum length of the vector should always be specified\n /// via a type signature:\n ///\n /// ```noir\n /// fn good() -> BoundedVec {\n /// // Ok! MaxLen is specified with a type annotation\n /// let v1: BoundedVec = BoundedVec::new();\n /// let v2 = BoundedVec::new();\n ///\n /// // Ok! MaxLen is known from the type of `good`'s return value\n /// v2\n /// }\n ///\n /// fn bad() {\n /// // Error: Type annotation needed\n /// // The compiler can't infer `MaxLen` from the following code:\n /// let mut v3 = BoundedVec::new();\n /// v3.push(5);\n /// }\n /// ```\n ///\n /// This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions\n /// but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a\n /// constraint failure at runtime when the vec is pushed to.\n pub fn new() -> Self {\n let zeroed = crate::mem::zeroed();\n BoundedVec { storage: [zeroed; MaxLen], len: 0 }\n }\n\n /// Retrieves an element from the vector at the given index, starting from zero.\n ///\n /// If the given index is equal to or greater than the length of the vector, this\n /// will issue a constraint failure.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn foo(v: BoundedVec) {\n /// let first = v.get(0);\n /// let last = v.get(v.len() - 1);\n /// assert(first != last);\n /// }\n /// ```\n pub fn get(self, index: u32) -> T {\n assert(index < self.len, \"Attempted to read past end of BoundedVec\");\n self.get_unchecked(index)\n }\n\n /// Retrieves an element from the vector at the given index, starting from zero, without\n /// performing a bounds check.\n ///\n /// Since this function does not perform a bounds check on length before accessing the element,\n /// it is unsafe! Use at your own risk!\n ///\n /// Example:\n ///\n /// ```noir\n /// fn sum_of_first_three(v: BoundedVec) -> u32 {\n /// // Always ensure the length is larger than the largest\n /// // index passed to get_unchecked\n /// assert(v.len() > 2);\n /// let first = v.get_unchecked(0);\n /// let second = v.get_unchecked(1);\n /// let third = v.get_unchecked(2);\n /// first + second + third\n /// }\n /// ```\n pub fn get_unchecked(self, index: u32) -> T {\n self.storage[index]\n }\n\n /// Writes an element to the vector at the given index, starting from zero.\n ///\n /// If the given index is equal to or greater than the length of the vector, this will issue a constraint failure.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn foo(v: BoundedVec) {\n /// let first = v.get(0);\n /// assert(first != 42);\n /// v.set(0, 42);\n /// let new_first = v.get(0);\n /// assert(new_first == 42);\n /// }\n /// ```\n pub fn set(&mut self, index: u32, value: T) {\n assert(index < self.len, \"Attempted to write past end of BoundedVec\");\n self.set_unchecked(index, value)\n }\n\n /// Writes an element to the vector at the given index, starting from zero, without performing a bounds check.\n ///\n /// Since this function does not perform a bounds check on length before accessing the element, it is unsafe! Use at your own risk!\n ///\n /// Example:\n ///\n /// ```noir\n /// fn set_unchecked_example() {\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_array([1, 2]);\n ///\n /// // Here we're safely writing within the valid range of `vec`\n /// // `vec` now has the value [42, 2]\n /// vec.set_unchecked(0, 42);\n ///\n /// // We can then safely read this value back out of `vec`.\n /// // Notice that we use the checked version of `get` which would prevent reading unsafe values.\n /// assert_eq(vec.get(0), 42);\n ///\n /// // We've now written past the end of `vec`.\n /// // As this index is still within the maximum potential length of `v`,\n /// // it won't cause a constraint failure.\n /// vec.set_unchecked(2, 42);\n /// println(vec);\n ///\n /// // This will write past the end of the maximum potential length of `vec`,\n /// // it will then trigger a constraint failure.\n /// vec.set_unchecked(5, 42);\n /// println(vec);\n /// }\n /// ```\n pub fn set_unchecked(&mut self, index: u32, value: T) {\n self.storage[index] = value;\n }\n\n /// Pushes an element to the end of the vector. This increases the length\n /// of the vector by one.\n ///\n /// Panics if the new length of the vector will be greater than the max length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// v.push(1);\n /// v.push(2);\n ///\n /// // Panics with failed assertion \"push out of bounds\"\n /// v.push(3);\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 /// Returns the current length of this vector\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// assert(v.len() == 0);\n ///\n /// v.push(100);\n /// assert(v.len() == 1);\n ///\n /// v.push(200);\n /// v.push(300);\n /// v.push(400);\n /// assert(v.len() == 4);\n ///\n /// let _ = v.pop();\n /// let _ = v.pop();\n /// assert(v.len() == 2);\n /// ```\n pub fn len(self) -> u32 {\n self.len\n }\n\n /// Returns the maximum length of this vector. This is always\n /// equal to the `MaxLen` parameter this vector was initialized with.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// assert(v.max_len() == 5);\n /// v.push(10);\n /// assert(v.max_len() == 5);\n /// ```\n pub fn max_len(_self: BoundedVec) -> u32 {\n MaxLen\n }\n\n /// Returns the internal array within this vector.\n ///\n /// Since arrays in Noir are immutable, mutating the returned storage array will not mutate\n /// the storage held internally by this vector.\n ///\n /// Note that uninitialized elements may be zeroed out!\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// assert(v.storage() == [0, 0, 0, 0, 0]);\n ///\n /// v.push(57);\n /// assert(v.storage() == [57, 0, 0, 0, 0]);\n /// ```\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n /// Pushes each element from the given array to this vector.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_array([2, 4]);\n ///\n /// assert(vec.len == 2);\n /// assert(vec.get(0) == 2);\n /// assert(vec.get(1) == 4);\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 /// Pushes each element from the given slice to this vector.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_slice(&[2, 4]);\n ///\n /// assert(vec.len == 2);\n /// assert(vec.get(0) == 2);\n /// assert(vec.get(1) == 4);\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 /// Pushes each element from the other vector to this vector. The length of\n /// the other vector is left unchanged.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// ```noir\n /// let mut v1: BoundedVec = BoundedVec::new();\n /// let mut v2: BoundedVec = BoundedVec::new();\n ///\n /// v2.extend_from_array([1, 2, 3]);\n /// v1.extend_from_bounded_vec(v2);\n ///\n /// assert(v1.storage() == [1, 2, 3, 0, 0]);\n /// assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]);\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 if is_unconstrained() {\n for i in 0..append_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n } else {\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 }\n self.len = new_len;\n }\n\n /// Creates a new vector, populating it with values derived from an array input.\n /// The maximum length of the vector is determined based on the type signature.\n ///\n /// Example:\n ///\n /// ```noir\n /// let bounded_vec: BoundedVec = BoundedVec::from_array([1, 2, 3])\n /// ```\n pub fn from_array(array: [T; Len]) -> Self {\n static_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 /// Pops the element at the end of the vector. This will decrease the length\n /// of the vector by one.\n ///\n /// Panics if the vector is empty.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// v.push(1);\n /// v.push(2);\n ///\n /// let two = v.pop();\n /// let one = v.pop();\n ///\n /// assert(two == 2);\n /// assert(one == 1);\n ///\n /// // error: cannot pop from an empty vector\n /// let _ = v.pop();\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::mem::zeroed();\n elem\n }\n\n /// Returns true if the given predicate returns true for any element\n /// in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// v.extend_from_array([2, 4, 6]);\n ///\n /// let all_even = !v.any(|elem: u32| elem % 2 != 0);\n /// assert(all_even);\n /// ```\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n if is_unconstrained() {\n for i in 0..self.len {\n ret |= predicate(self.storage[i]);\n }\n } else {\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 }\n ret\n }\n\n /// Creates a new vector of equal size by calling a closure on each element in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let result = vec.map(|value| value * 2);\n ///\n /// let expected = BoundedVec::from_array([2, 4, 6, 8]);\n /// assert_eq(result, expected);\n /// ```\n pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec {\n let mut ret = BoundedVec::new();\n ret.len = self.len();\n\n if is_unconstrained() {\n for i in 0..self.len() {\n ret.storage[i] = f(self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n ret.storage[i] = f(self.get_unchecked(i));\n }\n }\n }\n\n ret\n }\n\n /// Creates a new vector of equal size by calling a closure on each element\n /// in this vector, along with its index.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let result = vec.mapi(|i, value| i + value * 2);\n ///\n /// let expected = BoundedVec::from_array([2, 5, 8, 11]);\n /// assert_eq(result, expected);\n /// ```\n pub fn mapi(self, f: fn[Env](u32, T) -> U) -> BoundedVec {\n let mut ret = BoundedVec::new();\n ret.len = self.len();\n\n if is_unconstrained() {\n for i in 0..self.len() {\n ret.storage[i] = f(i, self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n ret.storage[i] = f(i, self.get_unchecked(i));\n }\n }\n }\n\n ret\n }\n\n /// Calls a closure on each element in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let mut result = BoundedVec::::new();\n /// vec.for_each(|value| result.push(value * 2));\n ///\n /// let expected = BoundedVec::from_array([2, 4, 6, 8]);\n /// assert_eq(result, expected);\n /// ```\n pub fn for_each(self, f: fn[Env](T) -> ()) {\n if is_unconstrained() {\n for i in 0..self.len() {\n f(self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n f(self.get_unchecked(i));\n }\n }\n }\n }\n\n /// Calls a closure on each element in this vector, along with its index.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let mut result = BoundedVec::::new();\n /// vec.for_eachi(|i, value| result.push(i + value * 2));\n ///\n /// let expected = BoundedVec::from_array([2, 5, 8, 11]);\n /// assert_eq(result, expected);\n /// ```\n pub fn for_eachi(self, f: fn[Env](u32, T) -> ()) {\n if is_unconstrained() {\n for i in 0..self.len() {\n f(i, self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n f(i, self.get_unchecked(i));\n }\n }\n }\n }\n\n /// Creates a new BoundedVec from the given array and length.\n /// The given length must be less than or equal to the length of the array.\n ///\n /// This function will zero out any elements at or past index `len` of `array`.\n /// This incurs an extra runtime cost of O(MaxLen). If you are sure your array is\n /// zeroed after that index, you can use `from_parts_unchecked` to remove the extra loop.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_parts([1, 2, 3, 0], 3);\n /// assert_eq(vec.len(), 3);\n /// ```\n pub fn from_parts(mut array: [T; MaxLen], len: u32) -> Self {\n assert(len <= MaxLen);\n let zeroed = crate::mem::zeroed();\n\n if is_unconstrained() {\n for i in len..MaxLen {\n array[i] = zeroed;\n }\n } else {\n for i in 0..MaxLen {\n if i >= len {\n array[i] = zeroed;\n }\n }\n }\n\n BoundedVec { storage: array, len }\n }\n\n /// Creates a new BoundedVec from the given array and length.\n /// The given length must be less than or equal to the length of the array.\n ///\n /// This function is unsafe because it expects all elements past the `len` index\n /// of `array` to be zeroed, but does not check for this internally. Use `from_parts`\n /// for a safe version of this function which does zero out any indices past the\n /// given length. Invalidating this assumption can notably cause `BoundedVec::eq`\n /// to give incorrect results since it will check even elements past `len`.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 0], 3);\n /// assert_eq(vec.len(), 3);\n ///\n /// // invalid use!\n /// let vec1: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 1], 3);\n /// let vec2: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 2], 3);\n ///\n /// // both vecs have length 3 so we'd expect them to be equal, but this\n /// // fails because elements past the length are still checked in eq\n /// assert_eq(vec1, vec2); // fails\n /// ```\n pub fn from_parts_unchecked(array: [T; MaxLen], len: u32) -> Self {\n assert(len <= MaxLen);\n BoundedVec { storage: array, len }\n }\n}\n\nimpl Eq for BoundedVec\nwhere\n T: Eq,\n{\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 if self.len == other.len {\n self.storage == other.storage\n } else {\n false\n }\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\n mod get {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test(should_fail_with = \"Attempted to read past end of BoundedVec\")]\n fn panics_when_reading_elements_past_end_of_vec() {\n let vec: BoundedVec = BoundedVec::new();\n\n crate::println(vec.get(0));\n }\n }\n\n mod set {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn set_updates_values_properly() {\n let mut vec = BoundedVec::from_array([0, 0, 0, 0, 0]);\n\n vec.set(0, 42);\n assert_eq(vec.storage, [42, 0, 0, 0, 0]);\n\n vec.set(1, 43);\n assert_eq(vec.storage, [42, 43, 0, 0, 0]);\n\n vec.set(2, 44);\n assert_eq(vec.storage, [42, 43, 44, 0, 0]);\n\n vec.set(1, 10);\n assert_eq(vec.storage, [42, 10, 44, 0, 0]);\n\n vec.set(0, 0);\n assert_eq(vec.storage, [0, 10, 44, 0, 0]);\n }\n\n #[test(should_fail_with = \"Attempted to write past end of BoundedVec\")]\n fn panics_when_writing_elements_past_end_of_vec() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.set(0, 42);\n\n // Need to use println to avoid DIE removing the write operation.\n crate::println(vec.get(0));\n }\n }\n\n mod map {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn applies_function_correctly() {\n // docs:start:bounded-vec-map-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|value| value * 2);\n // docs:end:bounded-vec-map-example\n let expected = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|value| (value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = vec.map(|value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n }\n\n mod mapi {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn applies_function_correctly() {\n // docs:start:bounded-vec-mapi-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.mapi(|i, value| i + value * 2);\n // docs:end:bounded-vec-mapi-example\n let expected = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.mapi(|i, value| (i + value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = vec.mapi(|_, value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n }\n\n mod for_each {\n use crate::collections::bounded_vec::BoundedVec;\n\n // map in terms of for_each\n fn for_each_map(\n input: BoundedVec,\n f: fn[Env](T) -> U,\n ) -> BoundedVec {\n let mut output = BoundedVec::::new();\n let output_ref = &mut output;\n input.for_each(|x| output_ref.push(f(x)));\n output\n }\n\n #[test]\n fn smoke_test() {\n let mut acc = 0;\n let acc_ref = &mut acc;\n // docs:start:bounded-vec-for-each-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.for_each(|value| { *acc_ref += value; });\n // docs:end:bounded-vec-for-each-example\n assert_eq(acc, 6);\n }\n\n #[test]\n fn applies_function_correctly() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_each_map(vec, |value| value * 2);\n let expected = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_each_map(vec, |value| (value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = for_each_map(vec, |value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n }\n\n mod for_eachi {\n use crate::collections::bounded_vec::BoundedVec;\n\n // mapi in terms of for_eachi\n fn for_eachi_mapi(\n input: BoundedVec,\n f: fn[Env](u32, T) -> U,\n ) -> BoundedVec {\n let mut output = BoundedVec::::new();\n let output_ref = &mut output;\n input.for_eachi(|i, x| output_ref.push(f(i, x)));\n output\n }\n\n #[test]\n fn smoke_test() {\n let mut acc = 0;\n let acc_ref = &mut acc;\n // docs:start:bounded-vec-for-eachi-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.for_eachi(|i, value| { *acc_ref += i * value; });\n // docs:end:bounded-vec-for-eachi-example\n\n // 0 * 1 + 1 * 2 + 2 * 3\n assert_eq(acc, 8);\n }\n\n #[test]\n fn applies_function_correctly() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_eachi_mapi(vec, |i, value| i + value * 2);\n let expected = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_eachi_mapi(vec, |i, value| (i + value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = for_eachi_mapi(vec, |_, value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\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.get(0), 1);\n assert_eq(bounded_vec.get(1), 2);\n assert_eq(bounded_vec.get(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 use crate::convert::From;\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.get(0), 1);\n assert_eq(bounded_vec.get(1), 2);\n }\n }\n\n mod trait_eq {\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\n mod from_parts {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn from_parts() {\n // docs:start:from-parts\n let vec: BoundedVec = BoundedVec::from_parts([1, 2, 3, 0], 3);\n assert_eq(vec.len(), 3);\n\n // Any elements past the given length are zeroed out, so these\n // two BoundedVecs will be completely equal\n let vec1: BoundedVec = BoundedVec::from_parts([1, 2, 3, 1], 3);\n let vec2: BoundedVec = BoundedVec::from_parts([1, 2, 3, 2], 3);\n assert_eq(vec1, vec2);\n // docs:end:from-parts\n }\n\n #[test]\n fn from_parts_unchecked() {\n // docs:start:from-parts-unchecked\n let vec: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 0], 3);\n assert_eq(vec.len(), 3);\n\n // invalid use!\n let vec1: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 1], 3);\n let vec2: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 2], 3);\n\n // both vecs have length 3 so we'd expect them to be equal, but this\n // fails because elements past the length are still checked in eq\n assert(vec1 != vec2);\n // docs:end:from-parts-unchecked\n }\n }\n}\n" - }, - "60": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/context/public_context.nr", - "source": "use crate::context::gas::GasOpts;\nuse crate::hash::{\n compute_l1_to_l2_message_hash, compute_l1_to_l2_message_nullifier, compute_secret_hash,\n};\nuse dep::protocol_types::abis::function_selector::FunctionSelector;\nuse dep::protocol_types::address::{AztecAddress, EthAddress};\nuse dep::protocol_types::constants::MAX_FIELD_VALUE;\nuse dep::protocol_types::traits::{Empty, FromField, Packable, Serialize, ToField};\n\npub struct PublicContext {\n pub args_hash: Option,\n pub compute_args_hash: fn() -> Field,\n}\n\nimpl PublicContext {\n pub fn new(compute_args_hash: fn() -> Field) -> Self {\n PublicContext { args_hash: Option::none(), compute_args_hash }\n }\n\n pub fn emit_public_log(_self: &mut Self, log: T)\n where\n T: Serialize,\n {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { emit_public_log(Serialize::serialize(log).as_slice()) };\n }\n\n pub fn note_hash_exists(_self: Self, note_hash: Field, leaf_index: Field) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { note_hash_exists(note_hash, leaf_index) } == 1\n }\n\n pub fn l1_to_l2_msg_exists(_self: Self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { l1_to_l2_msg_exists(msg_hash, msg_leaf_index) } == 1\n }\n\n pub fn nullifier_exists(_self: Self, unsiloed_nullifier: Field, address: AztecAddress) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { nullifier_exists(unsiloed_nullifier, address.to_field()) } == 1\n }\n\n pub 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_l1_to_l2_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/\n self.this_address(),\n self.version(),\n content,\n secret_hash,\n leaf_index,\n );\n let nullifier = compute_l1_to_l2_message_nullifier(message_hash, secret);\n\n assert(\n !self.nullifier_exists(nullifier, self.this_address()),\n \"L1-to-L2 message is already nullified\",\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index),\n \"Tried to consume nonexistent L1-to-L2 message\",\n );\n\n self.push_nullifier(nullifier);\n }\n\n pub fn message_portal(_self: &mut Self, recipient: EthAddress, content: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { send_l2_to_l1_msg(recipient, content) };\n }\n\n pub unconstrained fn call_public_function(\n _self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = args.push_front(function_selector.to_field());\n\n call(\n gas_opts.l2_gas.unwrap_or(MAX_FIELD_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_FIELD_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = success_copy();\n\n let result_data = returndata_copy(0, returndata_size());\n if !success {\n // Rethrow the revert data.\n avm_revert(result_data);\n }\n result_data\n }\n\n pub unconstrained fn static_call_public_function(\n _self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = args.push_front(function_selector.to_field());\n\n call_static(\n gas_opts.l2_gas.unwrap_or(MAX_FIELD_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_FIELD_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = success_copy();\n\n let result_data = returndata_copy(0, returndata_size());\n if !success {\n // Rethrow the revert data.\n avm_revert(result_data);\n }\n result_data\n }\n\n pub fn push_note_hash(_self: &mut Self, note_hash: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { emit_note_hash(note_hash) };\n }\n pub fn push_nullifier(_self: &mut Self, nullifier: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { emit_nullifier(nullifier) };\n }\n\n pub fn this_address(_self: Self) -> AztecAddress {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n address()\n }\n }\n pub fn msg_sender(_self: Self) -> AztecAddress {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n sender()\n }\n }\n pub fn selector(_self: Self) -> FunctionSelector {\n // The selector is the first element of the calldata when calling a public function through dispatch.\n // Safety: AVM opcodes are constrained by the AVM itself\n let raw_selector: [Field; 1] = unsafe { calldata_copy(0, 1) };\n FunctionSelector::from_field(raw_selector[0])\n }\n pub fn get_args_hash(mut self) -> Field {\n if !self.args_hash.is_some() {\n self.args_hash = Option::some((self.compute_args_hash)());\n }\n\n self.args_hash.unwrap_unchecked()\n }\n pub fn transaction_fee(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n transaction_fee()\n }\n }\n\n pub fn chain_id(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n chain_id()\n }\n }\n pub fn version(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n version()\n }\n }\n pub fn block_number(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n block_number()\n }\n }\n pub fn timestamp(_self: Self) -> u64 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n timestamp()\n }\n }\n pub fn fee_per_l2_gas(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n fee_per_l2_gas()\n }\n }\n pub fn fee_per_da_gas(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n fee_per_da_gas()\n }\n }\n\n pub fn l2_gas_left(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n l2_gas_left()\n }\n }\n pub fn da_gas_left(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n da_gas_left()\n }\n }\n pub fn is_static_call(_self: Self) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { is_static_call() } == 1\n }\n\n pub fn raw_storage_read(_self: Self, storage_slot: Field) -> [Field; N] {\n let mut out = [0; N];\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n out[i] = unsafe { storage_read(storage_slot + i as Field) };\n }\n out\n }\n\n pub fn storage_read(self, storage_slot: Field) -> T\n where\n T: Packable,\n {\n T::unpack(self.raw_storage_read(storage_slot))\n }\n\n pub fn raw_storage_write(_self: Self, storage_slot: Field, values: [Field; N]) {\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { storage_write(storage_slot + i as Field, values[i]) };\n }\n }\n\n pub fn storage_write(self, storage_slot: Field, value: T)\n where\n T: Packable,\n {\n self.raw_storage_write(storage_slot, value.pack());\n }\n}\n\n// Unconstrained opcode wrappers (do not use directly).\nunconstrained fn address() -> AztecAddress {\n address_opcode()\n}\nunconstrained fn sender() -> AztecAddress {\n sender_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 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 l2_gas_left() -> Field {\n l2_gas_left_opcode()\n}\nunconstrained fn da_gas_left() -> Field {\n da_gas_left_opcode()\n}\nunconstrained fn is_static_call() -> Field {\n is_static_call_opcode()\n}\nunconstrained fn note_hash_exists(note_hash: Field, leaf_index: Field) -> u1 {\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) -> u1 {\n nullifier_exists_opcode(nullifier, address)\n}\nunconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\nunconstrained fn emit_public_log(message: [Field]) {\n emit_public_log_opcode(message)\n}\nunconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: Field) -> u1 {\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 l2_gas_allocation: Field,\n da_gas_allocation: Field,\n address: AztecAddress,\n args: [Field],\n) {\n call_opcode(l2_gas_allocation, da_gas_allocation, address, args)\n}\n\nunconstrained fn call_static(\n l2_gas_allocation: Field,\n da_gas_allocation: Field,\n address: AztecAddress,\n args: [Field],\n) {\n call_static_opcode(l2_gas_allocation, da_gas_allocation, address, args)\n}\n\npub unconstrained fn calldata_copy(cdoffset: u32, copy_size: u32) -> [Field; N] {\n calldata_copy_opcode(cdoffset, copy_size)\n}\n\n// `success_copy` is placed immediately after the CALL opcode to get the success value\nunconstrained fn success_copy() -> bool {\n success_copy_opcode()\n}\n\nunconstrained fn returndata_size() -> u32 {\n returndata_size_opcode()\n}\n\nunconstrained fn returndata_copy(rdoffset: u32, copy_size: u32) -> [Field] {\n returndata_copy_opcode(rdoffset, copy_size)\n}\n\npub unconstrained fn avm_return(returndata: [Field]) {\n return_opcode(returndata)\n}\n\n// This opcode reverts using the exact data given. In general it should only be used\n// to do rethrows, where the revert data is the same as the original revert data.\n// For normal reverts, use Noir's `assert` which, on top of reverting, will also add\n// an error selector to the revert data.\nunconstrained fn avm_revert(revertdata: [Field]) {\n revert_opcode(revertdata)\n}\n\nunconstrained fn storage_read(storage_slot: Field) -> Field {\n storage_read_opcode(storage_slot)\n}\n\nunconstrained fn storage_write(storage_slot: Field, value: Field) {\n storage_write_opcode(storage_slot, value);\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(|| 0)\n }\n}\n\n// AVM oracles (opcodes) follow, do not use directly.\n#[oracle(avmOpcodeAddress)]\nunconstrained fn address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeSender)]\nunconstrained fn sender_opcode() -> AztecAddress {}\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(avmOpcodeFeePerL2Gas)]\nunconstrained fn fee_per_l2_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeFeePerDaGas)]\nunconstrained fn fee_per_da_gas_opcode() -> Field {}\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(avmOpcodeIsStaticCall)]\nunconstrained fn is_static_call_opcode() -> Field {}\n\n#[oracle(avmOpcodeNoteHashExists)]\nunconstrained fn note_hash_exists_opcode(note_hash: Field, leaf_index: Field) -> u1 {}\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) -> u1 {}\n\n#[oracle(avmOpcodeEmitNullifier)]\nunconstrained fn emit_nullifier_opcode(nullifier: Field) {}\n\n// TODO(#11124): rename unencrypted to public in avm\n#[oracle(avmOpcodeEmitUnencryptedLog)]\nunconstrained fn emit_public_log_opcode(message: [Field]) {}\n\n#[oracle(avmOpcodeL1ToL2MsgExists)]\nunconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: Field) -> u1 {}\n\n#[oracle(avmOpcodeSendL2ToL1Msg)]\nunconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(avmOpcodeCalldataCopy)]\nunconstrained fn calldata_copy_opcode(cdoffset: u32, copy_size: u32) -> [Field; N] {}\n\n#[oracle(avmOpcodeReturndataSize)]\nunconstrained fn returndata_size_opcode() -> u32 {}\n\n#[oracle(avmOpcodeReturndataCopy)]\nunconstrained fn returndata_copy_opcode(rdoffset: u32, copy_size: u32) -> [Field] {}\n\n#[oracle(avmOpcodeReturn)]\nunconstrained fn return_opcode(returndata: [Field]) {}\n\n// This opcode reverts using the exact data given. In general it should only be used\n// to do rethrows, where the revert data is the same as the original revert data.\n// For normal reverts, use Noir's `assert` which, on top of reverting, will also add\n// an error selector to the revert data.\n#[oracle(avmOpcodeRevert)]\nunconstrained fn revert_opcode(revertdata: [Field]) {}\n\n#[oracle(avmOpcodeCall)]\nunconstrained fn call_opcode(\n l2_gas_allocation: Field,\n da_gas_allocation: Field,\n address: AztecAddress,\n args: [Field],\n) {}\n\n#[oracle(avmOpcodeStaticCall)]\nunconstrained fn call_static_opcode(\n l2_gas_allocation: Field,\n da_gas_allocation: Field,\n address: AztecAddress,\n args: [Field],\n) {}\n\n#[oracle(avmOpcodeSuccessCopy)]\nunconstrained fn success_copy_opcode() -> bool {}\n\n#[oracle(avmOpcodeStorageRead)]\nunconstrained fn storage_read_opcode(storage_slot: Field) -> Field {}\n\n#[oracle(avmOpcodeStorageWrite)]\nunconstrained fn storage_write_opcode(storage_slot: Field, value: Field) {}\n" - }, - "62": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/context/utility_context.nr", - "source": "use crate::oracle::{\n execution::{get_block_number, get_chain_id, get_contract_address, get_version},\n storage::storage_read,\n};\nuse dep::protocol_types::{address::AztecAddress, traits::Packable};\n\npub struct UtilityContext {\n block_number: u32,\n contract_address: AztecAddress,\n version: Field,\n chain_id: Field,\n}\n\nimpl UtilityContext {\n pub unconstrained 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 a UtilityContext in an environment in which these oracles are not\n // available.\n let block_number = get_block_number();\n let contract_address = get_contract_address();\n let chain_id = get_chain_id();\n let version = get_version();\n Self { block_number, contract_address, version, chain_id }\n }\n\n pub unconstrained fn at(contract_address: AztecAddress) -> Self {\n let block_number = get_block_number();\n let chain_id = get_chain_id();\n let version = get_version();\n Self { block_number, contract_address, version, chain_id }\n }\n\n pub unconstrained fn at_historical(contract_address: AztecAddress, block_number: u32) -> Self {\n let chain_id = get_chain_id();\n let version = get_version();\n Self { block_number, contract_address, version, chain_id }\n }\n\n pub fn block_number(self) -> u32 {\n self.block_number\n }\n\n pub fn this_address(self) -> AztecAddress {\n self.contract_address\n }\n\n pub fn version(self) -> Field {\n self.version\n }\n\n pub fn chain_id(self) -> Field {\n self.chain_id\n }\n\n pub unconstrained fn raw_storage_read(\n self: Self,\n storage_slot: Field,\n ) -> [Field; N] {\n storage_read(self.this_address(), storage_slot, self.block_number())\n }\n\n pub unconstrained fn storage_read(self, storage_slot: Field) -> T\n where\n T: Packable,\n {\n T::unpack(self.raw_storage_read(storage_slot))\n }\n}\n" - }, - "66": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/hash.nr", - "source": "use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__FUNCTION_ARGS, GENERATOR_INDEX__MESSAGE_NULLIFIER,\n GENERATOR_INDEX__PUBLIC_CALLDATA, GENERATOR_INDEX__SECRET_HASH,\n },\n hash::{poseidon2_hash_with_separator, poseidon2_hash_with_separator_slice, sha256_to_field},\n point::Point,\n traits::{Hash, ToField},\n};\n\npub use dep::protocol_types::hash::{compute_siloed_nullifier, pedersen_hash};\n\npub fn pedersen_commitment(inputs: [Field; N], hash_index: u32) -> Point {\n std::hash::pedersen_commitment_with_separator(inputs, hash_index)\n}\n\npub fn compute_secret_hash(secret: Field) -> Field {\n poseidon2_hash_with_separator([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_l1_to_l2_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field,\n leaf_index: Field,\n) -> Field {\n let mut hash_bytes = [0 as u8; 224];\n let sender_bytes: [u8; 32] = sender.to_field().to_be_bytes();\n let chain_id_bytes: [u8; 32] = chain_id.to_be_bytes();\n let recipient_bytes: [u8; 32] = recipient.to_field().to_be_bytes();\n let version_bytes: [u8; 32] = version.to_be_bytes();\n let content_bytes: [u8; 32] = content.to_be_bytes();\n let secret_hash_bytes: [u8; 32] = secret_hash.to_be_bytes();\n let leaf_index_bytes: [u8; 32] = leaf_index.to_be_bytes();\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 hash_bytes[i + 192] = leaf_index_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\npub fn compute_l1_to_l2_message_nullifier(message_hash: Field, secret: Field) -> Field {\n poseidon2_hash_with_separator([message_hash, secret], GENERATOR_INDEX__MESSAGE_NULLIFIER)\n}\n\npub struct ArgsHasher {\n pub 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\n// Computes the hash of input arguments or return values for private functions, or for authwit creation.\npub fn hash_args_array(args: [Field; N]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n poseidon2_hash_with_separator(args, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n// Same as `hash_args_array`, but takes a slice instead of an array.\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n poseidon2_hash_with_separator_slice(args, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n// Computes the hash of calldata for public functions.\npub fn hash_calldata_array(calldata: [Field; N]) -> Field {\n if calldata.len() == 0 {\n 0\n } else {\n poseidon2_hash_with_separator(calldata, GENERATOR_INDEX__PUBLIC_CALLDATA)\n }\n}\n\n// Same as `hash_calldata_array`, but takes a slice instead of an array.\npub fn hash_calldata(calldata: [Field]) -> Field {\n if calldata.len() == 0 {\n 0\n } else {\n poseidon2_hash_with_separator_slice(calldata, GENERATOR_INDEX__PUBLIC_CALLDATA)\n }\n}\n\n#[test]\nunconstrained fn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..100 {\n input.add(i as Field);\n }\n let hash = input.hash();\n dep::std::println(hash);\n assert(hash == 0x19b0d74feb06ebde19edd85a28986c97063e84b3b351a8b666c7cac963ce655f);\n}\n" - }, - "83": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/keys/getters/mod.nr", - "source": "use crate::{\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX},\n oracle::{\n key_validation_request::get_key_validation_request,\n keys::get_public_keys_and_partial_address,\n },\n};\nuse dep::protocol_types::{address::AztecAddress, public_keys::PublicKeys};\n\nmod test;\n\npub unconstrained fn get_nsk_app(npk_m_hash: Field) -> Field {\n get_key_validation_request(npk_m_hash, NULLIFIER_INDEX).sk_app\n}\n\n// A helper function that gets app-siloed outgoing viewing key for a given `ovpk_m_hash`. This function is used\n// in unconstrained contexts only - when computing unconstrained note logs. The safe alternative is `request_ovsk_app`\n// function defined on `PrivateContext`.\npub unconstrained fn get_ovsk_app(ovpk_m_hash: Field) -> Field {\n get_key_validation_request(ovpk_m_hash, OUTGOING_INDEX).sk_app\n}\n\n// Returns all public keys for a given account, applying proper constraints to the context. We read all\n// keys at once since the constraints for reading them all are actually fewer than if we read them one at a time - any\n// read keys that are not required by the caller can simply be discarded.\npub fn get_public_keys(account: AztecAddress) -> PublicKeys {\n // Safety: Public keys are constrained by showing their inclusion in the address's preimage.\n let (public_keys, partial_address) = unsafe { get_public_keys_and_partial_address(account) };\n assert_eq(\n account,\n AztecAddress::compute(public_keys, partial_address),\n \"Invalid public keys hint for address\",\n );\n\n public_keys\n}\n" - }, - "87": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/macros/aztec.nr", - "source": "use crate::{\n macros::{\n dispatch::generate_public_dispatch,\n functions::{stub_registry, utils::check_each_fn_macroified},\n notes::{generate_note_export, NOTES},\n storage::STORAGE_LAYOUT_NAME,\n utils::{get_trait_impl_method, module_has_storage},\n },\n messages::discovery::private_notes::MAX_NOTE_PACKED_LEN,\n};\n\n/// Marks a contract as an Aztec contract, generating the interfaces for its functions and notes, as well as injecting\n/// the `sync_private_state` utility function.\n/// Note: This is a module annotation, so the returned quote gets injected inside the module (contract) itself.\npub comptime fn aztec(m: Module) -> Quoted {\n let interface = generate_contract_interface(m);\n\n // Functions that don't have #[private], #[public], #[utility], #[contract_library_method], or #[test] are not\n // allowed in contracts.\n check_each_fn_macroified(m);\n\n let contract_library_method_compute_note_hash_and_nullifier =\n generate_contract_library_method_compute_note_hash_and_nullifier();\n let note_exports = generate_note_exports();\n let public_dispatch = generate_public_dispatch(m);\n let sync_private_state = generate_sync_private_state();\n\n quote {\n $note_exports\n $interface\n $contract_library_method_compute_note_hash_and_nullifier\n $public_dispatch\n $sync_private_state\n }\n}\n\ncomptime fn generate_contract_interface(m: Module) -> Quoted {\n let module_name = m.name();\n let contract_stubs = stub_registry::get(m);\n let fn_stubs_quote = if contract_stubs.is_some() {\n contract_stubs.unwrap().join(quote {})\n } else {\n quote {}\n };\n\n let has_storage_layout = module_has_storage(m) & STORAGE_LAYOUT_NAME.get(m).is_some();\n let storage_layout_getter = if has_storage_layout {\n let storage_layout_name = STORAGE_LAYOUT_NAME.get(m).unwrap();\n quote {\n pub fn storage_layout() -> StorageLayoutFields {\n $storage_layout_name.fields\n }\n }\n } else {\n quote {}\n };\n\n let library_storage_layout_getter = if has_storage_layout {\n quote {\n #[contract_library_method]\n $storage_layout_getter\n }\n } else {\n quote {}\n };\n\n quote {\n pub struct $module_name {\n pub target_contract: dep::aztec::protocol_types::address::AztecAddress\n }\n\n impl $module_name {\n $fn_stubs_quote\n\n pub fn at(\n addr: aztec::protocol_types::address::AztecAddress\n ) -> Self {\n Self { target_contract: addr }\n }\n\n pub fn interface() -> Self {\n Self { target_contract: aztec::protocol_types::address::AztecAddress::zero() }\n }\n\n $storage_layout_getter\n }\n\n #[contract_library_method]\n pub fn at(\n addr: aztec::protocol_types::address::AztecAddress\n ) -> $module_name {\n $module_name { target_contract: addr }\n }\n\n #[contract_library_method]\n pub fn interface() -> $module_name {\n $module_name { target_contract: aztec::protocol_types::address::AztecAddress::zero() }\n }\n\n $library_storage_layout_getter\n\n }\n}\n\n/// Generates a contract library method called `_compute_note_hash_and_nullifier` which is used for note\n/// discovery (to create the `aztec::messages::discovery::ComputeNoteHashAndNullifier` function) and to implement the\n/// `compute_note_hash_and_nullifier` unconstrained contract function.\ncomptime fn generate_contract_library_method_compute_note_hash_and_nullifier() -> Quoted {\n let notes = NOTES.entries();\n\n if notes.len() > 0 {\n let max_note_packed_len = notes.fold(\n 0,\n |acc, (_, (_, len, _, _)): (Type, (TypeDefinition, u32, Field, [(Quoted, u32, bool)]))| {\n if len > acc {\n len\n } else {\n acc\n }\n },\n );\n\n if max_note_packed_len > MAX_NOTE_PACKED_LEN {\n panic(\n f\"One of the notes has packed len {max_note_packed_len} but the maximum is {MAX_NOTE_PACKED_LEN}\",\n );\n }\n\n // Contracts that do define notes produce an if-else chain where `note_type_id` is matched against the\n // `get_note_type_id()` function of each note type that we know of, in order to identify the note type. Once we\n // know it we call we correct `unpack` method from the `Packable` trait to obtain the underlying note type, and\n // compute the note hash (non-siloed) and inner nullifier (also non-siloed).\n\n let mut if_note_type_id_match_statements_list = &[];\n for i in 0..notes.len() {\n let (typ, (_, packed_note_length, _, _)) = notes[i];\n\n let get_note_type_id = get_trait_impl_method(\n typ,\n quote { crate::note::note_interface::NoteType },\n quote { get_id },\n );\n let unpack = get_trait_impl_method(\n typ,\n quote { crate::protocol_types::traits::Packable<_> },\n quote { unpack },\n );\n\n let compute_note_hash = get_trait_impl_method(\n typ,\n quote { crate::note::note_interface::NoteHash },\n quote { compute_note_hash },\n );\n\n let compute_nullifier_unconstrained = get_trait_impl_method(\n typ,\n quote { crate::note::note_interface::NoteHash },\n quote { compute_nullifier_unconstrained },\n );\n\n let if_or_else_if = if i == 0 {\n quote { if }\n } else {\n quote { else if }\n };\n\n if_note_type_id_match_statements_list = if_note_type_id_match_statements_list.push_back(\n quote {\n $if_or_else_if note_type_id == $get_note_type_id() {\n // As an extra safety check we make sure that the packed_note BoundedVec has the expected\n // length, since we're about to interpret it's raw storage as a fixed-size array by calling the\n // unpack function on it.\n let expected_len = $packed_note_length;\n let actual_len = packed_note.len();\n assert(\n actual_len == expected_len,\n f\"Expected packed note of length {expected_len} but got {actual_len} for note type id {note_type_id}\"\n );\n\n let note = $unpack(aztec::utils::array::subarray(packed_note.storage(), 0));\n\n let note_hash = $compute_note_hash(note, storage_slot);\n \n // The message discovery process finds settled notes, that is, notes that were created in prior\n // transactions and are therefore already part of the note hash tree. We therefore compute the\n // nullification note hash by treating the note as a settled note with the provided nonce.\n let note_hash_for_nullify = aztec::note::utils::compute_note_hash_for_nullify(\n aztec::note::retrieved_note::RetrievedNote{ \n note, \n contract_address, \n metadata: aztec::note::note_metadata::SettledNoteMetadata::new(nonce).into() \n }, \n storage_slot,\n );\n\n let inner_nullifier = $compute_nullifier_unconstrained(note, note_hash_for_nullify);\n\n Option::some(\n aztec::messages::discovery::NoteHashAndNullifier {\n note_hash, inner_nullifier\n }\n )\n }\n },\n );\n }\n\n let if_note_type_id_match_statements = if_note_type_id_match_statements_list.join(quote {});\n\n quote {\n /// Unpacks an array into a note corresponding to `note_type_id` and then computes its note hash\n /// (non-siloed) and inner nullifier (non-siloed) assuming the note has been inserted into the note hash\n /// tree with `nonce`.\n ///\n /// The signature of this function notably matches the `aztec::messages::discovery::ComputeNoteHashAndNullifier` type,\n /// and so it can be used to call functions from that module such as `discover_new_messages`, \n /// `do_process_log` and `attempt_note_discovery`.\n ///\n /// This function is automatically injected by the `#[aztec]` macro.\n #[contract_library_method]\n unconstrained fn _compute_note_hash_and_nullifier(\n packed_note: BoundedVec,\n storage_slot: Field,\n note_type_id: Field,\n contract_address: aztec::protocol_types::address::AztecAddress,\n nonce: Field,\n ) -> Option {\n $if_note_type_id_match_statements\n else {\n Option::none()\n }\n }\n }\n } else {\n // Contracts with no notes still implement this function to avoid having special-casing, the implementation\n // simply throws immediately.\n quote {\n /// This contract does not use private notes, so this function should never be called as it will\n /// unconditionally fail.\n ///\n /// This function is automatically injected by the `#[aztec]` macro.\n #[contract_library_method]\n unconstrained fn _compute_note_hash_and_nullifier(\n _packed_note: BoundedVec,\n _storage_slot: Field,\n _note_type_id: Field,\n _contract_address: aztec::protocol_types::address::AztecAddress,\n _nonce: Field,\n ) -> Option {\n panic(f\"This contract does not use private notes\")\n }\n }\n }\n}\n\ncomptime fn generate_note_exports() -> Quoted {\n let notes = NOTES.values();\n // Second value in each tuple is `note_packed_len` and that is ignored here because it's only used when\n // generating partial note helper functions.\n notes\n .map(|(s, _, note_type_id, fields): (TypeDefinition, u32, Field, [(Quoted, u32, bool)])| {\n generate_note_export(s, note_type_id, fields)\n })\n .join(quote {})\n}\n\ncomptime fn generate_sync_private_state() -> Quoted {\n // We obtain the `utility` function on the next line instead of directly doing\n // `#[aztec::macros::functions::utility]` in the returned quote because the latter would result in the function\n // attribute having the full path in the ABI. This is undesirable because we use the information in the ABI only\n // to determine whether a function is `private`, `public`, or `utility`.\n let utility = crate::macros::functions::utility;\n\n // All we need to do here is trigger message discovery, but this is already done by the #[utility] macro - we don't\n // need to do anything extra.\n quote {\n #[$utility]\n unconstrained fn sync_private_state() {\n }\n }\n}\n" - }, - "88": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/macros/dispatch.nr", - "source": "use super::utils::compute_fn_selector;\nuse std::panic;\n\n/// Returns an `fn public_dispatch(...)` function for the given module that's assumed to be an Aztec contract.\npub comptime fn generate_public_dispatch(m: Module) -> Quoted {\n let functions = m.functions();\n let functions =\n functions.filter(|function: FunctionDefinition| function.has_named_attribute(\"public\"));\n\n let unit = get_type::<()>();\n\n let ifs = functions.map(|function: FunctionDefinition| {\n let parameters = function.parameters();\n let return_type = function.return_type();\n\n let selector: Field = compute_fn_selector(function);\n\n let mut parameters_size = 0;\n for param in parameters {\n parameters_size += size_in_fields(param.1);\n }\n\n let initial_read = if parameters.len() == 0 {\n quote {}\n } else {\n // The initial calldata_copy offset is 1 to skip the Field selector\n // The expected calldata is the serialization of\n // - FunctionSelector: the selector of the function intended to dispatch\n // - Parameters: the parameters of the function intended to dispatch\n // That is, exactly what is expected for a call to the target function,\n // but with a selector added at the beginning.\n quote {\n let input_calldata: [Field; $parameters_size] = dep::aztec::context::public_context::calldata_copy(1, $parameters_size);\n let mut reader = dep::aztec::protocol_types::utils::reader::Reader::new(input_calldata);\n }\n };\n\n let parameter_index = &mut 0;\n let reads = parameters.map(|param: (Quoted, Type)| {\n let parameter_index_value = *parameter_index;\n let param_name = f\"arg{parameter_index_value}\".quoted_contents();\n let param_type = param.1;\n let read = quote {\n let $param_name: $param_type = reader.read_struct(dep::aztec::protocol_types::traits::Deserialize::deserialize);\n };\n *parameter_index += 1;\n quote { $read }\n });\n let read = reads.join(quote { });\n\n let mut args = &[];\n for parameter_index in 0..parameters.len() {\n let param_name = f\"arg{parameter_index}\".quoted_contents();\n args = args.push_back(quote { $param_name });\n }\n\n let args = args.join(quote { , });\n // name of the function is assigned just before the call so debug metadata doesn't span most of this macro when figuring out where the call comes from.\n let name = function.name();\n let call = quote { $name($args) };\n\n let return_code = if return_type == unit {\n quote {\n $call;\n // Force early return.\n dep::aztec::context::public_context::avm_return([]);\n }\n } else {\n quote {\n let return_value = dep::aztec::protocol_types::traits::Serialize::serialize($call);\n dep::aztec::context::public_context::avm_return(return_value.as_slice());\n }\n };\n\n let if_ = quote {\n if selector == $selector {\n $initial_read\n $read\n $return_code\n }\n };\n if_\n });\n\n if ifs.len() == 0 {\n // No dispatch function if there are no public functions\n quote {}\n } else {\n let ifs = ifs.push_back(quote { panic(f\"Unknown selector {selector}\") });\n let dispatch = ifs.join(quote { });\n\n let body = quote {\n // We mark this as public because our whole system depends on public\n // functions having this attribute. However, the public MACRO will\n // handle the public_dispatch function specially and do nothing.\n #[public]\n pub unconstrained fn public_dispatch(selector: Field) {\n $dispatch\n }\n };\n\n body\n }\n}\n\ncomptime fn size_in_fields(typ: Type) -> u32 {\n let size = array_size_in_fields(typ);\n let size = size.or_else(|| bool_size_in_fields(typ));\n let size = size.or_else(|| constant_size_in_fields(typ));\n let size = size.or_else(|| field_size_in_fields(typ));\n let size = size.or_else(|| int_size_in_fields(typ));\n let size = size.or_else(|| str_size_in_fields(typ));\n let size = size.or_else(|| struct_size_in_fields(typ));\n let size = size.or_else(|| tuple_size_in_fields(typ));\n if size.is_some() {\n size.unwrap()\n } else {\n panic(f\"Can't determine size in fields of {typ}\")\n }\n}\n\ncomptime fn array_size_in_fields(typ: Type) -> Option {\n typ.as_array().and_then(|typ: (Type, Type)| {\n let (typ, element_size) = typ;\n element_size.as_constant().map(|x: u32| x * size_in_fields(typ))\n })\n}\n\ncomptime fn bool_size_in_fields(typ: Type) -> Option {\n if typ.is_bool() {\n Option::some(1)\n } else {\n Option::none()\n }\n}\n\ncomptime fn field_size_in_fields(typ: Type) -> Option {\n if typ.is_field() {\n Option::some(1)\n } else {\n Option::none()\n }\n}\n\ncomptime fn int_size_in_fields(typ: Type) -> Option {\n if typ.as_integer().is_some() {\n Option::some(1)\n } else {\n Option::none()\n }\n}\n\ncomptime fn constant_size_in_fields(typ: Type) -> Option {\n typ.as_constant()\n}\n\ncomptime fn str_size_in_fields(typ: Type) -> Option {\n typ.as_str().map(|typ| size_in_fields(typ))\n}\n\ncomptime fn struct_size_in_fields(typ: Type) -> Option {\n typ.as_data_type().map(|typ: (TypeDefinition, [Type])| {\n let struct_type = typ.0;\n let generics = typ.1;\n let mut size = 0;\n for field in struct_type.fields(generics) {\n size += size_in_fields(field.1);\n }\n size\n })\n}\n\ncomptime fn tuple_size_in_fields(typ: Type) -> Option {\n typ.as_tuple().map(|types: [Type]| {\n let mut size = 0;\n for typ in types {\n size += size_in_fields(typ);\n }\n size\n })\n}\n\ncomptime fn get_type() -> Type {\n let t: T = std::mem::zeroed();\n std::meta::type_of(t)\n}\n" - }, - "92": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/macros/functions/initialization_utils.nr", - "source": "use dep::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::GENERATOR_INDEX__CONSTRUCTOR, hash::poseidon2_hash_with_separator, traits::ToField,\n};\n\nuse crate::{\n context::{PrivateContext, PublicContext},\n oracle::get_contract_instance::{\n get_contract_instance, get_contract_instance_deployer_avm,\n get_contract_instance_initialization_hash_avm,\n },\n};\n\npub fn mark_as_initialized_public(context: &mut PublicContext) {\n let init_nullifier =\n compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_nullifier(init_nullifier);\n}\n\npub fn mark_as_initialized_private(context: &mut PrivateContext) {\n let init_nullifier =\n compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_nullifier(init_nullifier);\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_unsiloed_contract_initialization_nullifier(context.this_address());\n context.push_nullifier_read_request(init_nullifier);\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 deployer = get_contract_instance_deployer_avm(address).unwrap();\n let initialization_hash = get_contract_instance_initialization_hash_avm(address).unwrap();\n let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash());\n assert(initialization_hash == expected_init, \"Initialization hash does not match\");\n assert(\n (deployer.is_zero()) | (deployer == context.msg_sender()),\n \"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()),\n \"Initializer address is not the contract deployer\",\n );\n}\n\n/// This function is not only used in macros but it's also used by external people to check that an instance has been\n/// initialized with the correct constructor arguments. Don't hide this unless you implement factory functionality.\npub fn compute_initialization_hash(\n init_selector: FunctionSelector,\n init_args_hash: Field,\n) -> Field {\n poseidon2_hash_with_separator(\n [init_selector.to_field(), init_args_hash],\n GENERATOR_INDEX__CONSTRUCTOR,\n )\n}\n" - }, - "95": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/macros/functions/utils.nr", - "source": "use crate::macros::{\n functions::{abi_export::create_fn_abi_export, call_interface_stubs::stub_fn, stub_registry},\n notes::NOTES,\n utils::{\n add_to_hasher, fn_has_noinitcheck, get_fn_visibility, is_fn_contract_library_method,\n is_fn_initializer, is_fn_internal, is_fn_private, is_fn_public, is_fn_test, is_fn_utility,\n is_fn_view, modify_fn_body, module_has_initializer, module_has_storage,\n },\n};\nuse protocol_types::meta::generate_serialize_to_fields;\nuse std::meta::type_of;\n\npub(crate) comptime fn transform_private(f: FunctionDefinition) -> Quoted {\n let fn_abi = create_fn_abi_export(f);\n let fn_stub = stub_fn(f);\n stub_registry::register(f.module(), fn_stub);\n\n // If a function is further modified as unconstrained, we throw an error\n if f.is_unconstrained() {\n let name = f.name();\n panic(\n f\"Function {name} is annotated with #[private] but marked as unconstrained, remove unconstrained keyword\",\n );\n }\n\n let module_has_initializer = module_has_initializer(f.module());\n let module_has_storage = module_has_storage(f.module());\n\n // Private functions undergo a lot of transformations from their Aztec.nr form into a circuit that can be fed to the\n // Private Kernel Circuit.\n // First we change the function signature so that it also receives `PrivateContextInputs`, which contain information\n // about the execution context (e.g. the caller).\n let original_params = f.parameters();\n f.set_parameters(&[(\n quote { inputs },\n quote { crate::context::inputs::private_context_inputs::PrivateContextInputs }.as_type(),\n )]\n .append(original_params));\n\n let mut body = f.body().as_block().unwrap();\n\n // The original params are hashed and passed to the `context` object, so that the kernel can verify we've received\n // the correct values.\n // TODO: Optimize args_hasher for small number of arguments\n let args_hasher_name = quote { args_hasher };\n let args_hasher = original_params.fold(\n quote {\n let mut $args_hasher_name = dep::aztec::hash::ArgsHasher::new();\n },\n |args_hasher, param: (Quoted, Type)| {\n let (name, typ) = param;\n let appended_arg = add_to_hasher(args_hasher_name, name, typ);\n quote {\n $args_hasher\n $appended_arg\n }\n },\n );\n\n let context_creation = quote {\n let mut context = dep::aztec::context::private_context::PrivateContext::new(inputs, dep::aztec::protocol_types::traits::Hash::hash($args_hasher_name));\n };\n\n // Modifications introduced by the different marker attributes.\n let internal_check = if is_fn_internal(f) {\n create_internal_check(f)\n } else {\n quote {}\n };\n\n let view_check = if is_fn_view(f) {\n create_view_check(f)\n } else {\n quote {}\n };\n\n let (assert_initializer, mark_as_initialized) = if is_fn_initializer(f) {\n (create_assert_correct_initializer_args(f), create_mark_as_initialized(f))\n } else {\n (quote {}, quote {})\n };\n\n let storage_init = if module_has_storage {\n quote {\n // Some functions don't access storage, but it'd be quite difficult to only inject this variable if it is\n // referenced. We instead ignore 'unused variable' warnings for it.\n #[allow(unused_variables)]\n let storage = Storage::init(&mut context);\n }\n } else {\n quote {}\n };\n\n // Initialization checks are not included in contracts that don't have initializers.\n let init_check = if module_has_initializer & !is_fn_initializer(f) & !fn_has_noinitcheck(f) {\n create_init_check(f)\n } else {\n quote {}\n };\n\n // All private functions perform message discovery, since they may need to access notes. This is slightly\n // inefficient and could be improved by only doing it once we actually attempt to read any.\n let message_discovery_call = if NOTES.len() > 0 {\n create_message_discovery_call()\n } else {\n quote {}\n };\n\n // Finally, we need to change the return type to be `PrivateCircuitPublicInputs`, which is what the Private Kernel\n // circuit expects.\n let return_value_var_name = quote { macro__returned__values };\n\n let return_value_type = f.return_type();\n let return_value = if body.len() == 0 {\n quote {}\n } else if return_value_type != type_of(()) {\n // The original return value is passed to a second args hasher which the context receives.\n let (body_without_return, last_body_expr) = body.pop_back();\n let return_value = last_body_expr.quoted();\n let return_value_assignment =\n quote { let $return_value_var_name: $return_value_type = $return_value; };\n let return_hasher_name = quote { return_hasher };\n let return_value_into_hasher =\n add_to_hasher(return_hasher_name, return_value_var_name, return_value_type);\n\n body = body_without_return;\n\n quote {\n let mut $return_hasher_name = dep::aztec::hash::ArgsHasher::new();\n $return_value_assignment\n $return_value_into_hasher\n context.set_return_hash($return_hasher_name);\n }\n } else {\n let (body_without_return, last_body_expr) = body.pop_back();\n if !last_body_expr.has_semicolon()\n & last_body_expr.as_for().is_none()\n & last_body_expr.as_assert().is_none()\n & last_body_expr.as_for_range().is_none()\n & last_body_expr.as_assert_eq().is_none()\n & last_body_expr.as_let().is_none() {\n let unused_return_value_name = f\"_{return_value_var_name}\".quoted_contents();\n body = body_without_return.push_back(\n quote { let $unused_return_value_name = $last_body_expr; }.as_expr().unwrap(),\n );\n }\n quote {}\n };\n\n let context_finish = quote { context.finish() };\n\n let to_prepend = quote {\n $args_hasher\n $context_creation\n $assert_initializer\n $init_check\n $internal_check\n $view_check\n $storage_init\n $message_discovery_call\n };\n\n let to_append = quote {\n $return_value\n $mark_as_initialized\n $context_finish\n };\n let modified_body = modify_fn_body(body, to_prepend, to_append);\n f.set_body(modified_body);\n f.set_return_type(\n quote { dep::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs }\n .as_type(),\n );\n f.set_return_data();\n\n fn_abi\n}\n\npub(crate) comptime fn transform_public(f: FunctionDefinition) -> Quoted {\n let fn_abi = create_fn_abi_export(f);\n let fn_stub = stub_fn(f);\n stub_registry::register(f.module(), fn_stub);\n\n // If a function is further modified as unconstrained, we throw an error\n if f.is_unconstrained() {\n let name = f.name();\n panic(\n f\"Function {name} is annotated with #[public] but marked as unconstrained, remove unconstrained keyword\",\n );\n }\n\n let module_has_initializer = module_has_initializer(f.module());\n let module_has_storage = module_has_storage(f.module());\n\n // Public functions undergo a lot of transformations from their Aztec.nr form.\n let original_params = f.parameters();\n let args_len = original_params\n .map(|(name, typ): (Quoted, Type)| {\n generate_serialize_to_fields(name, typ, false).0.len()\n })\n .fold(0, |acc: u32, val: u32| acc + val);\n\n // Unlike in the private case, in public the `context` does not need to receive the hash of the original params.\n let context_creation = quote {\n let mut context = dep::aztec::context::public_context::PublicContext::new(|| {\n // We start from 1 because we skip the selector for the dispatch function.\n let serialized_args : [Field; $args_len] = dep::aztec::context::public_context::calldata_copy(1, $args_len);\n dep::aztec::hash::hash_args_array(serialized_args)\n });\n };\n\n // Modifications introduced by the different marker attributes.\n let internal_check = if is_fn_internal(f) {\n create_internal_check(f)\n } else {\n quote {}\n };\n\n let view_check = if is_fn_view(f) {\n create_view_check(f)\n } else {\n quote {}\n };\n\n let (assert_initializer, mark_as_initialized) = if is_fn_initializer(f) {\n (create_assert_correct_initializer_args(f), create_mark_as_initialized(f))\n } else {\n (quote {}, quote {})\n };\n\n let storage_init = if module_has_storage {\n // Some functions don't access storage, but it'd be quite difficult to only inject this variable if it is\n // referenced. We instead ignore 'unused variable' warnings for it.\n quote {\n #[allow(unused_variables)]\n let storage = Storage::init(&mut context);\n }\n } else {\n quote {}\n };\n\n // Initialization checks are not included in contracts that don't have initializers.\n let init_check = if module_has_initializer & !fn_has_noinitcheck(f) & !is_fn_initializer(f) {\n create_init_check(f)\n } else {\n quote {}\n };\n\n let to_prepend = quote {\n $context_creation\n $assert_initializer\n $init_check\n $internal_check\n $view_check\n $storage_init\n };\n\n let to_append = quote {\n $mark_as_initialized\n };\n\n let body = f.body().as_block().unwrap();\n let modified_body = modify_fn_body(body, to_prepend, to_append);\n f.set_body(modified_body);\n\n // All public functions are automatically made unconstrained, even if they were not marked as such. This is because\n // instead of compiling into a circuit, they will compile to bytecode that will be later transpiled into AVM\n // bytecode.\n f.set_unconstrained(true);\n f.set_return_public(true);\n\n fn_abi\n}\n\npub(crate) comptime fn transform_utility(f: FunctionDefinition) -> Quoted {\n let fn_abi = create_fn_abi_export(f);\n let fn_stub = stub_fn(f);\n stub_registry::register(f.module(), fn_stub);\n\n // Check if function is marked as unconstrained\n if !f.is_unconstrained() {\n let name = f.name();\n panic(\n f\"Function {name} is annotated with #[utility] but not marked as unconstrained, add unconstrained keyword\",\n );\n }\n\n // Create utility context\n let context_creation =\n quote { let mut context = dep::aztec::context::utility_context::UtilityContext::new(); };\n let module_has_storage = module_has_storage(f.module());\n\n // Initialize Storage if module has storage\n let storage_init = if module_has_storage {\n quote {\n // Some functions don't access storage, but it'd be quite difficult to only inject this variable if it is\n // referenced. We instead ignore 'unused variable' warnings for it.\n #[allow(unused_variables)]\n let storage = Storage::init(context);\n }\n } else {\n quote {}\n };\n\n // All utility functions perform message discovery, since they may need to access private notes that would be\n // found during this process. This is slightly inefficient and could be improved by only doing it once we actually\n // attempt to read any.\n let message_discovery_call = if NOTES.len() > 0 {\n create_message_discovery_call()\n } else {\n quote {}\n };\n\n // Inject context creation, storage initialization, and message discovery call at the beginning of the function\n // body.\n let to_prepend = quote {\n $context_creation\n $storage_init\n $message_discovery_call\n };\n let body = f.body().as_block().unwrap();\n let modified_body = modify_fn_body(body, to_prepend, quote {});\n f.set_body(modified_body);\n\n f.set_return_public(true);\n\n fn_abi\n}\n\ncomptime fn create_internal_check(f: FunctionDefinition) -> Quoted {\n let name = f.name();\n let assertion_message = f\"Function {name} can only be called internally\";\n quote { assert(context.msg_sender() == context.this_address(), $assertion_message); }\n}\n\ncomptime fn create_view_check(f: FunctionDefinition) -> Quoted {\n let name = f.name();\n let assertion_message = f\"Function {name} can only be called statically\";\n if is_fn_private(f) {\n // Here `context` is of type context::PrivateContext\n quote { assert(context.inputs.call_context.is_static_call == true, $assertion_message); }\n } else {\n // Here `context` is of type context::PublicContext\n quote { assert(context.is_static_call(), $assertion_message); }\n }\n}\n\ncomptime fn create_assert_correct_initializer_args(f: FunctionDefinition) -> Quoted {\n let fn_visibility = get_fn_visibility(f);\n f\"dep::aztec::macros::functions::initialization_utils::assert_initialization_matches_address_preimage_{fn_visibility}(context);\"\n .quoted_contents()\n}\n\ncomptime fn create_mark_as_initialized(f: FunctionDefinition) -> Quoted {\n let fn_visibility = get_fn_visibility(f);\n f\"dep::aztec::macros::functions::initialization_utils::mark_as_initialized_{fn_visibility}(&mut context);\"\n .quoted_contents()\n}\n\ncomptime fn create_init_check(f: FunctionDefinition) -> Quoted {\n let fn_visibility = get_fn_visibility(f);\n f\"dep::aztec::macros::functions::initialization_utils::assert_is_initialized_{fn_visibility}(&mut context);\"\n .quoted_contents()\n}\n\n/// Injects a call to `aztec::messages::discovery::discover_new_messages`, causing for new notes to be added to PXE and made\n/// available for the current execution.\npub(crate) comptime fn create_message_discovery_call() -> Quoted {\n quote {\n /// Safety: message discovery returns nothing and is performed solely for its side-effects. It is therefore\n /// always safe to call.\n unsafe {\n dep::aztec::messages::discovery::discover_new_messages(\n context.this_address(),\n _compute_note_hash_and_nullifier,\n );\n };\n }\n}\n\n/// Checks if each function in the module is marked with either #[private], #[public], #[utility],\n/// #[contract_library_method], or #[test]. Non-macroified functions are not allowed in contracts.\npub(crate) comptime fn check_each_fn_macroified(m: Module) {\n for f in m.functions() {\n let name = f.name();\n if !is_fn_private(f)\n & !is_fn_public(f)\n & !is_fn_utility(f)\n & !is_fn_contract_library_method(f)\n & !is_fn_test(f) {\n panic(\n f\"Function {name} must be marked as either #[private], #[public], #[utility], #[contract_library_method], or #[test]\",\n );\n }\n }\n}\n" - }, - "97": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/macros/notes.nr", - "source": "use crate::{macros::utils::AsStrQuote, note::note_getter_options::PropertySelector};\nuse poseidon::poseidon2::Poseidon2Hasher;\nuse protocol_types::meta::{derive_packable_and_get_packed_len, generate_serialize_to_fields};\nuse std::{\n collections::umap::UHashMap,\n hash::{BuildHasherDefault, Hash, Hasher},\n meta::{type_of, unquote},\n};\n\n/// A map from note type to (note_struct_definition, note_packed_len, note_type_id, fields).\n/// `fields` is an array of tuples where each tuple contains the name of the field/struct member (e.g. `amount`\n/// in `TokenNote`), the index of where the packed member starts in the packed note and a flag indicating\n/// whether the field is nullable or not.\npub comptime mut global NOTES: UHashMap> =\n UHashMap::default();\n\npub comptime mut global NOTE_TYPE_ID_COUNTER: u32 = 0;\n\n/// The note type id is set by enumerating the note types.\ncomptime fn get_next_note_type_id() -> Field {\n // We assert that the note type id fits within 7 bits\n assert(\n NOTE_TYPE_ID_COUNTER < 128 as u32,\n \"A contract can contain at most 128 different note types\",\n );\n\n let note_type_id = NOTE_TYPE_ID_COUNTER as Field;\n NOTE_TYPE_ID_COUNTER += 1;\n note_type_id\n}\n\n/// Generates a quote that implements `Packable` for a given struct `s`.\n/// If the note struct already implements `Packable`, we return an empty quote.\ncomptime fn derive_packable_if_not_implemented_and_get_len(s: TypeDefinition) -> (Quoted, u32) {\n // We try to get the packed length of the note struct. If it does not implement `Packable`, we get Option::none()\n let packed_len_typ = std::meta::typ::fresh_type_variable();\n // We don't care about the result of the implements check. We just want the get the packed length.\n let _ = s.as_type().implements(\n quote { crate::protocol_types::traits::Packable<$packed_len_typ> }.as_trait_constraint(),\n );\n let maybe_packed_length = packed_len_typ.as_constant();\n\n if maybe_packed_length.is_some() {\n // We got some packed length meaning that the note struct implements `Packable`. For this reason we return\n // an empty quote for the implementation and the packed length.\n (quote {}, maybe_packed_length.unwrap())\n } else {\n // We didn't manage to get the packed length which means the note struct doesn't implement `Packable`\n // so we derive it and return it along with the packed length.\n derive_packable_and_get_packed_len(s)\n }\n}\n\n/// Generates default `NoteType` implementation for a given note struct `s` and returns it as a quote.\n///\n/// impl NoteType for NoteStruct {\n/// fn get_id() -> Field {\n/// ...\n/// }\n/// }\ncomptime fn generate_note_interface(s: TypeDefinition, note_type_id: Field) -> Quoted {\n let name = s.name();\n\n quote {\n impl aztec::note::note_interface::NoteType for $name {\n fn get_id() -> Field {\n $note_type_id\n }\n }\n }\n}\n\n/// Generates default `NoteHash` trait implementation for a given note struct `s` and returns it as a quote.\n///\n/// # Generated Implementation\n/// ```\n/// impl NoteHash for NoteStruct {\n/// fn compute_note_hash(self, storage_slot: Field) -> Field { ... }\n///\n/// fn compute_nullifier(self, context: &mut PrivateContext, note_hash_for_nullify: Field) -> Field { ... }\n///\n/// unconstrained fn compute_nullifier_unconstrained(note_hash_for_nullify: Field) -> Field { ... }\n/// }\n/// ```\ncomptime fn generate_note_hash_trait_impl(s: TypeDefinition) -> Quoted {\n let name = s.name();\n\n quote {\n impl aztec::note::note_interface::NoteHash for $name {\n fn compute_note_hash(self, storage_slot: Field) -> Field {\n let inputs = aztec::protocol_types::utils::arrays::array_concat(aztec::protocol_types::traits::Packable::pack(self), [storage_slot]);\n aztec::protocol_types::hash::poseidon2_hash_with_separator(inputs, aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_HASH)\n }\n\n fn compute_nullifier(\n self,\n context: &mut aztec::prelude::PrivateContext,\n note_hash_for_nullify: Field,\n ) -> Field {\n let owner_npk_m = aztec::keys::getters::get_public_keys(self.owner).npk_m;\n // We invoke hash as a static trait function rather than calling owner_npk_m.hash() directly\n // in the quote to avoid \"trait not in scope\" compiler warnings.\n let owner_npk_m_hash = aztec::protocol_types::traits::Hash::hash(owner_npk_m);\n let secret = context.request_nsk_app(owner_npk_m_hash);\n aztec::protocol_types::hash::poseidon2_hash_with_separator(\n [note_hash_for_nullify, secret],\n aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n )\n }\n\n unconstrained fn compute_nullifier_unconstrained(\n self,\n note_hash_for_nullify: Field,\n ) -> Field {\n let owner_npk_m = aztec::keys::getters::get_public_keys(self.owner).npk_m;\n // We invoke hash as a static trait function rather than calling owner_npk_m.hash() directly\n // in the quote to avoid \"trait not in scope\" compiler warnings.\n let owner_npk_m_hash = aztec::protocol_types::traits::Hash::hash(owner_npk_m);\n let secret = aztec::keys::getters::get_nsk_app(owner_npk_m_hash);\n aztec::protocol_types::hash::poseidon2_hash_with_separator(\n [note_hash_for_nullify, secret],\n aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n )\n }\n }\n }\n}\n\n/// Generates note properties struct for a given note struct `s`.\n///\n/// Example:\n/// ```\n/// struct TokenNoteProperties {\n/// amount: aztec::note::note_getter_options::PropertySelector,\n/// npk_m_hash: aztec::note::note_getter_options::PropertySelector\n/// randomness: aztec::note::note_getter_options::PropertySelector\n/// }\n///\n/// impl aztec::note::note_interface::NoteProperties for TokenNote {\n/// fn properties() -> TokenNoteProperties {\n/// Self {\n/// amount: aztec::note::note_getter_options::PropertySelector { index: 0, offset: 0, length: 32 },\n/// npk_m_hash: aztec::note::note_getter_options::PropertySelector { index: 1, offset: 0, length: 32 },\n/// randomness: aztec::note::note_getter_options::PropertySelector { index: 2, offset: 0, length: 32 }\n/// }\n/// }\n/// }\n/// ```\ncomptime fn generate_note_properties(s: TypeDefinition) -> Quoted {\n let name = s.name();\n\n let struct_name = f\"{name}Properties\".quoted_contents();\n\n let property_selector_type = type_of(PropertySelector { index: 0, offset: 0, length: 0 });\n\n let note_fields = s.fields_as_written();\n\n let properties_types = note_fields\n .map(|(name, _): (Quoted, Type)| quote { pub $name: $property_selector_type })\n .join(quote {,});\n\n // TODO #8694: Properly handle non-field types https://github.com/AztecProtocol/aztec-packages/issues/8694\n let mut properties_list = &[];\n for i in 0..note_fields.len() {\n let (name, _) = note_fields[i];\n properties_list = properties_list.push_back(\n quote { $name: aztec::note::note_getter_options::PropertySelector { index: $i, offset: 0, length: 32 } },\n );\n }\n\n let properties = properties_list.join(quote {,});\n\n quote {\n pub struct $struct_name {\n $properties_types\n }\n\n impl aztec::note::note_interface::NoteProperties<$struct_name> for $name {\n fn properties() -> $struct_name {\n $struct_name {\n $properties\n }\n }\n }\n }\n}\n\n/// Generates note export for a given note struct `s`. The export is a global variable that contains note type id,\n/// note name and information about note fields (field name, index and whether the field is nullable or not).\n///\n/// Example:\n/// ```\n/// struct TokenNoteFields_5695262104 {\n/// amount: aztec::note::note_field::NoteField,\n/// owner: aztec::note::note_field::NoteField\n/// }\n///\n/// #[abi(notes)]\n/// global TokenNote_EXPORTS_5695262104: (Field, str<8>, TokenNoteFields_5695262104) = (\n/// 0,\n/// \"TokenNote\",\n/// TokenNoteFields_5695262104 {\n/// amount: aztec::note::note_field::NoteField { index: 0, nullable: false },\n/// owner: aztec::note::note_field::NoteField { index: 1, nullable: false }\n/// }\n/// );\n///\n/// Randomly looking value at the end of the export name is generated by hashing the note struct type and is included\n/// to prevent naming collisions in case there are multiple notes with the same name imported in a contract.\npub(crate) comptime fn generate_note_export(\n s: TypeDefinition,\n note_type_id: Field,\n fields: [(Quoted, u32, bool)],\n) -> Quoted {\n let name = s.name();\n let mut hasher = Poseidon2Hasher::default();\n s.as_type().hash(&mut hasher);\n let hash = hasher.finish() as u32;\n let global_export_name = f\"{name}_EXPORTS_{hash}\".quoted_contents();\n let note_fields_name = f\"{name}Fields_{hash}\".quoted_contents();\n let (note_name_as_str, _) = name.as_str_quote();\n let note_name_str_len = unquote!(quote { $note_name_as_str.as_bytes().len() });\n\n let mut note_fields = &[];\n let mut note_field_constructors = &[];\n for field in fields {\n let (name, index, nullable) = field;\n note_fields = note_fields.push_back(quote { $name: aztec::note::note_field::NoteField });\n note_field_constructors = note_field_constructors.push_back(\n quote { $name: aztec::note::note_field::NoteField { index: $index, nullable: $nullable }},\n );\n }\n\n let note_fields = note_fields.join(quote {,});\n let note_field_constructors = note_field_constructors.join(quote {,});\n\n quote {\n pub struct $note_fields_name {\n pub $note_fields\n }\n\n #[abi(notes)]\n global $global_export_name: (Field, str<$note_name_str_len>, $note_fields_name) = ($note_type_id, $note_name_as_str, $note_fields_name { $note_field_constructors });\n }\n}\n\n/// Registers a note struct `note` with the given `note_packed_len`, `note_type_id`, `fixed_fields` and\n/// `nullable_fields` in the global `NOTES` map.\ncomptime fn register_note(\n note: TypeDefinition,\n note_packed_len: u32,\n note_type_id: Field,\n fixed_fields: [(Quoted, Type, u32)],\n nullable_fields: [(Quoted, Type, u32)],\n) {\n let mut fields = &[];\n for field in fixed_fields {\n let (name, _, index) = field;\n fields = fields.push_back((name, index, false));\n }\n for field in nullable_fields {\n let (name, _, index) = field;\n fields = fields.push_back((name, index, true));\n }\n\n NOTES.insert(note.as_type(), (note, note_packed_len, note_type_id, fields));\n}\n\n/// Separates note struct members into fixed and nullable ones. It also stores the index of where each struct member\n/// starts in the serialized note. Note that each struct member can occupy multiple fields (as in Field type).\ncomptime fn index_note_fields(\n s: TypeDefinition,\n nullable_fields: [Quoted],\n) -> ([(Quoted, Type, u32)], [(Quoted, Type, u32)]) {\n let mut indexed_fixed_fields: [(Quoted, Type, u32)] = &[];\n let mut indexed_nullable_fields = &[];\n let mut counter: u32 = 0;\n for field in s.fields_as_written() {\n let (name, typ) = field;\n if nullable_fields.all(|field| field != name) {\n indexed_fixed_fields = indexed_fixed_fields.push_back((name, typ, counter));\n } else {\n indexed_nullable_fields = indexed_nullable_fields.push_back((name, typ, counter));\n }\n let (serialization_fields, _) = generate_serialize_to_fields(name, typ, true);\n // Each struct member can occupy multiple fields so we need to increment the counter accordingly\n counter += serialization_fields.len();\n }\n (indexed_fixed_fields, indexed_nullable_fields)\n}\n\n/// Generates the following:\n/// - NoteTypeProperties\n/// - NoteType trait implementation\n/// - NoteHash trait implementation\n/// - Packable implementation\n///\n/// Registers the note in the global `NOTES` map.\n///\n/// For more details on the generated code, see the individual functions.\npub comptime fn note(s: TypeDefinition) -> Quoted {\n assert_has_owner(s);\n\n let (indexed_fixed_fields, indexed_nullable_fields) = index_note_fields(s, &[]);\n\n let note_properties = generate_note_properties(s);\n let note_type_id = get_next_note_type_id();\n let note_interface_impl = generate_note_interface(s, note_type_id);\n let note_hash_impl = generate_note_hash_trait_impl(s);\n let (packable_impl, note_packed_len) = derive_packable_if_not_implemented_and_get_len(s);\n\n register_note(\n s,\n note_packed_len,\n note_type_id,\n indexed_fixed_fields,\n indexed_nullable_fields,\n );\n\n quote {\n $note_properties\n $note_interface_impl\n $note_hash_impl\n $packable_impl\n }\n}\n\n/// Generates code for a custom note implementation that requires specialized note hash or nullifier computation.\n///\n/// # Generated Code\n/// - NoteTypeProperties: Defines the structure and properties of note fields\n/// - NoteType trait implementation: Provides the note type ID\n/// - Packable implementation: Enables serialization/deserialization of the note\n///\n/// # Registration\n/// Registers the note in the global `NOTES` map with:\n/// - Note type ID\n/// - Packed length\n/// - Field indices and nullability\n///\n/// # Use Cases\n/// Use this macro when implementing a note that needs custom:\n/// - Note hash computation logic\n/// - Nullifier computation logic\n///\n/// The macro omits generating default NoteHash trait implementation, allowing you to provide your own.\n///\n/// # Example\n/// ```\n/// #[custom_note]\n/// struct CustomNote {\n/// value: Field,\n/// metadata: Field\n/// }\n///\n/// impl NoteHash for CustomNote {\n/// // Custom note hash computation...\n/// fn compute_note_hash(...) -> Field { ... }\n///\n/// // Custom nullifier computation...\n/// fn compute_nullifier(...) -> Field { ... }\n/// fn compute_nullifier_unconstrained(...) -> Field { ... }\n/// }\n/// ```\npub comptime fn custom_note(s: TypeDefinition) -> Quoted {\n let (packable_impl, note_packed_len) = derive_packable_if_not_implemented_and_get_len(s);\n let note_type_id = get_next_note_type_id();\n\n let (indexed_fixed_fields, indexed_nullable_fields) = index_note_fields(s, &[]);\n register_note(\n s,\n note_packed_len,\n note_type_id,\n indexed_fixed_fields,\n indexed_nullable_fields,\n );\n\n let note_properties = generate_note_properties(s);\n let note_interface_impl = generate_note_interface(s, note_type_id);\n\n quote {\n $note_properties\n $note_interface_impl\n $packable_impl\n }\n}\n\n/// Asserts that the note has an 'owner' field.\n///\n/// We require notes implemented with #[note] macro macro to have an 'owner' field because our\n/// auto-generated nullifier functions expect it. This requirement is most likely only temporary.\ncomptime fn assert_has_owner(note: TypeDefinition) {\n let fields = note.fields_as_written();\n let mut has_owner = false;\n for i in 0..fields.len() {\n let (field_name, _) = fields[i];\n if field_name == quote { owner } {\n has_owner = true;\n break;\n }\n }\n assert(\n has_owner,\n \"Note must have an 'owner' field. If your notes have no owner, use #[custom_note] insteadof #[note] and implement the NoteHashing trait manually.\",\n );\n}\n" - }, - "98": { - "path": "/mnt/user-data/saleel/nargo/github.com/AztecProtocol/aztec-packages/v0.87.4/noir-projects/aztec-nr/aztec/src/macros/storage.nr", - "source": "use poseidon::poseidon2::Poseidon2Hasher;\nuse std::{collections::umap::UHashMap, hash::BuildHasherDefault};\n\nuse super::utils::AsStrQuote;\nuse super::utils::get_storage_size;\n\n/// Stores a map from a module to the name of the struct that describes its storage layout.\n/// This is then used when generating a `storage_layout()` getter on the contract struct.\npub comptime mut global STORAGE_LAYOUT_NAME: UHashMap> =\n UHashMap::default();\n\n/// Marks a struct as the one describing the storage layout of a contract.\n///\n/// The contract's storage is accessed via the `storage` variable, which will will automatically be made available in\n/// all functions as an instance of the struct this macro was applied to.\n///\n/// Only a single struct in the entire contract should have this macro (or `storage_no_init`) applied to it, and the\n/// struct has to be called 'Storage'.\npub comptime fn storage(s: TypeDefinition) -> Quoted {\n let struct_name = s.name();\n if struct_name != quote { Storage } {\n panic(\n f\"The #[storage] macro can only be applied to a struct with name 'Storage', got '{struct_name}' instead.\",\n )\n }\n\n assert(\n !s.has_named_attribute(\"storage_no_init\"),\n f\"Only one of #[storage] and #[storage_no_init] can be applied to the Storage struct.\",\n );\n\n // This macro performs three things:\n // - it marks the contract as having storage, so that `macros::utils::module_has_storage` will return true and\n // functions will have the storage variable injected and initialized via the `init` function.\n // - it implements said `init` function by allocating appropriate storage slots to each state variable.\n // - it exposes the storage layout by creating a `StorageLayout` struct that is exposed via the `abi(storage)`\n // macro.\n let mut slot: u32 = 1;\n let mut storage_vars_constructors = &[];\n let mut storage_layout_fields = &[];\n let mut storage_layout_constructors = &[];\n\n // TODO(#8658): uncomment the code below to inject the Context type parameter.\n //let mut new_storage_fields = &[];\n //let context_generic = s.add_generic(\"Context\");\n for field in s.fields_as_written() {\n // FIXME: This doesn't handle field types with generics\n let (name, typ) = field;\n let (storage_field_constructor, storage_size) =\n generate_storage_field_constructor(typ, quote { $slot });\n storage_vars_constructors =\n storage_vars_constructors.push_back(quote { $name: $storage_field_constructor });\n // We have `Storable` in a separate `.nr` file instead of defining it in the last quote of this function\n // because that way a dev gets a more reasonable error if he defines a struct with the same name in\n // a contract.\n storage_layout_fields =\n storage_layout_fields.push_back(quote { pub $name: dep::aztec::prelude::Storable });\n storage_layout_constructors = storage_layout_constructors.push_back(\n quote { $name: dep::aztec::prelude::Storable { slot: $slot } },\n );\n //let with_context_generic = add_context_generic(typ, context_generic);\n //println(with_context_generic);\n //new_storage_fields = new_storage_fields.push_back((name, with_context_generic ));\n slot += storage_size;\n }\n\n //s.set_fields(new_storage_fields);\n let storage_vars_constructors = storage_vars_constructors.join(quote {,});\n let storage_impl = quote {\n impl Storage {\n fn init(context: Context) -> Self {\n Self {\n $storage_vars_constructors\n }\n }\n }\n };\n\n let storage_layout_fields = storage_layout_fields.join(quote {,});\n let storage_layout_constructors = storage_layout_constructors.join(quote {,});\n\n let module = s.module();\n let module_name = module.name();\n let storage_layout_name = f\"STORAGE_LAYOUT_{module_name}\".quoted_contents();\n let (module_name_str, module_name_len) = module_name.as_str_quote();\n STORAGE_LAYOUT_NAME.insert(module, storage_layout_name);\n\n quote {\n $storage_impl\n\n pub struct StorageLayoutFields {\n $storage_layout_fields\n }\n\n pub struct StorageLayout {\n pub contract_name: str,\n pub fields: StorageLayoutFields\n }\n\n #[abi(storage)]\n pub global $storage_layout_name: StorageLayout<$module_name_len> = StorageLayout {\n contract_name: $module_name_str,\n fields: StorageLayoutFields { $storage_layout_constructors }\n };\n }\n}\n\n/// Same as `storage`, except the user is in charge of providing an implementation of the `init` constructor function\n/// with signature `fn init(context: Context) -> Self`, which allows for manual control of storage slot\n/// allocation. Similarly, no `StorageLayout` struct will be created.\n///\n/// The contract's storage is accessed via the `storage` variable, which will will automatically be made available in\n/// all functions as an instance of the struct this macro was applied to.\n///\n/// Only a single struct in the entire contract can have this macro (or storage_no_init) applied to it, and the struct\n/// has to be called 'Storage'.\npub comptime fn storage_no_init(s: TypeDefinition) {\n // All `storage` does is provide the `init` implementation, so we don't need to do anything here. Applying this\n // macro however will cause for `macros::utils::module_has_storage` to return true, resulting in the injection of\n // the `storage` variable.\n\n // We do need to make sure that the type is called Storage, since we'll do `Storage::init` later on.\n\n if s.name() != quote { Storage } {\n let name = s.name();\n panic(\n f\"The #[storage_no_init] macro can only be applied to a struct with name 'Storage', got '{name}' instead.\",\n )\n }\n\n assert(\n !s.has_named_attribute(\"storage\"),\n f\"Only one of #[storage] and #[storage_no_init] can be applied to the Storage struct.\",\n );\n}\n\n/// Returns the expression required to initialize a state variable with a given slot, along with its serialization size,\n/// i.e. how many contiguous storage slots the variable requires.\ncomptime fn generate_storage_field_constructor(typ: Type, slot: Quoted) -> (Quoted, u32) {\n assert(\n typ.as_data_type().is_some(),\n \"Storage containers must be generic structs of the form `Container<_, Context>`, or Map\",\n );\n let (container_struct, generics) = typ.as_data_type().unwrap();\n let struct_name = container_struct.name();\n\n let constructor = if is_storage_map(typ) {\n // Map state variables recursively initialize their contents - this includes nested maps.\n let (value_constructor, _) =\n generate_storage_field_constructor(generics[1], quote { slot });\n\n quote { $struct_name::new(context, $slot, | context, slot | { $value_constructor }) }\n } else {\n // We assume below that all state variables implement `fn new(context: Context, slot: Field) -> Self`.\n quote { $struct_name::new(context, $slot)}\n };\n\n (constructor, get_storage_size(typ))\n}\n\n/// Returns true if `typ` is `state_vars::map::Map`.\ncomptime fn is_storage_map(typ: Type) -> bool {\n if typ.as_data_type().is_some() {\n let (def, generics) = typ.as_data_type().unwrap();\n let maybe_map = if (def.name() == quote { Map }) & (generics.len() == 3) {\n let maybe_key = generics[0];\n let maybe_value = generics[1];\n let maybe_context = generics[2];\n quote { crate::state_vars::map::Map<$maybe_key, $maybe_value, $maybe_context> }.as_type()\n } else {\n quote {()}.as_type()\n };\n typ == maybe_map\n } else {\n false\n }\n}\n\ncomptime fn add_context_generic(typ: Type, context_generic: Type) -> Type {\n let (def, mut generics) = typ.as_data_type().expect(\n f\"Storage containers must be generic structs of the form `Container<..., Context>`\",\n );\n let name = def.name();\n\n if is_storage_map(typ) {\n generics[generics.len() - 2] = add_context_generic(generics[1], context_generic);\n generics[generics.len() - 1] = context_generic;\n } else {\n generics[generics.len() - 1] = context_generic;\n }\n\n let generics = generics.map(|typ: Type| quote {$typ}).join(quote {,});\n quote { $name<$generics> }.as_type()\n}\n" - } - } -} diff --git a/app/artifacts/private_voting-PrivateVoting.json b/app/artifacts/private_voting-PrivateVoting.json new file mode 100644 index 0000000..a4aafd1 --- /dev/null +++ b/app/artifacts/private_voting-PrivateVoting.json @@ -0,0 +1,3410 @@ +{ + "transpiled": true, + "noir_version": "1.0.0-beta.11+5b65f9637e85a4177692c3190cb35ea678fb15e9-aztec", + "name": "PrivateVoting", + "functions": [ + { + "name": "add_to_tally_public", + "is_unconstrained": true, + "custom_attributes": [ + "public", + "internal" + ], + "abi": { + "parameters": [ + { + "name": "candidate", + "type": { + "kind": "field" + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "206160798890201757": { + "error_kind": "string", + "string": "Storage slot 0 not allowed. Storage slots must start from 1." + }, + "2024020833944022298": { + "error_kind": "string", + "string": "Function add_to_tally_public can only be called internally" + }, + "3557153117338734214": { + "error_kind": "string", + "string": "Vote has ended" + }, + "13699457482007836410": { + "error_kind": "string", + "string": "Not initialized" + }, + "17843811134343075018": { + "error_kind": "string", + "string": "Stack too deep" + } + } + }, + "bytecode": "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", + "debug_symbols": "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" + }, + { + "name": "cast_vote", + "is_unconstrained": false, + "custom_attributes": [ + "private" + ], + "abi": { + "parameters": [ + { + "name": "inputs", + "type": { + "kind": "struct", + "path": "aztec::context::inputs::private_context_inputs::PrivateContextInputs", + "fields": [ + { + "name": "call_context", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::call_context::CallContext", + "fields": [ + { + "name": "msg_sender", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "contract_address", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "function_selector", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::function_selector::FunctionSelector", + "fields": [ + { + "name": "inner", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "is_static_call", + "type": { + "kind": "boolean" + } + } + ] + } + }, + { + "name": "historical_header", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::block_header::BlockHeader", + "fields": [ + { + "name": "last_archive", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", + "fields": [ + { + "name": "root", + "type": { + "kind": "field" + } + }, + { + "name": "next_available_leaf_index", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "content_commitment", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::content_commitment::ContentCommitment", + "fields": [ + { + "name": "blobs_hash", + "type": { + "kind": "field" + } + }, + { + "name": "in_hash", + "type": { + "kind": "field" + } + }, + { + "name": "out_hash", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "state", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::state_reference::StateReference", + "fields": [ + { + "name": "l1_to_l2_message_tree", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", + "fields": [ + { + "name": "root", + "type": { + "kind": "field" + } + }, + { + "name": "next_available_leaf_index", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "partial", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::partial_state_reference::PartialStateReference", + "fields": [ + { + "name": "note_hash_tree", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", + "fields": [ + { + "name": "root", + "type": { + "kind": "field" + } + }, + { + "name": "next_available_leaf_index", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "nullifier_tree", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", + "fields": [ + { + "name": "root", + "type": { + "kind": "field" + } + }, + { + "name": "next_available_leaf_index", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "public_data_tree", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", + "fields": [ + { + "name": "root", + "type": { + "kind": "field" + } + }, + { + "name": "next_available_leaf_index", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + } + ] + } + } + ] + } + }, + { + "name": "global_variables", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::global_variables::GlobalVariables", + "fields": [ + { + "name": "chain_id", + "type": { + "kind": "field" + } + }, + { + "name": "version", + "type": { + "kind": "field" + } + }, + { + "name": "block_number", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + }, + { + "name": "slot_number", + "type": { + "kind": "field" + } + }, + { + "name": "timestamp", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + }, + { + "name": "coinbase", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::eth_address::EthAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "fee_recipient", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "gas_fees", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::gas_fees::GasFees", + "fields": [ + { + "name": "fee_per_da_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "fee_per_l2_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + } + ] + } + } + ] + } + }, + { + "name": "total_fees", + "type": { + "kind": "field" + } + }, + { + "name": "total_mana_used", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "tx_context", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::transaction::tx_context::TxContext", + "fields": [ + { + "name": "chain_id", + "type": { + "kind": "field" + } + }, + { + "name": "version", + "type": { + "kind": "field" + } + }, + { + "name": "gas_settings", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::gas_settings::GasSettings", + "fields": [ + { + "name": "gas_limits", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::gas::Gas", + "fields": [ + { + "name": "da_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + }, + { + "name": "l2_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "teardown_gas_limits", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::gas::Gas", + "fields": [ + { + "name": "da_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + }, + { + "name": "l2_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "max_fees_per_gas", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::gas_fees::GasFees", + "fields": [ + { + "name": "fee_per_da_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "fee_per_l2_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + } + ] + } + }, + { + "name": "max_priority_fees_per_gas", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::gas_fees::GasFees", + "fields": [ + { + "name": "fee_per_da_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "fee_per_l2_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + } + ] + } + } + ] + } + } + ] + } + }, + { + "name": "start_side_effect_counter", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + }, + "visibility": "private" + }, + { + "name": "candidate", + "type": { + "kind": "field" + }, + "visibility": "private" + } + ], + "return_type": { + "abi_type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs", + "fields": [ + { + "name": "call_context", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::call_context::CallContext", + "fields": [ + { + "name": "msg_sender", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "contract_address", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "function_selector", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::function_selector::FunctionSelector", + "fields": [ + { + "name": "inner", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "is_static_call", + "type": { + "kind": "boolean" + } + } + ] + } + }, + { + "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": "include_by_timestamp", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + }, + { + "name": "note_hash_read_requests", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", + "fields": [ + { + "name": "array", + "type": { + "kind": "array", + "length": 16, + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::read_request::ReadRequest", + "fields": [ + { + "name": "value", + "type": { + "kind": "field" + } + }, + { + "name": "counter", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + } + }, + { + "name": "length", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "nullifier_read_requests", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", + "fields": [ + { + "name": "array", + "type": { + "kind": "array", + "length": 16, + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::read_request::ReadRequest", + "fields": [ + { + "name": "value", + "type": { + "kind": "field" + } + }, + { + "name": "counter", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + } + }, + { + "name": "length", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "key_validation_requests_and_generators", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", + "fields": [ + { + "name": "array", + "type": { + "kind": "array", + "length": 16, + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator", + "fields": [ + { + "name": "request", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest", + "fields": [ + { + "name": "pk_m", + "type": { + "kind": "struct", + "path": "std::embedded_curve_ops::EmbeddedCurvePoint", + "fields": [ + { + "name": "x", + "type": { + "kind": "field" + } + }, + { + "name": "y", + "type": { + "kind": "field" + } + }, + { + "name": "is_infinite", + "type": { + "kind": "boolean" + } + } + ] + } + }, + { + "name": "sk_app", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "sk_app_generator", + "type": { + "kind": "field" + } + } + ] + } + } + }, + { + "name": "length", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "note_hashes", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", + "fields": [ + { + "name": "array", + "type": { + "kind": "array", + "length": 16, + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::note_hash::NoteHash", + "fields": [ + { + "name": "value", + "type": { + "kind": "field" + } + }, + { + "name": "counter", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + } + }, + { + "name": "length", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "nullifiers", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", + "fields": [ + { + "name": "array", + "type": { + "kind": "array", + "length": 16, + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::nullifier::Nullifier", + "fields": [ + { + "name": "value", + "type": { + "kind": "field" + } + }, + { + "name": "counter", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + }, + { + "name": "note_hash", + "type": { + "kind": "field" + } + } + ] + } + } + }, + { + "name": "length", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "private_call_requests", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", + "fields": [ + { + "name": "array", + "type": { + "kind": "array", + "length": 5, + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::private_call_request::PrivateCallRequest", + "fields": [ + { + "name": "call_context", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::call_context::CallContext", + "fields": [ + { + "name": "msg_sender", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "contract_address", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "function_selector", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::function_selector::FunctionSelector", + "fields": [ + { + "name": "inner", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "is_static_call", + "type": { + "kind": "boolean" + } + } + ] + } + }, + { + "name": "args_hash", + "type": { + "kind": "field" + } + }, + { + "name": "returns_hash", + "type": { + "kind": "field" + } + }, + { + "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": "length", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "public_call_requests", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", + "fields": [ + { + "name": "array", + "type": { + "kind": "array", + "length": 16, + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::side_effect::counted::Counted", + "fields": [ + { + "name": "inner", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::public_call_request::PublicCallRequest", + "fields": [ + { + "name": "msg_sender", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "contract_address", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "is_static_call", + "type": { + "kind": "boolean" + } + }, + { + "name": "calldata_hash", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "counter", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + } + }, + { + "name": "length", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "public_teardown_call_request", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::public_call_request::PublicCallRequest", + "fields": [ + { + "name": "msg_sender", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "contract_address", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "is_static_call", + "type": { + "kind": "boolean" + } + }, + { + "name": "calldata_hash", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "l2_to_l1_msgs", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", + "fields": [ + { + "name": "array", + "type": { + "kind": "array", + "length": 2, + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::side_effect::counted::Counted", + "fields": [ + { + "name": "inner", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message", + "fields": [ + { + "name": "recipient", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::eth_address::EthAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "content", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "counter", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + } + }, + { + "name": "length", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "private_logs", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", + "fields": [ + { + "name": "array", + "type": { + "kind": "array", + "length": 16, + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::private_log::PrivateLogData", + "fields": [ + { + "name": "log", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::log::Log", + "fields": [ + { + "name": "fields", + "type": { + "kind": "array", + "length": 18, + "type": { + "kind": "field" + } + } + }, + { + "name": "length", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "note_hash_counter", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + }, + { + "name": "counter", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + } + }, + { + "name": "length", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "contract_class_logs_hashes", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", + "fields": [ + { + "name": "array", + "type": { + "kind": "array", + "length": 1, + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::side_effect::counted::Counted", + "fields": [ + { + "name": "inner", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::log_hash::LogHash", + "fields": [ + { + "name": "value", + "type": { + "kind": "field" + } + }, + { + "name": "length", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "counter", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + } + }, + { + "name": "length", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "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": "historical_header", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::block_header::BlockHeader", + "fields": [ + { + "name": "last_archive", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", + "fields": [ + { + "name": "root", + "type": { + "kind": "field" + } + }, + { + "name": "next_available_leaf_index", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "content_commitment", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::content_commitment::ContentCommitment", + "fields": [ + { + "name": "blobs_hash", + "type": { + "kind": "field" + } + }, + { + "name": "in_hash", + "type": { + "kind": "field" + } + }, + { + "name": "out_hash", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "state", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::state_reference::StateReference", + "fields": [ + { + "name": "l1_to_l2_message_tree", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", + "fields": [ + { + "name": "root", + "type": { + "kind": "field" + } + }, + { + "name": "next_available_leaf_index", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "partial", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::partial_state_reference::PartialStateReference", + "fields": [ + { + "name": "note_hash_tree", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", + "fields": [ + { + "name": "root", + "type": { + "kind": "field" + } + }, + { + "name": "next_available_leaf_index", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "nullifier_tree", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", + "fields": [ + { + "name": "root", + "type": { + "kind": "field" + } + }, + { + "name": "next_available_leaf_index", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "public_data_tree", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", + "fields": [ + { + "name": "root", + "type": { + "kind": "field" + } + }, + { + "name": "next_available_leaf_index", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + } + ] + } + } + ] + } + }, + { + "name": "global_variables", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::global_variables::GlobalVariables", + "fields": [ + { + "name": "chain_id", + "type": { + "kind": "field" + } + }, + { + "name": "version", + "type": { + "kind": "field" + } + }, + { + "name": "block_number", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + }, + { + "name": "slot_number", + "type": { + "kind": "field" + } + }, + { + "name": "timestamp", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 64 + } + }, + { + "name": "coinbase", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::eth_address::EthAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "fee_recipient", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "gas_fees", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::gas_fees::GasFees", + "fields": [ + { + "name": "fee_per_da_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "fee_per_l2_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + } + ] + } + } + ] + } + }, + { + "name": "total_fees", + "type": { + "kind": "field" + } + }, + { + "name": "total_mana_used", + "type": { + "kind": "field" + } + } + ] + } + }, + { + "name": "tx_context", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::transaction::tx_context::TxContext", + "fields": [ + { + "name": "chain_id", + "type": { + "kind": "field" + } + }, + { + "name": "version", + "type": { + "kind": "field" + } + }, + { + "name": "gas_settings", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::gas_settings::GasSettings", + "fields": [ + { + "name": "gas_limits", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::gas::Gas", + "fields": [ + { + "name": "da_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + }, + { + "name": "l2_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "teardown_gas_limits", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::gas::Gas", + "fields": [ + { + "name": "da_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + }, + { + "name": "l2_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "max_fees_per_gas", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::gas_fees::GasFees", + "fields": [ + { + "name": "fee_per_da_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "fee_per_l2_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + } + ] + } + }, + { + "name": "max_priority_fees_per_gas", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::abis::gas_fees::GasFees", + "fields": [ + { + "name": "fee_per_da_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + }, + { + "name": "fee_per_l2_gas", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 128 + } + } + ] + } + } + ] + } + } + ] + } + } + ] + }, + "visibility": "databus" + }, + "error_types": { + "576755928210959028": { + "error_kind": "string", + "string": "0 has a square root; you cannot claim it is not square" + }, + "855401245733623969": { + "error_kind": "string", + "string": "Obtained invalid key validation request" + }, + "1004672304334401604": { + "error_kind": "fmtstring", + "length": 48, + "item_types": [ + { + "kind": "field" + }, + { + "kind": "field" + } + ] + }, + "2920182694213909827": { + "error_kind": "string", + "string": "attempt to subtract with overflow" + }, + "3206131020419630384": { + "error_kind": "fmtstring", + "length": 75, + "item_types": [] + }, + "3305101268118424981": { + "error_kind": "string", + "string": "Attempted to delete past the length of a CapsuleArray" + }, + "3738765135689704617": { + "error_kind": "fmtstring", + "length": 58, + "item_types": [ + { + "kind": "field" + } + ] + }, + "5019202896831570965": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "5727012404371710682": { + "error_kind": "string", + "string": "push out of bounds" + }, + "6485997221020871071": { + "error_kind": "string", + "string": "call to assert_max_bit_size" + }, + "7233212735005103307": { + "error_kind": "string", + "string": "attempt to multiply with overflow" + }, + "8270195893599566439": { + "error_kind": "string", + "string": "Invalid public keys hint for address" + }, + "10676044680617262041": { + "error_kind": "fmtstring", + "length": 98, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + }, + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + }, + { + "kind": "field" + } + ] + }, + "11732781666457836689": { + "error_kind": "fmtstring", + "length": 77, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "13649294680379557736": { + "error_kind": "string", + "string": "extend_from_bounded_vec out of bounds" + }, + "14101993474458164081": { + "error_kind": "fmtstring", + "length": 61, + "item_types": [ + { + "kind": "field" + }, + { + "kind": "field" + } + ] + }, + "14225679739041873922": { + "error_kind": "string", + "string": "Index out of bounds" + }, + "14657895983200220173": { + "error_kind": "string", + "string": "Attempted to read past the length of a CapsuleArray" + }, + "15200354114977654233": { + "error_kind": "fmtstring", + "length": 144, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "15760694058516861966": { + "error_kind": "fmtstring", + "length": 128, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "16218014537381711836": { + "error_kind": "string", + "string": "Value does not fit in field" + }, + "16446004518090376065": { + "error_kind": "string", + "string": "Input length must be a multiple of 32" + }, + "16954218183513903507": { + "error_kind": "string", + "string": "Attempted to read past end of BoundedVec" + }, + "17226037485472400844": { + "error_kind": "fmtstring", + "length": 132, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "17610130137239148460": { + "error_kind": "fmtstring", + "length": 98, + "item_types": [] + }, + "17843811134343075018": { + "error_kind": "string", + "string": "Stack too deep" + } + } + }, + "bytecode": "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", + "debug_symbols": "TJ3LrjU9b5zv5R9nsHQgReVWMghyNAwYNpDDyMi9ZzdLZNXE71O/v62S1M1avbq5e//7P/77//iv//ef/vM//+v//Lf//Y//+J/+/R//9X/987/8yz//03/+l3/7b//l//zzv/3r3//67//4ff9n7H/8x7mu/b//8I/x6f33v47/8I898M/EPwv/bPxj+Mfxz8E/gX9u/mMYxTCKYRTDKIZRDKMYRjGMYhjFMIpjFMcojlEcozhGcYziGMUximMUxygHoxyMcjDKwSgHoxyMcjDKwSgHoxyMEhglMEpglMAogVECowRGCYwSGCUwysUoF6NcjHIxysUoF6NcjHIxysUoF6OM3+/9O96/8/273r/7/WvvX3//nvdvvH/feOONN95444033njjjTfeeOONN/7Gs+/feP9e/Dt/79/x/p3v3/X+3e9fe//6+/eNN9948288//t3/d6/4/0737/r/bvfv/b+/Rvvfv9+610fRMF9kOd5wiiYBd+qzwe7wAq84Bs5PoiC+yDP/W938uxPmAV/I8/9wS6wAi84BVFwH3z1ABgFs6BG9hrZa2Svkb/qmN/2fPUBuA++GgGMglmwCnaBFXhBjXxq5FMjR40cNXLUyFEjR40cNXLUyFEjR40cNfKtkW+NfGvkWyPfGvmrqvkdna+uAKcgCi5gfuUFGAWzYBXsAivwglMQBTXyqJFHjTxq5FEjjxp51MijRh418qiRR408a+RZI88aedbIs0aeNfKskWeNPGvkWSOvGnnVyKtGXjXyqpFXjbxq5FUjrxp51ci7Rt418q6Rd428a+RdI+8aedfIu0beNbLVyFYjW41sNbLVyFYjW41sNbLVyFYje4381eAaH8yCVbALrMALTkEU3AdfDQJq5FMjnxr51MhfDa79gRecgm/k+8F98NUgYBTMglWwC6zAC05BjRw18q2Rb418XyLNuwp2gRV4wSmIgpd16/crGAWzYBXsAiv4G3nPD05BFNwHXw0CRsEsWAW7wApq5FEjjxp51MizRv5qcK8PZsEq2AVW4AWnIArug68GATXyqpFXjbxq5K8G7feBF5yCKLgPvhoEjIJZsAp2QY28a+RdI+8aedfIViNbjWw1stXIViNbjWw1stXIViNbjew1stfIXiN7jew1stfIXiN7jew1stfIp0Y+NfKpkU+NfGrkUyOfGvnUyKdGPjVy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0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOkdbUjYrZ52DoukWZZ2DRtNsWk27yZra47THaY/THtEe0R7RHtEe0R7RHtEe0R7RHtEetz1ue9z2uO1x2+O2x22P2x63PW55oHEJNJpm02raTdbkTacpmtpjtMdoj9Eeoz1Ge4z2GO0x2mO0x2iP2R6zPWZ7zPaY7THbY7bHbI/ZHrM9Vnus9ljtsdpjtcdqj9Ueqz1We6z22O2x22O3x26P3R67PXZ77PbY7bHbw9rD2sPaw9rD2sPaw9rD2sPaw9rD28Pbw9vD28Pbw9uj63x3ne+u8911vrvOs//JR9JsWk27yZq86TRF0y366vxRe0R7RHtEe0R7RHtEe0R7RHvc9rjtcdvjtsdtj9setz1ue9z2uOWRzVGPRtNsWk27yZq86TRFU3uM9hjtMdpjtMdoj9Eeoz1Ge4z2GO0x22O2x2yP2R6zPWZ7zPaY7THbY7bHao/VHqs9Vnus9ljtsdpjtcdqj9Ueuz12e+z22O2x22O3x26P3R67PXZ7WHtYe1h7WHtYe1h7WHtYe1h7WHt4e3h7eHt4e3h7eHt4e3h7eHt4e5z26Dq3rnPrOreuc+s6t65z6zq3rnPrOreuc+s6t65z6zq3rnPrOreuc+s6t65z6zq3rnPrOreuc+s6t65z6zq3rnPrOreu8+y/cvze069pNM2m1bSbrMmbTlM0tcdoj9Eeoz1Ge4z2GO0x2mO0x2iP0R6zPWZ7zPaY7THb46vz80vyptMUTbfoq/NHo2k2rabd1B5fnZ+RdJqi6RZ9df5oNM2m1bSbrKk9dnvs9tjt8dX5WUmjaTatpt1kTd50mqLpFnl7eHt4e3h7eHt4e3h7eHt4e3h7nPY47XHa47THaY/THqc9Tnuc9jjt8dX5wW/2jabZ9OcRM2k3WdOfR2CU0xRNfx7x/SpmtnY9Gk2zaTXtJmvyptMUTeWRTV6PRtNs+jzw24q7yZo+j5t0mqLpFn11/mg0zabVtJusqT1Ge4z2GO3x1fn9JY2m2bSadpM1edNpiqZbtNpjtcdqj9Ueqz1We6z2WO2x2mO1x26P3R67PXZ77PbY7bHbY7fHbo/dHtYe1h7WHtYe1h7WHtYe1h7WHtYe3h7eHt4e3h7eHt4e3h7eHt4e3h6nPU57nPY47XHa47THaY/THqc9TntEe0R7RHtEe0R7RHtEe0R7RHtEe9z2uO1x2+O2x22P2x63PW573Pa45ZGNZI9G02xaTbvJmrzpNEVTe4z2GO0x2mO0x2iP0R6jPUZ7fHV+Z9ItyjoHjabZtJp2kzV502lqj9keqz1We6z2WO2x2mO1x2qP1R6rPVZ77PbY7bHbY7fHbo/dHrs9dnvs9tjtYe1h7WHtYe1h7WHtYe1h7WHtYe3h7eHt4e3h7eHt4e3h7eHt4e3h7XHa47THaY/THqc9Tnuc9jjtcdrjtEe0R7RHtEe0R7RHtEe0R7RHtEe0x22P2x63PW573Pa47XHb47bHbY9bHtms9mg0zabVtJusyZtOUzS1x2iP0R6jPUZ7jPYY7THaY7RH1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d59kBdy3Jm05TNN2irHPQaJpNq2k3tcdtj9setz2yzj3fl/FrGk2zaTXtJmvyptMUTe0x2mO0x2iP0R6jPUZ7jPYY7THaY7THbI/ZHrM9ZnvM9pjtMdtjtsdsj9keqz1We6z2WO2x2mO1x2qP1R6rPVZ77PbY7bHbY7fHbo/dHrs9dnvs9tjtYe1h7WHtYe1h7WHtYe1h7ZGvfvr9Em9jvgLq4fhwJU7iIm6iEZ14iEG8jfmqqId0O3Q7dDt0O3Q7dDt0O3Q7dAu6Bd2CbkG3oFvQLegWdAu6Bd0u3S7dLt0u3S7dLt0u3S7dLt1uu+ENVQ8HcRIXcRON6MRDDCLdBt0G3QbdBt0G3QbdBt0G3QbdBt0m3SbdJt0m3SbdJt0m3SbdJt0m3RbdFt0W3RbdFt0W3RbdFt0W3RbdNt023TbdNt023TbdNt023TbdNt2MbkY3o5vRzehmdDO6Gd2MbkY3pxuzZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDFLFrNkMUsWs2QxSxazZDFLFrNkMUsWs2QxSxazZDFLFrNkMUsWs2QxSxazZDFLFrNkMUsWs2QxSxazZDFLFrNkIUs88RCDeBuRJcBBnMRF3EQj0m3RbdFt0Q1ZchIHcRIXcRON6MRDDOJtNLoZ3YxuRjejm9HN6GZ0M7oZ3ZxuTjenm9PN6eZ0c7o53ZxuTrdDt0O3Q7dDt0O3Q7dDt0O3Q7dDt6Bb0C3oFnQLugXdgm5Bt6Bb0O3S7dLt0u3S7dLt0u3S7dLt0u222/79iIM4iYu4iUZ04iEGkW6DboNug26DboNumSXfy2dndh0WHuLnNnbibcwseTiIk7iIm2hEJx4i3SbdFt0W3RbdFt0W3RbdFt0W3RbdFt023TbdNt023TbdNt023TbdNt023YxuRjejm9HN6GZ0M7oZ3YxuRjenm9PN6eZ0c7o53ZxuTjenm9Pt0O3Q7dDt0O3Q7dDt0O3Q7dDt0C3oFnQLugXdgm5Bt6Bb0C3oFnS7dLt0u3S7dLt0u3S7dLt0u3S77ZadjIWDOImLuIlGdOIhBpFug26DboNug26DboNug26DbswSY5YYs8SYJcYsMWaJMUuMWWLMEmOWGLPEmCXGLDFmiTFLjFlizBJjlhizxJglxiwxZokxS4xZYswSY5YYs8SYJcYsMWaJMUuMWWLMEmOWGLPEmCXGLDFmiTFLjFlizBJjlhizxJglxiwxZokxS4xZYswSY5YYs8SYJcYsMWaJMUuMWWLMEmOWGLPEmCXGLDFmiTFLjFlizBJjlhizxJglxiwxZokxS4xZYswSY5YYs8SYJcYsMWaJMUuMWWLMEmOWOLPEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmyWGWHGbJYZYcZslhlhxmyWGWHGbJYZYcZslhlhxkyUmcxEXcRCM68RCDeBuRJUC6TbpNuk26ZZbMkejEQwzibcwseTiIk7iIm0i3RbdFt0W3RbdNt023TbdNt023zJL5S3TiIQbxNmaWPBzESVzETaSb0c3oZnQzujndnG5ON6eb083p5nRzujndnG6Hboduh26Hboduh26Hboduh26HbkG3oFvQLegWdAu6Bd2CbkG3oNul26Xbpdul26Xbpdul26Xbpdttt+z6LBzESVzETTSiEw8xiHQbdBt0G3QbdBt0G3QbdBt0G3QbdJt0m3SbdJt0m3SbdJt0m3SbdJt0W3RbdFt0W3RbdFt0W3RbdFt0W3TbdNt023TbdNt0Y5YEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSUXWTITN9GITjzEIN5GZAlwECeRbotui26Lbotui26Lbptum26bbptum26bbptum26bbptuRjejm9HN6GZ0M7oZ3YxuRjejm9PN6eZ0c7o53ZxuTjenm9PN6Xboduh26Hboduh26Hboduh26HboFnQLugXdgm7IEk80ohPTLRKDeBuRJcBBnMRF3EQjOpFul2633Nbv9yMO4iQu4iYa0YmHGES6DboNug26DboNug26DboNug26DbpNuk26TbpNuk26TbpNuk26TbpNui26Lbotui26Lbotui26Lbotui26bbptum26bbptum26bbptum26bboZ3YxuRjejm9HN6GZ0M7oZ3YxuTjenm9PN6eZ0c7o53ZxuTjen26Hboduh26Hboduh26Hboduh26Fb0C3oFnQLugXdgm5Bt6Bb0C3odul26Xbpdul26Xbpdul26XbpxiwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySxB3+v3V2UX+l4fBvFzW+vDzJKHgziJi7iJRnTiIQaRboduyJKTOImLuIlGdOIhBvE2IkuAdAu6Bd2CbkG3oFvQLegWdLt0u3S7dLt0u3S7dLt0u3S7dLvthr7Xh4M4iYu4iUZ04iEGkW6DboNug26DboNug26DboNug26DbpNuk26TbpNumSX5N3rR9/rQiZ/b+wu7QbyNmSXfH1pe6Ht9OImLuIlGdOIhBvE2brptum26bbptum26bbptum26bboZ3YxuRjejm9HN6GZ0M7oZ3YxuTjenm9PN6eZ0c7o53ZxuTjen26Hboduh26Hboduh26Hboduh26Fb0C3oFnQLugXdgm5Bt6Bb0C3odul26Xbpdul26Xbpdul26XbpdtsNfa8PB3ESF3ETjejEQwwi3QbdBt0G3QbdBt0G3QbdBt0G3QbdJt3wTPgmTuIibqIRnXiIQbyN6C8B0m3RbdFt0W3RbdFt0W3RbdFt023TbdNt023TbdNt023TbdNt083oZnQzuhndjG5GN6Ob0c3oZnRzujndnG5ON6eb083p5nRzujndDt0O3Q7dDt0O3Q7dDt0O3Q7dDt2CbkG3oFvQLegWdAu6Bd2CbkG3S7dLt0u3S7dLt0u3S7dLt0u3226v7xU4iJO4iJtoRCceYhDpNug26JZZsj1xETcxrxQi0YmHGMTbmFnycBAncRE3kW6TbpNuk26Tbotui26Lbotui26Lbotui26Lbotum26bbptum26bbptum26bbptum25GN6Ob0c3oZnQzuhndjG5GN6Ob083p5nRzujndnG5ON6eb083pduh26Hboduh26Hboduh26HbodugWdAu6Bd2CbkG3oFvQLegWdAu6Xbpdul26Xbpdul26Xbpdul26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IQbxNub1w/cA1LI5rHAS080Sc1xPPMQg3sb5Iw7iJC7iJhqRbpNuk26Tbotui26Lbotui26Lbotui26Lbotum26bbptum26bbptum26bbptum25GN6Ob0c3oZnQzuhndjG5GN6Ob083p5nRzujndnG5ON6eb083pduh26Hboduh26Hboduh26HbodugWdAu6Bd2CbkG3oFvQLegWdAu6Xbpdul26Xbpdul26Xbpdul263Xbbvx9xECdxETfRiE48xCDSbdBt0G3QbdBt0G3QjVmymSWbWbKZJZtZspklm1mymSUbWXITjejEQwzibUSWAAdxEheRbotui26Lbotui26ZJd8TJsvX4RVO4iJuohHT7SQeYhBvI7IEOIiTuIibaES6Gd2Mbpkl35/gsGyzKxzEXFsuPrPk4SZ+bivXlqmBH8t8+Pp/LVvnCr8Rvh5Zy1fcFRrRiYcYxG++39NUyza7wkGcxHTLSWY+PDTi57Zz6pkPD4P4ue2ceubDw0GcxM9t5+IzH/IqPhvqPK/Xs6Gu8Bbmy+wKc1xPzHFPYo57E79xvwfBls13hU48xM/tezxs2Xz3MJPg4SB+bvmdITvuPG+aZcedW04ny/+782/5Bjt3/FgQb2OW/8NBnMRF/NzyDlx25xWeOo2yJa+wz9RsySscxElcxE00ohPptui26LbptumWNZ/35bIlr3ATc0G5k1nzDw8xiLcxa/7hIE7iIm4i3YxuWfP5fShfW1d4G7PmHw7iJH5ueSst2/cKjejEzy3vqmX7XuFtzOuH/PaV7Xue37Oyfa8w3fK0z3x4mG45ncyHh4cYxNuY+fBwECdxETeRbkG3oFvQLeh26Xbpdul26Xbpdul26Xbpdul22y1fW1c4iJO4iJtoRCceYhDpNug26DboNug26DboNug26DboNug26ZYBkl+2s0uxcBE3Masb6MRDDOJtRJYAB3ESF/EbN79nZechPvWy89DzrmV2HhZO4iJuohGd+I2bt2Gzx/Dtg3HFxhVnzT904rfivHOaPYaFtzFr/iGPptPNeTSdR9N5NJ1H03k0UfM5B9R8ImoeyKOZNY85ZM0/3ES6seadNe+seWfNO2veWfMePHeCOxncyeBOZs1jDsGdDO4ka95Z886ad9a8s+adNe+seb88bqh5IHfy9k5muyHmkO2GhZPYboc1f1jzhzV/WPOHNX9Y84c1f0YftzMmcRE30Yi5kzvxEHMnLfE2Zs0/HMRcW84ha/7hJhrRiYcYxNuYNZ/3o7K5sTBrPncyrxSyCrON0b/mZ8s2xsIg3sbNI7R5hDaP0F7ETTSiE3mENo/Q5hEyHiEbxEnk+WA8H4znQ+ZD3mjM5saHmQ8Pv3HzRmM2N/rNmWU+PNxEIzrxEIN4GzMfHva9q4O7B0AjOvEQg3gbcfcAOIiTSLegW9At6BZ0C7oF3S7dLt0u3S7dLt0u3S7dLt0u3W67xe9HHMRJXMRNNKITDzGIdBt0G3QbdOM9xxh0G3QbdBt0G3QbdJt0m3SbdJt0m3SbdJt0m3SbdJt0W3RbdFt0W3RbdFt0W3RbdFt0W3TbdNt023TbdNt023TbdNt023TbdDO6Gd2MbkY3o5vRzehmdDO6Gd2cbk43p5vTzenmdHO6Od2cbk63Q7dDt0M3ZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSXZa+n5jDV7LQsPMYi3MbPk4SBO4iJuIt2CbkG3oFvQ7dLt0u3S7dLt0i17LfOqGL2WDw8xiNV14ui1fJhunjiJi5huJ9GITsy1RWIQb2NmycNBnMRF3EQjOpFug26DbpNuk26TbpNuk26TbpNuk26ZJTf37MuS8z2U9+y1LBzESVzETTSiEw8xiHTLvivsevZdPZzE9TqAHL2WD42Y3UJ5YLPv6mEQb2P2XT0cxElcxE00It2Mbp57NhNzd3Zi7o4lGtGJp/HkCLnikyPk2s4mGtGJhxjEb3+/jgTPnsjCQZzERdxEIzox3XLFEcTbeH/EdMtjfCcx9xe4iUZ04iF+bt/vm3p2P56vp8Gz+7HwEPO/3Ym3cfyIgziJi7iJRnTiIdJt0G3SbdJt0m3SbdJt0m3SbdJt0m3SbdFt0W3RbdEtK/Z7AOrZKVnoxEMM4m3c6RaJgziJi7iJRnTiIQbxNhrdjG5GN0u3m7iJ9toCPTslCw8xGr/P+fM9IfXsfjzf80LP7kfDit2Jhxiv68+z+/Hh+RGzQ9ASJ3ERN9GITjzEIN7G7H58SLegW9bxzMLJip15EmTFzvwPsmIfDuIk5gi5oKzCmbt+b2F2KRYO4iQu4re/361rzy7FQiceYhBvY9bxw0FMN09cxE00YrqNxENMt2/F2W54vk5Jz3bDQifmj+WCsiAfVuOmo93w4SBOYo57E78Rdq4iWwhXTjJbCB8O4nw9nI4WwoebmK2fuYpsIXx4iEG8jdlC+HAQJ3ERN5FuRrfvYvrsXOZ32Xy+X9f1bAs833Npz7bAQiM6MUfIFZ8cIdeWH4sPN9GITjzE3N/c6vxYBObH4sNBnMRF3EQjpluuOD8WHwbxNmaRWR7jLLKHn9v3286erX7HcvFZZA9vYbb6FQ7iJC7iJhrRiYdYrcC+uhXYV7cC++pWYF/dCuyrW4E9/x6u5THOv4db6MRDDOJtzFbgh4M4iYtIt0m3rELL6eQH4Pfbzp5NfefrHPBs6ivcRCN+I3z9v56NeufrEfBs1CtcxE00ohO//fWcWX6oPbyN+aH2cBAncRE3Med7E514iEFMtzyEeXH6MN08cRIXcRNzbbk7WZsPDzGItzEvZB8O4iQu4ibS7VSrtWejXmEQq9Xas1GvcBCzsTtXke3/DzfRiE48xCDexmz/fziIdLt0u7lneSyyjr9fD/Jsvjtfy4Jn813hJC7iN8L3hi/PhrrzdS94NtQVDuIkLuImfvv79TR4NtQVHmIQb2NeyD4cxElMt5W4iUZ0YrpFYjRmxX5Ptj3b4U7k4vMy9GEQb2Nehj4cxElcxE00It3yE9JykvkJ+fA25idkRma2wxVO4nfkM8yzHa7QiE48xCDexmyyfziIk0g3p1vWZuR8swojj3xW4feLQJ7tcIWLuIk5Qh6W/ITMGyrZ4lY4iYu4iUb89je/v2WLW2EQb2N+Qj4cxElcxHTLsy8vTh868RDTLXcnqzAxG9/Od7vJs/GtcBIX8XPLb/nZ+FboxEMM4m3Min04iJO4iHTLT9Ms3uyBKzzE/HUQ/Le3MT9NH+Yvn+Qq8tP04SJuohGdeIhBvI15pfuQbotu+Rmbd3Kyxe3k7aZscYvvNVmeLW6FgziJ9mEet682I7+0ZdvaQ/sRB3ESF3F/mNtnRnTiIQbxNvqPOIjpNhIXcRONmG55hPw0nhw3EgdxEhdxE42Y4+b+nkP8VpG3b7JB7eFX3ZG3ZLJBrfBzy9ss2aBW+LnlvZVsUCv83PKeQjaoFaZbbkncxptuucw7iOmWp8ZdxHTLBV0jplsu6B7i55bf3LNBDZgNapFf4rNBrfBzy2/C2aBW+Ll9jReeDWqFn1t+Vc4GtcJ0s8TbOOpXyzwb1AoncRE30Yjp5omHGMR0+1acDWqFgziJi7iJRnTiIQaRbotu3xV05JftbEWL/B6br8aLlTv5VXfhbczqfjiInO/mfDfnuznfzfluzndzvpvzNc7XuDtGN6Nb1jwWlNWNBTnn65xvVvfDRdxEztc5X+d8nfN1zvdwvofzPZzv4XwPd+fQ7dAtqxsLyjrGgoLzDc436/ihE3k0g/MNzvdyvpfzvZzv5Xwv53s538v5Xu7Opdttt2wvw4KykQwLykYyTDIbyQqD2GdfNpIVDmKOuxIXMT8L0xifvEAnnsaswu+XAjybwyJvfGRzWP72pWdzWKETvxEC/20Qb2N+muYFXDaHFU7iIm6iEZ14iEG8jZtum25ZhXm7KdvAIm9uZRtY5A2rbAN7mPX2cBC/EfIGUP6N0Ni56/lp+vA2Zr09HMRJ/PY3b0Vkw1ehEZ14iEG8jVlvD9MtT66st4eLuInplkco6+1hup3EIN7G/Ix9OIiTuIibaEQn0i2/m+alcLaBPczvpg+/o5lXutkGVriI37lzc235q+kPnXiIQbyF2QZWOIiTuIibaMTcs+/kytauyHti2doV32+GeLZ2FW6iEb8R8utZtmtFfhHLdq3CRdxEIzrx29/vN04827UKb2N+Fj4cxElcxE1Mt5noxEMMYrp9xzjbtQo/t7yxlO1ahZ+b549lxeYdomzXyl++9mzXKjzEIN7G/Hb7cBAncRE3kW5Gt6z573dAPNu1Cm9j1vzDQZzERdxEIzox3XKrs+Yf3sas+YeDOInff3vy7MuKfTiIk7iIm/jNLO/vZLPVw/wszDs52SpVaMT8b3PP8rPwYRC/FoD8zoBWqYeD+LUA5FcjtEo93MSvBSC/RqFV6uEhBvE2ZnvDw0GcxEXcRLoNuuXVa35jzfanyPtG2f4UeQMo258KjejEb4S8Q5QtTRG5+Ky3h5toRCce4re/+VGXLU0Ps94eDuIkLuImGjHnexMPMYi3MT8385ogW5oK0y13J69TA//tJhrRiYcYxNuY9fZwECeRbnhlQ+46XtkAdGKeO/hvg3gb8cqGXAVe2QCcxEXcRCM68RCDeBuDbkG3rM38mMk2pchPvWxTipsHK69pgXlN+3AQc4Q8abM285ZMth4V3ocnW48KB3ESv/39mlVOth4VGtGJhxjE25jXtA/TbSdO4iJuYrrdRG/M1zg9/BvhfrFysp2ocBON6MRDDOJt/D43CweRbotui26Lbotui26Lbotum26bbptuO91+iem2Eo3oxEMM4m20H3EQJ3ER6ZafmyPnkJ+bDw8xH/bnfPOuMDDvCj/8PqV/edzyrvDDRdxEIzrxEIN4G7OR4SHdDt1O7lmeXCd3J8/1k7tzPowfcRAnMUfIwb7avFj8V5sPv9osHMRJXMRvf78bVifbiQqdeIhBvIX5OrbCQcz5RuIibqIR020lHmK6WeJtHD/iIE7iIm6iEZ14iHTLu8LfvauTDUmFg/gdzZn/bd4VfriJ37kzcxX5PfbhIQbxNub32IeDOImLuIl0W3TL6v7uGJ5sMrojtzrr+LsLeLLJqNCITvxG+O4CnmwcujMPbNbmw000ohMP8dtfbJ/dxq82CwdxEhdxE42Ybr/EQwzibTzplkfoDGK65UZlbT50Yo6b25cV+zDHzY3Kin04iN+4K42/69/CTTSiEw8xiLcxq/vhINLt0u3S7dLt0u3S7dLttlu2KRUO4iQu4iYaMd1G4iEG8TZmdT8cxOx+zMGyeCf+10MMYp+0+a60+927OvlWNJyI2aZUaMSc5Eo8xCDmJL9TLtuU3o/lR/PDSaTbotui23LiIQbxNm66bVpkxX73z052LBUeYk79JN7G/OR9OIh5NCNxETfRiOl2E79xdx6WrOOHg/iNu/NYZB0/3EQjOvEQg5huufis44eDOImLuIlG9MYs3p0HNst05/ZlmT40ohMPMYg5ydzULNOHgziJi7iJRnRiuuUByDJ9eAuz0alwECdx1WHJRqdCIzoxz50v+7KPCbuTfUyFi7iJOdhN7C3JjqWHWZAPv3Et3fIK+uEifuN+N6xOdizVjznxEOk26bbolmX6cBIXcRPptmiBC+RcGy6QgZO4iDn1mZgXGLmgHcS+VMuWpvvdjDvZ0lQ4ibklub9ZkO/HjOhEuhndjG7+Iw7iJC4i3ZwWWYWWW5JV+HAQc+oncRE30YjfuJanZ37GPgzibcwytdzfLFPP6WSZPjTiN67nuZNl+jCItzHL9OEgTmK65dHMMn1oRCceYhBvYfYxFeZgOzF/zBKDeBvzY/HhIE5iTvIkbqIRnXiIQbyNWaYP0y0SJ3ERN9GITjx1WLJ5qfA2Zpk+zHPHE613Jz8sHx5iEHOw79TIPqa3JVmQDzfxG/ekW35uPjzEb9zvTuTJPqb3Y8YDYDwARjejm9Ety/ShE3m4jYfb6Oa08LqhcvKtXYVOPMScep5cp2+oZPNS4SJ+k/zay06+y6vQibklub8n+GN9+yYbnQrpFnQLuuHGEtCITjxEul1aZBWeXGZW4UMj5tTzpM0qfBjEW5h9TPe7R3qyj6lwEhcx3W7iN+53P/Vkx1Lhbcwy/W6XnuxYKpzERdxEIzox3WZiEG9jlunDQZzERdzEHOw7sNl6dL9HqCdbjwoXcRON6MScZG5qFuTD25ifmw8HcRIXcRPTLQ9AlunDQwzibcwyfTj6sGSZPlzETcxzxxNv705+WD4cxEnMwfLUcG5JXr0+DOI3bn6FyY6lwkH8xr155A8PwOEBODwAh26Hbodu+bkJzM/NhzzcwcMddAtaZBVid+I2ZkE+HMScep5ctx4jHLQePTzEb5LfveKTrUfAbD0qzC3ZifXQ4qD16OEmGtGJhxjE25i3gh8OIt0GLbIKM16zs6jwNmYVfo16JzuLCidxEb+jmfegs7Oo0ImHmG7fyZUvufq7y/ZLnsJLeCfnnL9SbXbhIxzCl/zVazN8Z/IUXsJb2IRd+AgH2TBmHmvDz+aWmgsf4RC+ZP8JY8653T6Fl/AWNmEXPsIhDN88ROcnPISn8BLewsZjd1z4CAc5yzg/CrM1qbYttrAJuzCGzFPpylbdITyFc/y83M9upGYTzvHzpno2JPXPyiG6PET5IqzmITyFl/AWNmEXPsLihV6IlbiIm2hErGMmZxvBt2VoVHo4iDnZvDmd/UvNWxibhP/e+aOHGEQ6LjouOq5JXMRNNCLdFi1Qw3lf+6CGHy9hzP8km7ALH+E8yHk/Obuaiu0nPIThe5Nz/Lwde1Dnj49wjp/38A7qHIw6fzyEp/AS3sLwzQONOn98hEP4klHnj4fwFMaYuecHP5t7Gz/hITyFl/AWxpxzz1HQj49wCF8yCv3xEJ7C8M1jhEJ/bMIufIRD+PaxCxT64yE8hXG+efLpfcvWpuZLHj9hjHmTuVfZ39Tswjl+3ojOxqfmS545ft5qzo6o+tk5hZew+E7xneI7j3AI89zI1qhm8V3ilVWdN0DR/PQwiLcRn915wxt9Thu4iUbMyea97UBxPw5hbFJuvP36R20QJ5GORkejY/ZePDzEIN5Gp5vTAkWc97cDRfz4CGP+J/mSUcSPh3Ae5Ly3HfiwfryFTRi+eQKi0POeaaDQHw/hHB8HCIX+eAubsAsf4RCGb+4JCv3xEJ7CS3gLm7A3XxRx3tS9+FTOm6AXhfvYhF34CIcw5vzt+UVBPx7CU3gJb2ETdmH4RnIIXzIK/fEQnsKrj91FoT82YRfG+faF2UURY99wof54CW9hjHmTZa9wQQ5GUT/O8fP++MWH+eMlnOPnjfO75RhtOUZbjtEW3y2+Jr74MH88heXcMDk3THxNvPABnnfGLz7A8yrs4gP88RLewibswkc4u61hdRuzk/HhIE7iIm6iEXPc3F6UfF5bXZT84yE8hbGcHAYl/9iEXfgIh/Al57fw/LhC69XDSVzETTSiEw8xHgYasr4Vx+/Xq4kfwuDxFjbhXk38fkc4hC8ZYfB4CE/h1TMbm2hEJx4iFzRu4/wRB3H3iqesBqX++AiHsKxmyWqWrGbJatYS3sImzAUtLmhxQYsL2lzQ5oL2JHL7NrcPv6aQK96ymn3J9hMewrIak9WYrMZkNSbnhMk5YXJOGBfkXJBzQc4FORfkXJDzfHBun3P78LuCM3EQJ3ERsRRPzl8LXIlBvI0vCU7yEJ7C2KdI3vxRIzqRjkHHoGNmwMNBnMRFpNulBa7avydqMfCB/3gI5/y/52AxUPuPt7AJ53H+nm/FQO0/DuFLRu1/Pfgx8IH/PdGJgQ/8xyaM8S35CIfwJeMD//EQnsLw9eQtbMIufIRD+JKRAo8xZiTjZ3Nv8YH/+JLxgf94CE/hnPPJPccH/mMTduEjHMKXjFp/nL4njxFq/fES3sIm7MKHxw61/viScVHwGGv8JRv3DR/4j49wCGMteS4d2Stc1D/ewphz+uKi/vERxl7leXLkGIUco5BjFOIb4hvii0/+xy4s50bIuRHie8ULv86fS8ev8wOdeIhYx3c+4mVT31OLwMumHi4iDuxJNmEXxiZFcvBHb2P+9v5DOg46Djrmb+8/NKITD5FukxYo4gPewiac8/9u68dEET8O4UtGEX8PzWLio/zxFF7C6fv9VkNMFPr3mCgmCv3xJaPQv8ctMVHoj6fwEt7CJuzC8M0DjUJ/fMko9MdDeAov4S2MMfO44woe+4/CfbyEt7AJu3DO+eaeo6AfXzK+vT8ewlN4CW/h9L15jFDoj49wCF8yCv3x4LFDoT9ewlsYa/wlX+4bvrE/HsJTGGvJc+nKXuEW3OMQxpw/34UP88dDGHtlyTxG67eFTdiFj3AIXzI+zB8P4SksvkO88BadnCbeopOIt+gABxHr8GR7b+qJhRfmAA8RB/YkXzKK+zE2KZJn/2i+/OrhJtJx0XHRMV/X8fA25mt3Hg4i3TYtUMQ3NwZF/PiSs4jH95wusnGseQov4Z08k03YhY9wJH8nYLaK/XFuvk/hJYzxc/5uwi58hEP4ks9PGL55oM8UXsJb2IRd+AgHOTBmHvfAz+behgsf4RC+5PsTzjmP3PMs6OIlvIVN2IWPcAin7/fAKrKZrHkIT+ElvIWtj12+MKv5CAd5YI2/5NX7lt1mzSbswljLdy5lb9nbq2wua57CmHP6zi1swtgrSz7ysyHMY5RdZs3iu8R3LeEtbMIuLL5LvPD6u9wqvP4OuIlGxDo8+YuL/CK18aY74CDiwJ7kJbyFsUm58fm2u/ejhxhEOjodnY542x1wETfRiHRzWqCIR24MivjxEs75T/z3JuzCRzgP8swTOT+tH+endfEQTt+ZJyAKfeZJhEJ/fIQxfp5cKHQwCv3xEJ7CS3gLwzcPNAr98REO4dtsKPTHQ3gKY8xIxs9+e2so3MdDeAov4S2cc857J4aCfnyEQ/iSUeiPh/AUTt/vgVUYCv2xCbvwEQ7h28fOUOiPh/AUxhp/yYf7tkL4kvdPGGtZybJX24RdGHNO3x3Cl4wP8+9ec5jJMTI5RibHyMTXxNfEFx/mj0NYzg2Xc8PF18UL75fNUyzfk/cwiLcRH94L/MXF92gmrF87G9avnQ1DcS/wEQ5hbFJuPF49m/8zXj0LnEQ6Bh2Djnj1LPAQg3gbL90uLVDEKzcGRfz4COf8d57gKOJkRxE/HsJ5kL8Hb+H4tH68hU04fb8XuIaj0L+HSeEo9MdDGONb8hLewibswkc4hOH7HWhHoT8ewlN4CW9hE3Yyivh7IBfochvfQ7JAl1uxCbvwEQ7hnLPlnqOgHw/hKbyEt7AJu3D6Wh4jFPrjS0ahPx7CU3jx2KHQH5uwC2ONX5ih++3tG67UHy/hLYy15Lnksle4IgejqB9jzumLD/PHSxh7lefJkWN05BgdOUZHfI/4hvjiw/zxFJZzI+TcCPEN8cIHeN7UR/vbyHvzaH8rXsJb2IRd+AhnluShyNdmJmbzW+EgTuIibqIRcT7d5EtGzT8ewlN4CW9hE3bhIyy+Q3yn+E7xneI7xXeK7xTfKb5TfPM1t1+TUmSP3MP8ew0PBzE982o62+HylfmR7XCFh5gLyivTg0AAIxAe54LyAUW2zL0fzUv5h5tIx03HTcd8k/XD25jX9w8HkW5GC3yS50MStMYVXzI+yfOBBlrjiqfwEs4Dkg8o0BpX7MJHGL654QiBvOmOFrjiJYzx82AiBB678BEO4UtGCDxO35MHGiHweAlvYRN24SMcZIRAPrhAC9zIhwlogSs+wiF8m9ECV4w5W/IUXsJb2IRd+AiHMHy/Y4Q2ueIhPIWX8Ba2PnZonys+wkFGAORDG7TGYd/QGldswi6MtXznElrg3l7hav3xFMb46YsLgMcmjPFv8pGfDWE5Rlt8t/hu8cUFwOMtbMIuLL5bvPDhnveBAx/u+Xwh8OH+2IRd+AiH8CXnN/cJHMRJXMRNNKITT2P/aaXIhrnCSVxErCWPb/9tpYj+20qRvXIPUdT5oAStcsVTGBuVJ1hezb8fNaIT6Rh0DDri7ysBB3ESF5FulxYo8HzIgva44iGM+Z/kJbyFTRgHOpKPcAhfMgo8b5ijPW58vzoUaI8rNuEcPx+CoD2uOIQvGUX9eAhPYfjO5C1swi58hEP4khECjzHmTsbP5t6ikB9fMgr58RCewphz7jkK+bEJu/ARDuFLxpX8Y/jmMUKxP17CW9iEXfjw2KHYH18yPugf43zzZOO+4UP88REOYYyZ59KRvcKH+OMt/I0/8/5vvmis+QhHcp4nR45RyDEKOUYhviG+Ib74EH/swnJuhJwbIb5XvPKvpuVnBf5S4kOsJM+8e4RD+BbffGVZ8xCewit5J29hE4avJR/hEIbv+nj8hIfw/JZyExdxE43oxEMM4m38kqBwEHPcXOQ0ItbiyUc4hC95/YSH8BTGHkbyFjZh+ObM1hEOYfiej/dPeAjnHuZ25t9MfLiJRnTiIQbxNubfTHw4iLma75eoLjrkil04V/M977nokCu+5MyBOfII5AV/ce7iSK+84C/ewvDNM9Fd+AiH8CWfn/AQhm+euWcJb2ETduEj/O2l5RK/qNg7z4cvKbblAr+gKNxEIzrxEIP4HaOdO/FdFxQO4iR+bjvPk0yQh0Z04iEG8RZml13hIGKHPNmEXRg7hP8+hC8ZGfE9+LkDGfEYR+YmL+EtnL7fDfGLHrviIxzCl5xXDcVDOH2/S8mLHrviLWzCLnyE/3zXd1F486Vo6+SqvrRY32XXzZeiFW6iEZ14iEG8H+ZOfylROIiT+LllHmbnXaERnXiIQbyNX0YUDqKcESZnhMkZYXJGmJwRJmeEyxnhcka4nBEuZ4TLGeFyRricES5nhMsZ4XJGHDkjjpwRR86II2fEkTPiyBlx5Iw4ckYcnhHBMyJ4RgTPiOAZETwjgmdE8IwInhHBM+LyjLg8Iy7PiMsz4vKMuDwjLs+IyzPi8oy4fUbk69YKBxE7NJNN2IWPMI7MSr5kZMTjIfyt5rujcLMtr3ATjejEQwzibZw/Ig64J29hE3bhIxzCuZyvbf2iQ694CE/h9P2eN1506BWbcPqu3DpcSjwOYfh+H3bo3Jsr14VLiZVz21N4CW9hE3ay4WdP8hLGz0ayCeNn8/T4wmD98J8H8TZ+SVA4iJOYI+/cMZT1zp35ynrlVUm24BUOYo6Rs/hKunATjejEQ4RdbnJ+a3ic3xpmfgyj9a54CmPaeVCyevPSEN12b2/uT3gIT+Hc753HM2/5F5uw7De+KjwOYfqiC68YY55kE3bhHDOvfNBhV3zJKN/HQ3gK51q+xy934SP+sQm7MHw9OYQvGR/x368u3IWPeE8vfMQ/XsJb2IRd+AiH8CWjvr878RdNesXwXclLeAubMHxzLajvxyF8yajvx0N4Ci9h+OZxRH0/xvHNfdvwBYfwJdtPeAjDK88l5MFjE06v7072RSNfcQinV35tW7g4eJxe+QUFDX7FSzh9vw7Miwa/Yhc+wiF8ybg4eAzfPA9xcfB4CW9hE3Zh+OY582Ij1/tiI/+bFxvgJbyFTdiFj3B0Bq+XM8kvZ8BDGL45t5cz4C1swi58hEP4NqMJsBj75slb2IRd+AjjeN3kS0bmPB7CU3gJp29enaEhsNiFj3D6fjd670bmgJE5j9M3r8zQKFi8hOF7kuEbyfDNuSFzHofwJSNzHg/hv/HzCiTbAR9502mKpluEGv9u2t2NGn88hP/WNXO1X7U/2k3W5E2nCLV88xxAzX43U2/26S38F9bkTd9ncB6Dr1Yf3aL8uAeNptkEF/AWzp2/OT4q9PEho0JvHjVU4s1dQiU+/uaba0Ad3jyuqMPHIXzJqMPHo3bo9u7e3t3bu3t7d2/vLmos9xR9dthTQ419N2yvocYeY+U32YW/Oa/vBunNt8blhUt26IG++no0mmbTavIcJ+eTdbLydiP+bmX+F/mCctBsWt/7wJN2kzV502mKJrjkOFkVxSN5J0/hJYzZWjLG+Y4rOumKv/nmevbkHu0lvIVNGKOf5CMcwpfH4NUceAiLr4mvia+Jr4mvia+Jr4mvi6+Lr4uvi6+Lr4uvu/B5lWHOCjBnBaALr3gIT3JgBjmbWMJb+KuKPLe/Gnx0mqLpFn2192g0zabVtJva47bHbY/bHrc80Ea38iYo2uiKp3CuKG92oo2uOPc0b6Cgja74CIfwJY+f8BCewkt4C4vvEN8hvkN8Ud95EwftdcVDeAov4S0M39y36cJH+Mv+3LV5i9avaTTNptWEMW9yzjlv9KC9buXNGrTXFU/hJZxzzlsRaK8rduEjHMLfmZEzMLju5CE8heGau4wqf2zCcM3dQZU/hiu8Ltl/wt9+gWbTatpN1uRNOWbetUBz3cIu52ftyppHc12xCbtwzjk/49FcV3zJ+RlcPIS/T54cJe+zg3bTd98755Q32UGnKZpuUd5gB8HFkqfwEnZhzPY7Inh7XPH3KflLmk2rCfsTySbswrk/778P4XTM2aKxrjhnnjuAxrqVn8horFt58wGNdSu/IaCxrtiFMX6uAtWb3/zRKLfyWyIa5dbXrHjRKLcs54bqzU/Lg89lS198Lj8ewjlOfsPP9rc/Tt/8xrvy2gD9b49RsZbzQcXmt328Mq54CW9hzDPnjIp9fIRD+JJRs4+H8BTO8T33ATWYdwfQ27byjgB621Z+20dvW7EJu/Alo9Y89w219hjj5B6ipvLbPnrPVn7DR+9Z8RaGb+5PuPARDo4fl/97XsEWD+EpvLgPdwubsAtzvehPwxrRn1Y8ha3PH/ShrbzLgD60lXcT0IdWfMmoncdDeAov4Zx/fntHH1qxC8N3JsM314KayrsJ6EnD3Wa8xg3nPF7jVryEMT74CAcZNfX1ql30nuFhQ/aeYXfyL+6AMEbuE+oscn2oMzDq7PEQzjlGrhV19ngLm7ALH+EQvmTUU+T+oZ7y2zf6yFZ+yw7UU36bDtTT4y1swn9zyLMrm8YeRdMtyr9sBxpNs2k17SZrao/THqc9TntEe0R7RHtEe0R7RHtEe0R7RHtEe+APwSbtJmvyptMUTffRxV+ATRpNs2k17SZr8qbTFE3tMdpjtMdoj9Eeoz1Ge4z2QD3lHRW0gxVP4TxP8psx2sFW3nVBO9jKewJo+1r53R9vQlv5HT9bvRz/qzV502mKplv01dGj0TSb4J4zREXkd/Rs4MrcyPatR6NpNq2m3WRN3nSa4JL7hpoC49rw8bf2nd/i0KK189s8WrR2fptHi1bxJed3uuIhPIWX8BY2YRcW3yO+R3wDvrnGGMJTeAlvYRN24SMcwpd8xfeK7xXfK75XfK/4Xvha8hEO4Vv8vWz5p2KogIVDYKwD8fWcvv/9NuYLUB5+5xhGyRegPFzETTSiEzHHmyILcH/P3z6xVGwVuQ/fN+JPuIqjIlRcEXlx2WKomCqWiq1CZ7B0BgszWBCh4orYmAH2YA8VmAH2d2MGOBobM8BWbVPhKnIGE9PJkGiRM/gepH9vlM4ZTEwnX3wK/3zx6cNF3EQjOhFj7xT5gbsn/j9Ih4k15EduC1ORa/i+kH7iqAgVVwTCowR8sAmIg4XzBXmwsAkIhBJXBCKhxFAxVSwVW4WpwAyw2UiGEqECM8BhQDiUGCqmCswAe42AKGEqvqOD7cCfrAUG8X5/DeDD7OAqHMRJXMRNhJ9BuIqjIkSMoQKzdwhTgdEOxFERKv7WcHMrs1+rcBAncRE30YhOPMQg0m3RbdFt0W3RbdFt0W3RbdFt0W3RbdNt0w1ZsXAskBUltorc1/2DcBVHRe7rfkNfEciKjUOW32ZbTBVLxVaBGeDImqvADHAwDTPArJEoO09VdHy1GCpyBoYlIGtKbBXfvmMy+SdNHh5iEG8j/hQYEGMPiFyDYXuQL7YgQsUVgXwpkWswDI18KbFUbBWm4lsF9hDpYthDpIthc5AuTyBdHAvAe5jwI3gyi7Xg6VD+7xNPYB8P4Zyub4ilYqswFa7iqAgVV8T4qRgqdAZDZzB0BkNngEBxgzgqQsUVMX8qhorVe1ZdX2ATRncG+AiHMOwgcF1SYqiYKpaKrQILDghXgQXjAOK6pMQVgQYR/AgaRB5P4SW8hU3YhY9wCF+yia+Jr4mvia+Jr4mvia+Jr4mvia+LL2LFL8RUsVTkhp8fhKlwFUdFbvgZELnhB+fIwVMQ8BCewml/FsRWYSpcxVERKq4IZFKJoWKq0BmEziB0BrghiCXjhuDjEL5k3BB8PISn8BLGTXCwCbswFo6ax7ehEpcCXWwtsHCDmCqWCleB0bJs0L+Wv3rziaFiqlgqcrT4QeRokccbXWkthoqpYqnYKvKgxIJwFUdFqLgiEEQlhoqpAuu5EFuFqXAVmAE2HkFUAjPA9uILUomhApUJXsJb2IRd+JBxURNPYC9xNHHpgktctKK1cBVHRa7k4mji0uUJXLqUGCqmipzBxcYiY0qYCldxVIQKzADrwdekEkPFVIEZYD2ImRKm4puB/TDrjBn74bTLmGlxU2TKoXetxUiBiWbMtFgqtgpT4SqOilBxRdyfCp3B1RlcncHVGVydwdUZXJ3B1RlcmQH62VoMFVPFUrFVmApXcVSECp3B0BkMncHQGQydwdAZDJ3B0BkMncHQGQydwdQZTJ3B1BlMzGBDbBWmwlV8M0CaogWu+JIz1oqH8BRewlvYhLHAzKO9sQyHmCqwjAOxVZgKV3FUhIorwuATEHpYTDfFjopQcUU4DsuFGCqmiqVCTwzXGbieGK4nhuuJ4XpiHD0xzpC5nalCT4yjJ8YxmduLqCeOCp3B0RmEzkAjamtEbY2orRG1Q0/N0KMQehRCj8KLKMzt6lG4ehQ0orZG1NaI2hpRWyNqa0RtjaitEWUvojbEUDFVLBVbRc4At2nRLNgiZ4CbpIaIKnFFIKJK5AwGhkZElVgqtgpT4SqOilCBGWQ54/V+LaTM8FI/w51ZvNWvhalwFXLy4c1+LeTQowuxxVAxVSwVcujzj9hSuIqjIlTood8/FUPFVIGVHghXcVRge7FvCC7cnUbHYouhYqpYKrYKU+EqjghE2sTJh0grMVUsFemDm+VoU2zhKo4KXMFi2bjqegJXXSWGiqliqdgqTAV8MFF8hXsCX+FKDBVY6YTAaJg1bk6XOCryyOGxgCGenkA8lcCOon6ufCuxu1RsFTqDqzO4OgN8Zysh34vQIdliqJgqtgp8HTSIUHFFIHdwTwZdkC2wiQGxVGwVOF0uhKs4KnJ78b0e3ZAlkDslhoqcAZ4XoCOyxVZhKnIG+ErsiBo8FcAbCFsMFfDBhiBqSmwVpsJVHBWhAjPAjiJqSgwVU8VSsVWYCheBdMFtb7RE2sLGI0NKmApXcVSEilzCxiFBupQYKqaKpWKrMBWuImeAG+94dWGLKwIXTCWGiqliyQHGBVMJU+EqsOzMEPRQ1o4iUEosFVsFFoeTL3QTEShPIFBKYAmYAa53SiwV2EScVVcP49XDePUwXp3BlRmg/bLFUDFVLBVbhakQU/RZ4mIdfZbFU/gbF9c67wWGj00Y54ZDHBWh4opAlJQYKrCxsEeUlNgqcgIb7MJHOIQv+b3hFDyEp/AS3sLiu8R3ie8S3yW+W3y3+G7x3eK7xXeL7xZfXNPgeRQ6PVtcEbiThOcvaPZsgQc72HzcYyqxVeB2FY447jGVyBngGRZ6RFvkDPA4Cm9JbDFU5PIxG7wn8fEWNmEXPmTkDR54oZnU8CQL3aRm2DGkSglXcVRgJVg9voY9ga9hJYaKqSJn4NgKhE8JU+EqjopQkTPAcyJ0qbYYKqYKzMAgtgpTgRlgExFLeCaAtyy2yBngAQH6WFvkDPC0AJ2sLZaKrcJUuIqjIlRcEbgcKqEzGDqDoTMYOoOhMxg6g6EzGDqDoTOYOoOpM5g6g6kzmDqDqTOYOoOpM5g6g6kzWDqDpTNYOoOlM1g6g6UzWDqDpTNYOgNcKOFxCnpqWwwVUwVmYBBbhalwFUdFqLgicD1VYqiAj0NgtAMRKjBa5mQgpUoMFVPFUrFVmAr45Mct/vBxbeLR3UFWldgqTEXuDr44BbKqRKi4IkLPkNAZhJ4hoWdI6BkSeoaEniGhZwiy6k009Ay5eoZcPUOu7gGyCt+I8HeSW+QMAj7IqhJHRajAHuR5gFdGthgqpoqlYqswFa4CM3CIEPHi6ULA9EBMFUvFVmE8jHibZIujIlTIoUcLcYuhQg791Xi6Gk9X4+lqPF2Np6vxdDWersYTuo8Nj6LwpskWpgIrxb4hhPD0CW+hbHFFIIRKDBVTxVKxVZgK+AyIKwJRU2KogA9Wii91JbYKU4FLjwVxVISKK+JdRD0xVEwVS8VWcaolJ9udC28j/tgbdgJ/7O3xFMYCMSLyqoSpcBVHRaj4zHHOf2lVOIjY3A2xVGwVnzfuAb6/6vz4CIfwJePPwj0ewlN4CW9h8b3ie8X3iu9t34GO5+IhPIWX8BY2YWy1QRwVoQJn80mBhCqBszkgpoqlIv0dbMIufIRD+JKRQF9r/ie+gTzPrYFeac8HtAO90i1CxRWROeNvK/IyqMVUsVRsFZjBhnAVR0V26DzPS0ZH0uPsDMJa0JH0eAlvYRN24SMcwpeMjqTH4mvia1g0jr9h0TiWZipcxVERKq4I/6kYKqaKpUJn4DoD1xm4zsB1Bq4zODqDozM4mAFOsLNUbBWmwlUcFZgBzt1zRcRPRc5gYOMztVosFa4Cv5iajF6jx0N4Ci/hLWzCLpzrGDg5M4Z8vP/PpcAfoW4xVEwVS8VWYSpcxVERKnQGQ2cwdAYDMzCIpWKrMBWu4qjADCbEFTF/KvL+zAVP4SW8hU3YheEdEKHiikCEvZ9BhJWYKpaKrcJUYPUOcVSEipwBggJ/+rrFUJEzQL6hUbv/P38DLGxrvk3zIX74ialiqdgqTIWryOlPLAxhVOKKQBiVyBksTBJhVGKpyBksLAxhVMJV5AwWzguEUYkrAmFUAjNYEJgB1oPIWTgCiJwSR0WogE9+VKNH2xfOG0TOxnoQORuzRuSU2CpMRc5gY9Z5qdQiVFwRmVO+UZ0XppjohSkmemGKQ5L55PYGcBVHRai4FOj0bjFU5AzyAneg17uFnKxo725xVIQKKQq0d7eAqUFMFUtFLjtvAg60d7dwFUdFqLgiEEolhoqpYqnQGUydAa6ustl+oN+7Rai4IhBNJYaKnIFjrxFNJbYKU5EzyBuUAx3fLUJFzsAxa0RT3qAcaPlugRkExFKBGWCiCK0SruKoCBVXhP1UDBVTxVKhMzCdgekMTGdgOgPTGbjOwHUGrjNwnYHrDFxn4DoD1xm4zsB1BkdncHQGR2dwdAZHZ3B0BkdncHQGR2dwdAahMwidQegMQmcQOoPQGYTOIHQGoTMInQGS7yAP8hKtxVSxVOCCE2zCLnyEQ/g2ox28eAhP4Rw/b8uP9WLtiRwp78UM9IK3GCqmiqViqzAV6ZP38QZ6wd92oRf87QN6wVtsFaYityW73gd6wVuEiitiyYmBXvAWU8VSsVWYCldxZG6IqBJXxP6pGDI3RFSJpUJnoBG1NKKWRtTSiFoaUUsjCi8wremYHgXTo2B6FBBRb26mR8H0KGhELY2opRG1NKKWRtTSiFoaUegir+kgokroUXA9Cq7nASKqhB4FjailEbU0opZG1NKIWhpRSyNqaUShi7zmFnoUQo9C6FEIPQqIqHyCMdBF3gJ74BCh4op4EfUEZoC5vYh6YqnYKkyFqzgqQkXOIG8vD3SRt8CzffBmUKBV3PMe/0CreIujIlTIwd7jp2KomCqWiq3CVMjBRqt4i1AhBxut4i2GiqliqdgqsNIJESquCMRbYN8Qb4FZI95KLBVbhalwFUdFqLgittzMQM94i63CVLiKowI+DnFFIMRKYKUHYqpYKrDSgDAVruKoCBVXBEKsxFAxVSwVOgPXGbjOwHUGrjNwncHRGRydwdEZHJ3B0RkgxAKnGELson4QYiVCxRWBECsxVEwVS8VWYSp0BmjkxGmNXwN+fMnvFQPgITyFs1EFY6KD87EJu/ARDuHbjNby4iE8hZfwFsbO5gLQIe75WGKgQ9xxAx4d4i2Wiq0Co+X5jW5vxw14/DX3FlPFUrFVmIpvUw5utqP1u0WouCIyf1oMFVPFUoEZOISpcBVHBWaAHV1XBF7dhf8Kr+56PIWX8Ba2HAiHxjDhBbFUbBXoAwa78BEO4UvGL9M9HsJTeAlvYfF18XXxdfF18T3ie8T3iO8R3yO+R3yP+B7xPeJ7xDfEN3By4CyOqWKp2CpMhavA6YkyiFBxRdyfiqFiqlgqtgpT4Sp0BldncGUG6Po+ePSAru8WaM0GL+EtbMLwyOxGk/fBhyaavHHthB7v4i2cC9lgFz7C6QC3vJp5nDFTPISn8BLewibswkdYfKf4IkLwgAKN22dgNRkUBw8B0LjdIlRcERujOQRGwzHaruKoCBVXRF6OtMDRwKFBjpRYKrYKU+EqjopQgRlkCaCLu8VQMVXgwOBM8a3imwE+l9CDfeYTU8VSgZ/HQTim4lsBPkjwptviEL5kJMDEoUGd465+vsN2ImzzLbbNIXw/xg/n262Lh/D8GPPOd1wXb2ETduEjHMK3Oduvm4fwFF7COPsdAqd57gW6rQ8eUKDdusVUsVTkaHgMgf7pg+cL6J9uMVRMFUvFVpFHAw8J0UDd4qgIFVcELgpKDBVTBWbwg9gqTIWrwAwMIlRgBlmQaI8+C1uFWi/hKo6KUHFFoNZLDBVTxVKhM8g/E4Ecywbp5iP8nWZ4wpjd0cVfmTd/pxlCP1ujm5fwFjZhFz7CIXzJ5ycsvkd8kQD7idw/XKijK/rgihxd0S2GiqkCo+Fw4jMdz47Q4VwCn+klhoqpYqnIo4ErEXQ4t3AVR0WouBTocG4xVGAGG2Kp2CpMBWZwIY6KnEG2wg90OJdAYpQYKnIGeMiFDucWW4WpcBVHRai4IpAyJYYKncGXMhP1ng3OzSb8nZmo4uxubg7h78zEM9NsbW4ewlN4CW9hE3bhIxzC4rvFd2NnsQBkCp6joTf55G9QDPQmt7gikCklMBqOOq4FcNcevcktQsUVgWuBEkNFHg2fEEvFVmEqXMVRESquiIP1oAxwNVFiqlgqMAPsKLKkBHxw7PH9AI/10IHcwlS4iqMiVFwRyJISQ8VUoTPI6wdcQmUDcrMLf6cTHq9k93Hzbc7e44kLu2w9bp7CS3gLm7ALH+EQvuQhvkN8kQ94RopG4oMbz2gkPnh0hEbiEkiBEkNFjoYvH2gKPviWgabgFlcErhtKDBVTRR4N3MZGu3ALU+EqjopQcUXsnwrMYEJMFUvFVoEZHAhXgRlgr5ELJa4I5EKJnAHucKORuMVSsVWYCldxVISKKwJZUkJnkJcc+IDPPuLmLfydmfhAz7cpNx/h78zcb8xLzkuO4iE8hZfwFjZhFz7C4nvEF1chuKOOXuGDm9toFj7Z0T/QLdwiVFwRSA7cgUYH8MHdV7QAtzgqQsVtMdEG3CKPRjajTzQCt1gqtgpT4SqOilCBGXgKXGuUGCqmCsxgQGwV8FkQoeKKQJaUGCqmCvhsiK0CKzUIV4EZYKLInxKYwUmB/CmBGWDjkT8lMIMLsVV8M4gfNjHzp8VJgQ3J/GlxU8wUmT8tRgosO/OnxUqBZWf+tMAMsOztKjADLHuHCswAy7afCswAy7apAjPAsm2ryBkMLDvzp0V+KL6RQ/iS89tO8RCewuk9sH15FdPCVMAb+5JXMS1CxRWRVzEthoqpYqnYKkyFzuDoDAI+ODKB0XAwAqNhpWEqXMVRESp0PVfXc3U9V9dzdT1X13N1PVfXc3U9V3f0ygzQPdxicdnoBH7LRifwWwI6gVtcEeOnYqiQ9aATuMVWYSpcxVERKnQ9U9czhwqdwdQZTJdl441eb9lL17N0PXipV4mlYqvQ9Sxdz9L1LF3P0vVsXc/W9Wxdz9b1bN3RrTPYOgPkyls20uMt23Q9pusxU+Eq9AwxPUMMPhlMaPZtkRcR8MTFy+MlvIXhkUGGpt3IC/qZTbv5l5w/nsJL+Bspb9bPbOVtduEvA+2NGcKX/IVD8xCewkt4C5uwC4tviC8yYWIBqPy8oTvRlRsThxKVX+KoCAr03kbe4px4m3Igs9Fu28JVHBWh4opA5efNz4l22xZTxVKxVZgKV3FUYAYGcUWg8ksMFTmDvEM50W7bImeQ91Un2m1buIqjIlRcEUiLEkPFVLFU6Azy7kd++Z7Zbdt8hPPswGbk3Y/HefejOM9KHJg9hZfwFjZhFz7CIXzJ9hMWXxNfpEbemplolI2FQ4NsWDgjkQ0lhoqpAqNhO3CtsLBuXCs8gXwoMVRMFUtFHo382jHR9NrCVRwVoeKKwFVEiaECM8Du4PqixFZhKjADnCm4viiBGWB3cH3xBK4vNgZAlmzsWz59ccwmn74Ub2ETduEjHMK3OVtem4fwFF7CuW6kHnphW7iKoyJUXBFIoxJDxVSxVGAGmA7SqISrOCpCxRWB/MjfK5johW0RKq4I5EeJoQKzdoglAtcHqDN0r7aYKvAzF2KrMBV5lAN8hEM4jzL++yz+4iGcRxnW+Xe5i7ewCbvwEQ7hS86vIcVDWHxdfPFdw3GgkRJ5X3Si7zTytuZE32mLqWKpwGg4NKh4x9FAxZcYKqaKpWKryKPxdhoVX+KoCBVXBCq+xFAxVWAGG2KrMBWuAjPAEcZ1RYmcQd5im+ghjbwXONFD2mKqWCq2ClPhKo6KUHFFDJ1B3kLNPtyZ3aXNS/g7LfOu4szW0mYX/k7LGjOEL/m7BGkewlN4CW9hE3Zh8Z3ii3x4C8BVRN7JnO9dwvkek4mW0RZHRYhAcmTj70RjaORNxYnG0Bau4qgIFVcE7lhkC+xEY2iLqWKp2CpMhas4KrCeC3FF4LqixFCBGWBHcd+iRLZMYUMRGLiPhh7PFkPFVLFUbBWmwlUcFaFCZxA6g9AZhM4gdAahMwidQegMQmcQOoPQGSBkAuceQgZ3QNHo2WKp2CpMhas4KkLFpUDDZ4uhAh3k4CW8hdFmC3bhI4zecfAlo0P08RCewkt4C5uwCx9h8R3iiy8x2Ro80RcauH+LvtDIRqGJvtAWoeKKwAUFbsyixzNwLxY9ni2OilBxReAipEQeDdylRZdni6ViqzAVruKoCBWYQRY/XvzbYqiYKjADHGGETIlstsLdYPSNtjgqQsUVkSHTYqiYKpaKrUJngAsWLBR3PR6HMAoi+aUSeAjjQx+8hLewCbvwEQ7hS34XPOAhLL4hvoGdxYkb2D8cmov9wxl5h4qpYqnAaBj6YrTcG7R1thgqpoqlYqvA0bgQruKoCBVXxPipGCqmCszAILYKU+Eqcga4a4+m0BY5A9xgR/tni6UifbJXc6IDtEX64AYhekBbhAr4YDr5taXFUDFVLBVbhalwFUdFqNAZbJ3B1hlsncHWGWydwdYZbJ3B1hlsncHWGZjOwHQGpjMwzMAhtgpT4SqOihCBv5KLkV+uvP/HVmEqXAVGxgl/tGKOVszRijlYQUBsFaYCK8A5jn7TGiBUaM2GziB0BqEzCK3Z0JoNU+EqdAahpggX3EXGy4BbbBXoxZ0QruKoCBXpg9u1eBlwi6FiqsAMNgR8DOKoCBXwyWOKXtUWQ8VUsVRsFaYCMzgQR0WouCLmT8VQMVUsFRg6Txe0p17coUV7aoupYqnYKkxFLgE3WNGe2iJUXBHIkxJDxVSxVGAGOIzIkxKu4qgIFVcE8uQdYORJialiqcCRGxAhO4oLlSdwoVJiqMDicPK5biJio8RRgSVgBn5FIFBKYBNxVh09jEcP49HDeHQGR2dwdAYIlBJXROiJFHoihc4g1BTfgHBhjCbXFlcEvgGVwNA4lfE9B9fCaGVt4SqwhIAIFZcCrawXd6fRyvoGQCtri6ViqzAVruKoCBVybY9W1hY6g6GmSIpsNZ7oUW0RKnJxuG+NHtUWQ8VUkWdI9iZNvIW3halwFZhBHh+8a/duTBSBUgI+T8DHIbYKU+EqjopQcUUgUHA7Ae/abTFVLBVbhalwFUcEkmLjdMH1Be5uB8KhhKs4KkLFFYHYwGNStLC2mCqWiq3CVLiKowIzwGFEoDyBQCkxVEwVS8WWA4xAKeEqjgocucxRvGu3dhSXHiW2ClOBxeHkC91EfMkpMVRgCZgBrkNKbBXYRJxVVw/j1cN49TBemQHeqNtiqJgqloqtwlS4CjHFe3PfDUW8N7fFUrFVYOgDITcU0dRaAg96S2AJATFVLBVYwoUwHcBVHBU6g6kzWDoD3IgtMVUsFVuFzmCpKZICTyrQ4dpiqsjF4RkGOlxbmApXkWcInmGgw7XFFYFLjxKYwYaAj0GYClcBH4cIFVcEAqXEUDFVLBWYAc4QBEoJV3FUhIorAoFSYqjA0DhdcIFxsPEIhydwgVFiqJgqlopcAp6VoJm1has4KkLFFYFAKTFUYAY4jAiUEluFqXAVR0XIAUagpFhogG0xVODIDQjvHV3obG0RKq4IfJfJ5x0L/avYxIX+1RamAkvADHAdUiJUYBM9xfzJAHOomCp0BlNnMHUGuA4pcVSEiiti6QyWmiIp3o4uV3FUhAoMfVJsPnhcrzG1xFaBJQSEqzgqsAQcn31lAPupGCp0BqYzMJ0BHvOUcBVHRajQGbiaIikCm4ikKOEq8KuwEyJUXBFIihJ5huRTp4W+0xZLxVaBGeBUfr9zi4P1fukWAoFSAj5YDwKlxFKxVZgKV3FUYAY4QxAoTyBQSgwVU8VSsVWYCgydpwteR3uzhX2h1bTFVmEqXMVRkUvIxxkLTaglEBslhoqpYqnYKkwFZrAgjopQcUUgUEoMFZMHGE2oLbYKU4EjlzmKjtTaUXyXKTFVLBVY3IbQTcQ3lhJXBK5DLmaA65ASUwU20SH0MG49jFsP49YZbJ3B1hngOqTEUKEnkumJZDoDU9PXaJYp9ppQSwwVUwWGPhBoCMSO4pFMiVCBJWAAxEaJoQJLwM9IC9oaeDJTwlToDI7O4OgMzhURPxVDxVShMwg1xW/1/7CJ+LX+J/B7/SVGCpQMfrO/xFKxVeQv9/9QGPjt/hJHRajADPJUnvhN/nwosiZ+lb/EVgEfh3AVR0WouCLGT8VQgRkciKViqzAVruKoCBVXxMTQFyIHyCc+K1tTKULFFZG/k9tiqMgl5C+wr2xNpdgqTIWrOCpCxRWxMYMFMVRMFUvFVmEqXA7wPipCxRVhOHIDYsuOmqlwFUcFFoeTz3UTfapYKrAEzMBNhavAJuKscj2Mrofx6GE8OoOjMzg6g7NVmAo9kY6eSEdnEGqKpJiYKLpKSpgKV4GhcSrjzul8YqiYKrCEgNgqTAWWgONzjw4QKtiqvvA21hZDxVSxVGwVpsJVHBVqiqTIp0lrISlKbBW5uHyAtBaSosRRESryDMkHSGtlC1qLoWKqwAw2BHwM4qgIFfDJY7oQKCWGiqliqdgqTAVmgK1CoJQIFVcEAqXEUDFVLBUYOk8XNK/+FjYe4VBiqlgqtgpTkUtYOCSIjRKh4orwn4qhYqpYKjADHEYESglXcVSEiisCgfIOMAKlxFSxVODIDYiQHT1XBGKjxFCBxeHkC93E926hJ44KLAEzwHXIE7gOKYFNxFl19TBePYxXD+PVGVydwdUZ4DqkxKXYv5+KoWKq2Cow9IHA0AFxReDSo8RQMVUsFVsFsgqm79dqnjgqQsUVMX8qhoqpAr8YZhDYxAtxVISKKwKBsjEaAqXEVLFUbBWmwlXg18YcIlRcEe9X7Z4YKqaKpWKrMBUhG7J1pS93nhgqpgpdqelKTVdqulLkTolQcUW4rtR1pa4rdV2p60pdV+quQvfada/fr+tiQ46uFOlSYqswFbrSoys9utKjKw09q0LPqtCzKnSloSsNXWnoSkNXGrrS0LPq6l5f3ev3i7zYkKsrvVo/V+vnav1cWan9fiqGiqliqdgqTIWs1H5HRaiQldr4qRgqpoqlYqv4fPBmhoU+2BZXBF5EUAIrHRB40UZAmApXgXNnQoSKK+Il0oIYMgBeN1BiqdAZLJ3B0hngdSclQsUVgdedlNAZbDXFl6F82L0MlzglQgUWh71GCJUYKqYKnC7Y6xdCT5gKV4EZYG64xMkHo8twiVNiqkgfw8mHS5wSpsJVHBWh4orAJY7hDMElTompYqnYKkyFqzgikC6G0yUwADYelzglXMVRESquCFziGA4JLnFKTBVLxVZhKlzFUYEZ4DAiXSAc6VJiqJgqlorNA+wvXZ5wFUcFztHMRMclDnbUcYlTYqswFVhcQMgmOr4ZlRgq4IMZ4JtRia0iffIB7PLpOsBRESp0BktnsHQGuMQpsVRsFaZCZ7DU9L0YCRvyXoz0xFKxVWBxAyIT6bzRroj3+qMncgn5dHk5YqPEUpFLcPjg9Uc1gKs4KnQGpjNwnQFef1RiqlgqtgqdgaspksKfGCqmCizOIbYKU+Eq8gxxFAYuV0pcEbhcKYEZ4FRGoODBqCNQSriK9MGzw/dG1hJXBAKlxFAxVSwVOYODMwSBUsJVHBWh4lK8t7OWGCow9ILAABviisA3oxJDxVSxVGAJDmEqXMVRESquCARKiaECMzgQS8VWYSpcxVERPMAHgfIEAqXEUIFz1CBcdhR3V0qEiisCd1fw1Pds3UTclC1hKuCDGeA6pESoSB88gD2mh9H0MJoeRtMZmM7AdAa4DilxVOiJZHoiuc7A1RRJgfRHC2yLoyJUYHE4lfFqRXxioNG1xVaRS8DT5YPYKHFU5BLwQPm9wPUNgBe4lhgqdAahMwidwXtR4xOu4qgIFTqDq6ZICjzsPkiKEq4Ci0PJIClKXIpAUpTIMwTX/oFLjxJLxVaBGQQEfC7EFYFAKZE+eHYYCJQSS8VWYSpcxVGRM8jf3VuBQHkCgVJiqJgqloqtwlRg6Dxd8O7VHx4B4+WrLbYKU+EqjgosAYcEsfEEYqPEUDFVLBVbhanADHAYESglQsUVgUApMVRMOcAIlBJbhanAOZo5GkiKt6P4LlNiqlgqsDicfK6biG8sJa4IXIfg4XDgOqTEVPH54A+7rzh6GI8exqOH8egMjs7g6AxwHVJiqNATKfRECp1BqOl7PTQ28b0e+omhYqrA4nAqv5dA46R4L4F+IlTc/JlMy/f61hJDxUyxIBYHuO8l0E+YCldxVISKKwIvZiwxVEwVOoOhppkUAw+7swW2xfypwOLwM3OqWCq2CktxIFzFUREqMIM8lbPR9Xv5G8RSsVWkD54d5htfKY6KUHFFZKC0GCpyBvkbjSv7YSm2ClPhKo6KUHFFGIbG6fLeDo+Nf6+HfyJUXBF4Q3yJoQJLwCHBS+JLbBWmwlUcFaHiisC74vEAFm9ubTFVLBVbhalwOcDnqAgVV0TgHDWILTsapsJVHBVYHE6+q5t4p4qlAj6YwTUVriJ98BwjG105AA/j/v1+KoaKqWKp2CpMhas4KkLEUNP3t2MGxFZhKlwFFgchf3pi/+RPT+yf/OmJ/UNszCe2ClORS8gHyvu9wrUGCBVXxNIZLJ3B0hm8Pz3xxFZhKlyFzmCpKZJiYhORFCW2CizOIVzFUREq8gzJp8s7W2AphoqpAjMICPhciKMiVKRPPjvceAlri6FiqlgqtgpTkTN4pwsCpUSouCIQKCWGiqliqcDQOF0CA2DjEQ4lpoqlYqswFVgCDglio0SouCLuT8VQMVUsFZgBDiMCpYSrOCpCxaUYCBQc4IFAKTFVLBU4Rw0iuKMDr5B/ArFRYqjA4gJCNjEbXSmOCvhgBrgOeQLXISXSJx8g7THlMI65VGwVOoOpM5g6A1yHlLgi1k/FUKEzWGqKS498ZrQHLj3ykc8euPR4ApceJYaKqWKp2Coyq97BwsvmSxwVoeKKwN3WEkPFVJGbuLE4BEqJoyJUXBEIlBJDxVSxVGwVOgPXGbjOwHUGrjM4OoOjMzg6g6MzODoD/HmKvN7Z6JRtcVSECswAm4g7JQOliTslJbYKrBQDIHdKHBVY6fuZKwPg+0+JoUJncHUGV2eAV9aXcBVHRaiQGeAtsC2wiQFhKlxFLi6fqG10yra4IpA7JfIw5tOxjU7ZFkvFVpEzyF8F3eiHHflgZ6MftgRypwR8NsRUsVRsFabCVRwVmIFBXBHInRJDxVSxVGwVpgJD45AgXQwbj3QpsVWYCldxVOQSHIcElytP4HKlxFAxVSwVW4WpyBk4DiNyp0SouCKQOyWGiikHGLlTYqswFSjA/DBCp2ztKAKlxFSxVGBxOPmObiK+2JS4InAh45gBLmRKTBXYRJxVoYcx9DCGHsbQGYTOIHQGuJApMVToiXT1RLo6g6umuELJBwcbL3HFC8g23uLaYqpYKrYKU+EqkFU/iFBxReAeSomhYqpYKraKzwd/j3fjda0troj3l3qfwEqf2P+oP8H7J0yFq8AZ/0SouCIQG/mQZuMVrzUA/h54iaVCZ7B0Bktn8P4e7xOh4orYPxU6g62mCJSDTUSglAgVubj8ldONhtoWQ8VUkadLPmfaaKhtYSpcBWaQ9YO22XFwjiI2SkwV8MH5htgoYSpcxVERKq4IpMvBGYJ0KTFVLBVbhalwFUcEAuXgdEFsBDYesVHCVRwVoeKKQGwEDglio8RUsVRsFabCVRwVmAEOI9IFAm2zLYaKqWKp2DzAG+lSwlUcFThy+cGCttm3o2ibbbFVmAosbkPIJuKFry2GCiwBM8B1SImtApvoEK4DHBWhQmewdAZLZ4DrkBJLxVZhKnQGS03x/SefqO2NK5QSS8VWgaEDwlUcFaEis+oH0/z+02KomCqWiq3CVLgKbCIOMAKlxFAxVeRKLwZAoJQwFa7iS+WNC9r3UtkSVwT+AniJoWKqWCq2itzRi5MclyslrghcrpQYKqYKrAdDI0MuChAZclELyJASQwVGw0mODCmBfcMZjwwp4SqwHpxIyJASl8LeH+l7YqiYKpYKzCAgTIWrOCpCxRWRVygbN4gMgYJ9MwRKCVMBnwtxVISKKwJRU+Jb6cSpnG+GpVgqtgpLgRlk1LQ4KiLFhrgiMmpaYAYGMVUsFZjBgMAMsFULM8AhWZgBdnSFiitiwwd7sJeKrcJUpA+uBtEC+05ltMC2GCqmiq0iyxk34/Ay2BZXhOOkgGk2qbWYKpaKrcJUuIqjIkTkdQj+XPFGb2uLpWKryK0aOPTHVRwVoQIrxQHO1pMWQ8VUsVRsFabCVRwRedtkv2Oat01aYKU4Pnep2CpMBVaKU/n9MdAnQsWlQAtsi6EiV4pTDK+UbbFVmApXcVSEiisCUVNiqMBKDcJUuIqjAit1iCti/lQMFblSFC1eKdtiqzAVruKoCBVXBAJlPLFUbBVYaUC4iqMiVFwR+6fi29GFhEXbbIulYqswFa4CPhAZKPjjsxvNsS22CuzbgHAVR0WouCKQOyWGiqliqdgqdAauM3CdgesMXGdwdAZHZ3B0Bsid+YSrOCpCRe4oHj6iU7bFUDFVLBVbhalwFZjBgggVV8T9qcAMkAdIpBJLxVZhcuiRSCWOilBxKdBD22KomCqWCvgYxFERKuCTVY9WW/x1x41W2xZTxVKBlQaEqXAVR0XOAJ9maLWdeIKLVtsWQ8VUsVRsFabCVRwVoUJn8F384J5HNtoWTuKfN75j5stoC43454obP9mDWxjE2/jlUuEgTuIibqIR6bbpZtjHBYHdwgFHDuEyFj21LVzFEYE/BopniccxGnx8qzAVruKoCBW593hEl2+SpRgqpoqlYqswFa4CM8A5i7QpcUUgbUpgBjgvkDYlMIMNgRlgq5A2JVzFUREqrgikTYmhYqpYKnQGX9rglkx24RYe4p837rJk/y0wu28L/1yzsXln523hIm6iEZ14iEG8jV/SFNJt0A1Jgudq6KSduOGPTlr82cSNTtoWQ8VUkaPhG3Sg9vEsAc2zJfDFp8RQMVUsFbn3eLyDttoWruKoCBVXBK5TSgwVmAF2B1+JSmwVpgIzcIijAjPAjuIK5gkkR4mhYqpYKrYKU5EzwJMW9Ni2CBVXBNKmxFAxVSwV3xmJpX0pVOjEQwzibUTC4CkO+monnuKgr7bFyUu/gAgVV0R+W2oxVEwVS8VWYSqwVzgRkBZ4uhJIixJDxVSxVGwVpgIrRdHh2qREqLgUaL/Fn4zbaL9tMVUsFf+/t6/bmS23rXwXX/tCf6SkeZUgCDqOZ2CgYQcdO8Ag8LuPausrilXVexVrizU39uY5fVbph1ySSIoqWiAtsBZmC/oUjhbMNbjPXcuPMHctdyFqIWkha6GsOe2RtMBaqFpoWuhKmCx0F6IWkhYUC81cXBGqFpoWZk8Pe+6ahbpmof7DQj/C8TszCDNzcUWoWpgj+vNvFA/2ErQQtaBbUHQLim7BDwv9CKyFqoWmBd0C0j866WXGhPqkl7vAWpid4yk0LXQl/Lxs/iNMdZmq/PO2+Y+QtVC0MFswdXRuZmb8YObi3oW5mbkLx+9MF/vMxRUha6FogbTAWqhaOFowl82Zi3sX5mbmLkQtJC1kLRQtkBYm9JySyS4zUjJzcUUoWiAtsBaqFmYX5pRMdjkEmrm4IkQtJC1kLRQtkBZmC+oUqhaaFroSJrvchaiFJBNM4YddfoSiBdLC1FE6hEkbx4hSmLRxF5IWshZm59oU1iBSmLRxF7oS5ramzRbMbc1dSFo4fucIZ1DIRQOQFlgLugVZtyDrFkxCuQtRC0kLWQu6BUX/6GSKPMeAghaiFpIWZufiFNbZhAJVLTQtHL9zuPJp5uKKELVw/E6f86NORxTU6YiCOh1RYN0C1i1g3YJJKD/CJJS7ELWQtKBbUPWPTqbocxAnU/wIkynuwuzcNJnJFHcha6Fo4fidPg1jHnvuQtVC08JswZyfSSh9NnQSyl0oWrj9Tg5TRw9CEaFqoWmhL2Hm4ooQtZAOIU4ha6FogbTAWqhaaFroSogTOk9hApQpVC00LXQlpKCFqIXZBZ5C1kLRAmmBtVC10LTQlZBnC+oUohaSFrIWihZIC7wmeKbsitC00JUwOeSINNLMxb2PaCEtsBaqFmbnDuU7Mm5lEClpIWth/s5sAZEWWAvH78SpVaSnkfQ0sp5G1i1g3QLWLeCiBdKCViTWisS6BVX/6MEUOU61PLYe+Yj80JFkuwTWQlXCQRsiTLQ5vK1oYaLNHz0oIMc5c33+m6lVvWiBtDBbMNVlGvpdaFro63fSNPT5N2ka+l1IWshaOE5gc6U9cmSXwFqoSohqDGYm7E+3ZyasCFkLB1qdPzqt/ghN0MyEzUcwgWYm7F2YVn8XohaSFrIWihaOET28wzQzYUWoWjhacHjiaWbC5jQ7N60+zS5Mq09zrI+UtlxnF46UNhGKFo5xO9xUNAvI5sMLTTMtNqf5NyVoIWohaSFroWiBtDB7Osd6UsBdaFqYLZgNpdmCOW6THPIcnUkOeY7OkY6SywQ40lFEIC0cXoI8e3pEce7CfNfvLszfmcM7KeAuHD29/2dFC6SFo6d5dntSwF1oWjh6OrdFM3tWhKiFpIWshaMFZY7BZIq7wFqoWmha6EqYHHIXohbm70zlO2LE9y70+W/m6PSohaSFo9Vl6uhkl7swWz3HbbLLXahamK3++dG+hJkwK0LUQtJC1kLRwmxBnQJroWqhaaErYfLOXYhrdGad2Xzk89OsMysCa6FqYf5On0JXwuSduxC1cFj9tIWjzuwSihZIC6yFqoWmha6Euac4PLk068yKULRAWjh6Sj8AVQtNC10JR8LsDw3OhFkRkhayFooWSAushaqEyS6Hf4dm9qwISQuzp3kKRQukhdnTMoWqhdlTmkJXwtx63IXZgqk7k3fuQtZC0QJpgbVQtTBbMHV08s6PMHnnLkQtJC1kLRxjPbegefph55Y6Tz9s+PnPuhKmH/YuRC0kLWQtFC3c5vRn13mk3y6haqFpYbZgTmMPWohaSFrIWihaIC2wFuoSjiTb+HPAnUm2+cj0p5lkK0LWQtECaYG1ULUw57RPoSthMtJdiFpIR9tmQ48UfhGKFkgLrIWqhaaFroQUtHD09Li0QjMXVwTSwtFTnuM2d0J3oWnh6ClP6LkTugtHT4/AAc1cXBGyFmYLyhRIC6yFqoWmha6EuUe6C7MFNIWkhayFogXSAmthjvVhZjMx965VpLWKtFaR1irSWkVaq0hrFWmtIq1VpLWKtVax1irWWsVaq1hrFWutYq1VrLWKtVax1qr6o1X//OMfxi/+zx/mHN+cznOCj68iXyRfLF9Vvo5+3vx/czpvX3Mubw7pOZHH1/yNwUFzCo+v+RtjwObkHV/zN8aAzK3t8XX8xs07PDe1t6+55hxfx2/cfLpzBo+vLF/Hb9wCxXPijq/jN27HnTllx1eTr/kbo29zpo6vKF/zN0Yv52JyfBX5mr8x+jvXkONr/sbo71w9jq9+/5rrxs39OReN4yvJ1/yNMQZzj3p8kXwdv3Hzb86t6fF1/MZNv+em9PY1d6Q9jvnOt/meu6YjcFTla87jzS7mPI5xmjuletOTsv7doUQTu4y/oeNv5r/JQ+ZDnpbZhlxv8o9x1vv8Hl9Vvpp8TUqo49+1hcv8z/EHv/7tT7/8/S9/++u//f23P//59pf3P/ivP/yvf/mfP/znL7/9+a9//8P/+us/fv31j3/4719+/cfxH/3Xf/7y1+P///7Lb+NvR0///Nf/GP8/AP/3X3798+3rn39c/zqc/9NxoqKffz3OU1UAhpvMCpGPoT4gbjXRF0R8bEU6h4g3I5mNCFkA8lMb8jlAu/lKDoARqD8FKOcAx0tcB8CIbFwC4HsLhvMynSKgcaR2hxjLWTsdxwpm84hHzoEce/AFMb41REOzedeHsaVZAEzmbnBa3cj1tBsRYBDnu0qNzzUU/AQRgUqV2zZvTghROoUAWlkri1KV1Q/KZoRW7t1oHM8RgFql0GVGhx9bMEp6hCDQCL4bV+v1vBEMGlHrfSxvj3Av5b46H/V8PpBW1NtBYmpFDf0UoiO6uy2GP3RX4hlECrtzmuL2nKa0O6cJMOb4YSZhLObVjOFEs3flKJ7y0xWKp10B6nkEriddhFMATBadRS1iPp3Tuk3eCCIfLy3/EGcHq2BHNsJJbEQNRnpeCNFotPuEcCCFwB9oRutLM7qa1WfNyEBDe2l3FR0js1oy3ASPGBnxThBDqUlxhnlWShCEW7GR01nJhDYnJMzVkloT4+OamAGDHjXb7iC3cjEK5Wk8qoN+tF39gH0pRyz2py/DwXXal4I2nsf18x/maF21pD9ixF39QFpqZ0E8IpyFQG7XEs5HBC31THceG0ECNTexPGIAXc1HPfwfNmU1qvGRTwvqTatR9L3lcwygqccza3N9UqvsCwLS0yhrfQJtQGx6ZH7PfoxIzZqT9oF6WKmQ4j4VUtpVdTitPQqNdTApVNCQLipMQL2IdieWeHtioZ0c9f6mnYzjwXkz4Emp3pX89pzZuY6idqQix63UztvBgElLl3bckuJOMTCDNSGfWxJhO2UwBkrKxyXsubjkdL7GMVjzS5TF5Vbp7hpG5bua3hLqzzHAzAyI+8zUmtWeMD6aHINRrSXfTxu1tHCOgfaVtDYwa3VK6QmhoZW23y3udgv7HANwKaX7gI745jWELvuOSOcISLuyNIJLPN911ITOCmJvxHyOAW2FalnbsAb0vCIqjY3uyjG+azih9Eq7iwK0lCZLU+lq9/PSk7pvKbXtW0rtu5bSwr6ltLhrKRDBZClQQ7msLRyPmNTpvLaye1JA2kVRthy3fMhr1lYDyRasBrC3bsgxmpeHWfs109M5sLVda4OtOOoDTIQRGzxtBTqNzhKQP+emGk9Poz0iF22/W9vtmRmFwWaMcoT4p7nd/ICnGHn/PNu3tRSPaFtW/6ClZMdIeWGgWam7QZDedqMgve+GQfBINLGSEQk4HYnjLQngLmmyGy16E1ieQBLanyfR8hGVvAZSgozIrUgvACn7en4U5P+iorO4rhM/DMgHis4yM6kWBtPbdjX9eKtgT9Uj8hs76Hol8X53wBwRxYjmu2I/hJ61e/HJBR4z2oNJZ2qldg2kcYoS2qAIQMhB11HAyabrmEKK2jZEYP0RLflHmvo9XMQApEP/sZDZmBwFEp8CiWHb1YmUtWdxL/bK16y/y8TkkNq5wsP4gs36U9m2fhR22rf+fLz7/OO7yQkMBlr00/I/56xtLn8A0otQSGgBgCA1pSZDMla6eH4Iiyj+tOIcWsnGWvxJS3pULUkdtAQ5b3sV4w0hnrcFBoyjDMrT5vDJeDNa/7lmoQCuyrf/3B1kexRWpg4V0BLo25ctwBieBgbW4cAfs8OJ/3jNYu/IH4vDmT+W7UM/hjCd+iENzKuuP8fLCLikeOxVy/ZeFat7W57xkPK5uqMw1NjwikO6qByezh9gVElx4FoBBtLTIofl25v0qzPPg0oBmZ1o+9juxXOLQbEoIgm7EmmQDzZFvM7LNYBNEWXI8StkSl1tWZ87gyKmNSsdSaAlQNFKkoBUmenDPyBPOXMRhqS6uIRTULvN59QkghkkQmYB5GmhkNTw9Ymucgin0cpIaPkNPaUV9FS29xywhAacoyw1OQWwcjKK8JNsjxLUeRQ4MK9XyJdpXq+4bK9XTA7rFQpMGdcrCGFbrzChWeelO8xLDdvzUqPDvMDwlG1eIITDPqJEOaFRB8cJFJu63dKRhUaNxwutVgdarfu0Wj1otf5/oNUk+p4flqtnWm1QWdNKvurl3GiaB602D1pt+7TaPGi17dNq26dVtGGtRSJElZTRPG9YW4e+87uSFeWxejo4d5isLUdeqlpPy5N3BAaqQhEXS1Ah8hcQOB6xr31z7KfjASNVVSJ3UR8CRjDuCQSFqsJd1akEAEEOB4nODgcJFK0yHiRwO4wE0h3W/+PZhT0CScFh/U9he/3HEDYC6dC7ep+WVvOpnqZA+/v24/WJXf04Xq3Y14+2rx/dQT/gVQebfkAIo34gMmRpxtg2xXMNQcGmHBaThY5AioOaRYdMvxQdUv2OpxI21Sw2DzXr+2rWv7uPYcnirDWdrtsJ3ZNSifm3xwdO18sEA1Ylquz+1Zv+fF8LaWpe92y1bzb1+ASCWPW4IP0DomNnLzfHgKaOAP59KzM+zzPa8RIh1+hGEBYYb2r7h5CEYkVm40UxK7Px5rhtvChiZTZedGnKaLwQwmS8mN7jSjFLOgX7WUNQtMqsIR7RquQRrUr70arkEa1K+9GqtB+tekNmRSKrRV0IfiEzFK2yHmUSjFaZjjJv2mFUsuKxVS37W9XisVWl/a0qhX0lQ8tuWQ5EVivmy7JL2WFyUazKPLkoVmWcXGKPya37k1u/O7lrc5dYXYN/mVx0e+pWzvrel6A9O5/sMnuSO0u9nntlEsNaEfe5bVTP2RDm20vonvRqmZ+Hw0NNeV9N2UNNeV9N2UFNkUcmSB7SrSLluXZUh1hZQjEq8+SiAJNxcmt2mFx0gco4uRDCdkiFtSfk2iQxn9YTQbc3j7qWczxL09kUz+Ur0KIfJHM3x4eaO+kDkMOP9rNlf8hnfAJBV6iMZXcSik7Z6u5ACGORFhSZslZpQYEpY5kWGJgy1t6xz8p58R2sHlFuXecEssNT276hktr2FRUMYS33AvfZ4p3KKFn+yMk713Txo4zPchokxyBNCm4NjA5Ayr7douCU0W4RhNFuUWDKarfwIpXNblFcymy35lkBdgvVo0sst3a1s3xWj4yiSsa6WcezDXtzm8N+NbQctsuhZRSY+qBqDIYxF1pCwSlzpSUYnrKVWsI8xEJmrV8ksxb7IpF6no2Z0ZWqSGXduFGn/ucqhpjgu2x0c6/ne6oc92k1x21ahRBG04v7tJrjNq3m6ECr9lm5uh3qkgVdwkMW9NOAoKOhVT1QdMqoHmmfmaE316geKDJlVA+YumhVD/OsXFaPdUwOoV07kZUg96BKKEDHUFzKWEs1Zwc9zft6mvf1NDvoad7X0+yhp3lfT99ox7YDo0qi7+2V7lMHRkbxJE5yOZVLBst+QSUno9pNhdNV/8141DUe7eKY2urUZhSTSivRbwTiyjkG71stjEnZrBbWArRZLYxIGa0WRZOMVkvRwWrNswKsFmrHqo+RtBf2IwwSn+GIfp2Wzc2wll+XS/bUuV/EkCgOxMDWYjueortTRk1HEEZNR+Eoq6ajS1NGTYe11kK5KwcHVR/xRdNROMpU2Rk2g7oUk+Ggb6S/NINcjtkoImU+ZnPdPWZjDbGV3M7o0pTDzFTxgJBOiH+dGTNIvwjS5LbS+LwMIm9Y3MogXATpQUJSPZWL2hqLZKPcvjPQVnJxUWGYKhuz8c3xMkxfd5+aOg99ZoJVYn69qsKvryZoBulXQaQ/45OugYzgg5qj0BAMHNxeVyXJEMvVOWrqflrTMeYPYeQ+9Q0G6K99RT8/tTaY+beCK+CkB08DpqcFMgo2mQ/xEGSVXB/Ho3N3Qu5w+yrX5UdY/Lw33cET0Pc9AX3fE9AdPAF93xPQPTwB3cETgLWD19aklUsYOUpnhhe3XsUI2xh5bXCycgV8hiGTO+BOMUoo2+ejNxi28xHsS5Fc23E2bfsYF3UsJ8m4yaXV8/FA96jVxma4noDVoYZUybrJlU+psMS4P7kYw2Fya1x9OTfcAiMiQYqyxahyoT4c1C4ZIu1cywq6R2W7rV9QpOpWPuzel3GOPWVU2I4ivsSiy4Q/Dwdes1cV+qzjoc/vA8C6fzY/YEn7T6GVtP0WGoSwrdkl7cf/S9qO/5fk8B6afVYqmJWw7QfEGDY/YIGPTtlo7I2mm3x4Je9rad7X0uygpXlfS7NLeklBoSqr36vk7drpeFRtfq8Cr09Z/F54UM3umXdzYzwlv4GxHv3fwFidRW9grM6idzBGZxHWW6Oz6AOQfhXE5iyCIHZn0TvFM3p5PiDr860evlZlcc/AHVYpa5f28CLM8wtMiGltTwejO1XGWsK4K6sKYQEOHtwOW14zbkhfdXtiOL8FUFCMwjimKIhlfJAZQjgMB8UkHsBY0HCUb2r67a37ezPGDgs0A55p5GyV9IOLT3uK/fgVboWsEfpk9doKpKPrnbGxxa6nrYDV2FpeJQwahWsgndYq3nX6zEcgUpAhRp1K+MmgyqakdDC16DKUA8Rt5V5rVIunXcEgxpnBIMaZeQNimhlsuayORg+vFz2/hYnu7xifECht+7VU3I4uV8Rif4hlxE86I0H92PXh5gVk+wWA0rZfAMAQthWm4EfHbBXmC7pXFblK7Hl8qzA4fwRiKlNfOnQn2MrUF+RJtJapL92hPmXpDvUpS9+uT1m6Q33K0rfrU2II05VZrCHGyu4FXa8yVmUnWPXPWEyRUN0/awUSgkX7TBVI4Khay21TcKinRsGhnhoFh3pqFLbrqVFwqKdGYbueGoYw2d0bTTXOC7paZZ4XWBzKNi+w8p91XtC1KOO8QIh9PrRWdKboUEyNokMxNUoOxdQobRdTo+RQTI3SdjE1DGHUEDQvtgrGlOA7qrYKxoSuV9kqGBOq+mdedHHVP+OiC4NWpkWXPKoPUvag1LxPqdmDUvM+peZtSoV6aqtgTDBiZd0KZQ/9KB6EWvYJtXgQatkn1JL39QM+kG2rYEzoIo+1gjGhy1FmNUM1/+xq5lBInWi7kDqRQyF1ou1C6hjCYd22VTAm+DyVsYIxweepbBWMieAT6rYKxkTwQVVbBWNCD1RZKxjjJcJWwZjY4RkV8nidijxep6L916nI43Uq2n+divZfp8L0bqxgTPCilVVDPGr/kUftP9qv/Ucetf9ov/Yf7df+e0NmtgrGVKvDUQYVijAeZapDmWxqHlvVtr9VbR5b1ba/VW37W1W47BorGFNjj8mtHpPb9ifXoTw19e3y1BjCYXKNFYwJhaiMFYzxLtNYwZhw8T5LBWOC4SVTBWPqHmra99W0O6gph201xRBGNUUeGWMFYw4OVdQ5OJSn5rBdnpoDe0xu3Z/c7fLUMP+gVHkju9Tcz8OxEIQlTa7Ucp7TwegylC2ng1F4ypbTgSEcsgY5SvYRxwqu62KQNbm5lIsgWRLEeZwPTkE41v2JafsT0748MSTtYI5gOODNnbEtkDQ36vEsT+YdiOkBdEaxJeb11GfgBLqDEv+MD6AzulVlfKmX0/bdP0ZeHetLvYxCVPaXejFMXA+xjm+upzBQZWuOsuTlAlQ271/9Z4cigLxfBJD3iwCyQxFA3i8CyB5FANmhCOAb7TBd/YcYxqv/7zDCNobt2j7jCJPK2aV0sR2mEgRv2mG6YW7vC8CAfSmSXDpOc/G8He3b7TCVMbBjXLQXYxkDRuElaxkD3BBbGQOm/RoVbzAcJtdWxoAJXpKzlTF40xBTGQNGISrjVgbdobKWMYDtsJUxeLtRZbVRLWcbVRSfMu92EYjt2g/eplapazg+zxWV98uqMm+XVYUQxn0Q75dV5bpdVpWrQ1lV+6wAXseHGFmzY+/ndFodqBCeYowBbghSV92xqk9kH4HwqtDIteWLIMsxzK3my4cyXc1A3YH89FC2UiHGAY0ADBwXKZoxtCFdHdzljGiBAQjvMzw+DoVFA+2S6QwfglQiiWD1bvvn/+ZQ+we2wzqkcGolIDtmOV1U+Riyqu5QLvshIqldUb1sOTEFtbkCloMKK8m4qCdVytM9lzeX1CTcdbukdnazk1GkynrTDYIYbyGjEKL1/iC8K9clKTv2dPmunC0LocJIE2cJaLDaGD3fYkI0cjyx/hNXUbz62V25Kivf8HudR1YqCle5gMRjh39Xs3YRpK4aL7UnAALvU8n8Fr4G0eXant6/fwQRg3KsMgEQWCqDV6mMroIr/YMxXaWah9EgPUN3stoqytDD6R1EiBEHhjDR+O6nSwW+DlkkiDe8QdeawryuVLLSsyeMiq5DcekCsVqRwie3Mpe/O2cdsXoixYoiVjYqenMnU9K7xymPL0EcwZufVuiC4J9AmDoCr8oZORWDWOkw5S+DmDk1eXBq2ufUtM+pyYNTkwOnpm9zal0xs+HbrKckhEIiWR68zOp89xQuqyjGRGt7SFo9YqEnEJROHYQMx4YunILg63JWNsy8TSL4spyJDSGEjQ1z2O+IBxtmDzaE96k8QMxsCEGsbIgq9hvZEEEY2bCQAxuiWJWVDeGYGtkQ37dlVTtIEcjjDYSKrlOVvDI7s36n+pmFssN924rq/RmNF5qM1Xhd7I74yyBm44UgVuOlvm28CMJovNQdjBfdp7IaLxxTD+Pt4iLuyln2YrzoOtXYkq/qg7ru17Pxsodvh/cPVOzg28EgVrtDMSsXELPxQhCr8da8bbwIwmi8CMJsvJX3jbcGB+NFt//SAkl6SF7Mt8KnfySfqUSVav5ivvhyt9F8W9w2X3gv22q++AVNo+W18mUQs/lCEKv54ntVJvNtddt8YeTMar4onmE1XzimHuabVzhy2Mn55d2KLlaVJnV7RxSnnpsvvrxrNF8U0TCaL7x3azXf6uHA6+3LIGbzhSBG822wrJrJfCGEzXwhhNV8G7pdZTVfOKZW84X77yzXiWJWrrOnehUNXY0qkulVtAePsx2CxP51RtFnEPUeUyH1rOhHEBzWXaKwD0EXIWQs+OpYsIwFXx2L9bJ6vToWGuLiWOh67hfHospY1Ktj0aQj7epYaIiLY9GEMlq92ooq1braxVZ0eR6zXx0LDXG1FVLYugPKgbVtrFl7uECO8RZUg/mDUaalptQACPKkcv0dEn65zw07Y0y1ewNiy2PEIMY8xjelOkyBFAhhC6RgCNOGsnn4YpuDL7bhe1QOINYNJQaxbihxvT/ThhJBGDeUCMK8oUSXj4wbSjym1g0lLoBiO4W1sh9GhbVLzEbTHfS9fBvEbDQQxGo0lLaNBkEYjQZe6rIaDazFYjQaOKbmUxisTkOr9JBKuH+uTtNQkawc5cmQHHU6xvOIQA1Rt3bUsMbHHIiGrlNxuYdSmfI1BLkcwuqSymcIQfZ2p214U+snyWW98HBweGoFOuVTXxUliwdGP8MwFz+q4bygZENxqVjWizQlt/PONHQ6lttYHNWe+wUDqWhMJC6LmEP3QInpfGCh96SvMQHVPmEhpuW36PF0496Qs9C49+8ey2X3WOkqfxnEvFxWh3h/q9vxfghhXC6rQ7y/tf14Px5T83IJq2SFxc2kePUpVa+hF6WynNyLuhDy7PeEt6jkpFv0a1L8dKcTl+oy7pbb9hETV9kymj8GsVpuj18GMZs/BLGafy/b5o8gjObfi4P597pv/m+uUBkzl63PWpXzZ606uvwQ27om39S7us81FPH7Szbr7Q73DuDTSdbFOzgEC3ugL4NYrReDGK23ozGxWS+EsFkvhLBab0cl/4zWi8fUunhHhwzXji7JGI0meXhVk4NXtcf6ZRCz0UQHr2pP215VCGE0muTgVe1p36uKx9RjyRuBD6ml9JBb/vKSI8oZCitQ/1jD8GndRMEqFxBuVFZ85+xiOYZYlSG5p3oNYnmqOp1DIEUVn0hPV3VdKsL1StvmUukikWW52z54MV4ESevNkRwAfeT9xFSIcfMLiXOntGsNiVFmJsZGF0GUhyj3qy2hVQ+CVM3fD0F4le1p/Wp3FpnlBLpTtrOoIYRxgSgOWdS9fFtZs9BQzFQvDoiNiCCEjYiM04Ig4H7Z1hEIYeuIcdeOGBWep6yMik92RkYlByUlD0YlD0YlD0YlD0YlD0YlD0blfUblfUZlD0blbyurlVF5n1F5n1F5m1Gx/9DUEQxh6ojViwkgsH/ZyKhvPN1GRnW4PAUxzIxaPRi1ejBq9WDU6sGo1YNR2z6jtn1GbR6M2r6trFZGbfuM2vYZte0zKgzI2hgVQtgY1RgWRntUGLC37lFx6oCRUbuDknYPRu0ejNo9GLV7MGr3YNTuwKgxhG1KxRg2TsUYVlKNIXxbYY2s+mZMTGz0BsNER+a5QZQGE0NtxAohbMRqTE9FxNo8iLU5EGsMcV9RMYiVWt+h2Lj1DYqRXN+gGNn1HYqNXt/1yMqvyYFfkwO/Jhd+TV9XWzPBJgeCTQ4Em/YJtmzHqzCEjWDLfryqecSrWvIg2OyhqdmFYLMLwWYXgs0uBJtdCDa7EGxxINjiQLDFhWDL19XWTLDFgWCLA8Huh6/eXPdcdcSYzt+HhxDrmShd2/mDu83WRxHegNgezcAFN2wLDoSwLTjGsh9wYrPDgoNLw1gXHA4OlgsfvTIvOBjFuuBAFPOCg5/xsi44GMW64OAeWRccrvsLDtf9BYcdKlbFUL+utuYFBw6KccGBGMYFxzg5AAMXJDN1BUOYemIti4YIFhassxIsLp1nJdjmoanNhWCbC8E2F4JtLgTbXAi2uRBscyDY5kCwzYVg+9fV1kywzYFgmwPB7vMSLthqI9i6fTaxlo1FBAsL+loJFpcWNhJsDA6aCkHMBPsGxUiwGMVKsBjFSrBvUIwE+6ZHRoKNYZ9gIYaRYCGGmWAHzLfV1kqweFBsBIsxbARrnRxEbbSdTYEhbARL+9kUxcMnXTx80jF5aGpyIdjkQrDJhWCTC8EmF4JNLgSbHAg2ORBsciHY/HW1NRNsciDY5ECwaZ9g4WM/NoKFEDaCNT45hAgWPgZlJVj8LJWVYIuHphYXgi0uBFtcCLa4EGxxIdjiQrDFgWCLA8EWF4Klr6utmWCLA8EWB4ItdZ+XwnbQD0NYgn74FcTIckc8tfOnFOcj5af6Lup++mo4fmfTtthACNtiY3ztE01q9Fhsostiw8XBahGIfbHBKNbFBqKYFxuIYl5sMIp1scE9si42Ne4vNjXuLzbV4Y2LgfJ1tTUvNjXuLzY17i82dT8RAdeLMi02GMK02IR9mg/7NB+2ab50B684BjHTvMNFLQxip/nmkUiIUcw03zwSCd+gWGm+eSQSxr6fSAgxrDTfPRIJY/+62pppvu8nEmIMI8337WhdqbBkY+9Si2sEFBbMJyDjH/YFosbkqTcJX5jqLaimXEMpsd8fiispnlVbKrBos3VMcOVn85hUlzGp22OCHm3ondZTOLqcHtVPQJbCdp0v+gxCcNMYpCDu+FarxkcwttpgGMJUG+wNhKU2WEaVLKwz8wbENjMZXyO3zgyEsc0MhjDNzBsI28yg/W/P67X3vPYCmcMnIGkVbi/hHATtxFORun6pxLUTf8KIKSGWL31tbVQxzFcQVMtWKvO3vNoRKX+AcVz6mRgcEQYqhhm6PIURFa0+1eUdIMCJdTxCMBvSK2oILGZfZU9f1TMU+frc1NO5wUqSZZUYSsLXMEje9kqU87mOZPQmRl/nxs79KogyvnOQDK+Sm5Q1B3jCKXUdcQp4ZAzDhBblxZTQ8mWYXtXORjHBhzA1y6sWoXK8DNPXwaCFBmBQEbWaumyDGaxddpB+FaSvTX0Hy9+bqVbHpZYTGBVI+U0cDqQO6C9GVOArW+tdzFOOTB0949TlxfTaNUnmZ5Is8F1f9V5QAYwAn1Cyrl8osmVdvxCGdf1CxQPM6xfl/fWLisf6ZZ6bCuYGakmXB53iOMGBCa7b68a7lojrJelHP19bAsYkywyXgGYHPlBlfCYTt6REeYGEM2gJGpJ05JTfFbZdG9e0XoFPsYF9LHL1m8cVlainLqrGoQCthwE307hCfm1R3nVqUU3wM7/idct6hMQgxiMkfoPAeoSMqcbv49jOom8wTIfRdxiW02iEkf+64jntnGG7wymyVodVGN1dtq7CCMO6CqNbLOZVuMX9VRg/u2tdhc1zU6/piO0QCSGsZ0jk6DefITGIaS+QtveLsM6N+QSJq+VYj2xvUKwntuRwYDNj9IsYxuNa8lho8Liaz+XJxdeQXFwN6es9sjsakofWIle9VWvtGP0ihk1rfWIobzTF6KnAuwqbowLuG22OCrD05cp3qs+1q2cW43Mz0CYrJ1n9ctY7pE8wsmQQ5NzqOUbaDfjB8WA5ruWmIqC/Mx7ggNNCkdVPafvT+5kDAyX0S3mY3i9jyOQObU+nIMhPb5sWlHvL6a6jnFRiSPgAQbas+pnnZwTUi0iShhRJvxL1wUjEktYuMeVTjJjRIz6xJ5nY8a2m9jnCtqvmb2qQyZlmfOv3VeNLb2jf8CGG0fDTdqQ/w1fixKEwPttp6HRbz9uunqNeWPUcYpj1HMWhrHqObkKkFORQlZSOjuOnHYNkUBPROQa0llLkrDq+VV9erQWNrNVaIIbRWnL/Kn88jAhpf+LTiBTkQ+ck88tqw53G2FzDqPsY+q3KZwxgu0UOvKUp243JjEDi6npIw/wEoYqzTGVMvCAA7WriEG1UryHIu99NJ05eQ+B8igAruGVJMiy5nWOgEOAIlsh6wJFOMWJG4aoZX5hmktTB53dQ8q5uYQybdr3BMOnXuxFpkrSc9BuoGyh8FeWIJP9sgkK7jMIrDbvmqyi0vA9ULo9LXp7MEsgFpV9FKUnO2iXHyyjr4d3CfB1l9ahe1t0i9BhLuzzTpcupjEK4aovUJKxRrmK0JG7efBkjCEbZxuBwuR0SCGBsySj3MUpZ19z32wE4kmiX7RGCjeshgonpUX6EleftGHwNw8jxGMPG8BDDyO9wX9NlT1J6a5cwMovbcXyeazneL5MERLme75djbrtJVgWn4Mi2vYWMmoFcqFTvE1M1hcX2DAK9ZG2dynQ08/l4iAoMppXHk7W77hUEubhjKCsYoq8dPXUIjmwTF0Bq+tD8yaGqifNxfPIpBj5mLiUZ3/DgjS4QdiHlEZJRIPXRqcvwrfp4b0nRSQDPDUEYlOUqF2keecaoCa4vkhdf9XWwTzBYFO0hJ+IjjJ5lA9LVPdlnDPz6QJCD981zxVdR1l2h8d0uoiSVBDAI/1zVSihoL1NlH0KnPjyMYfMkvsEw+RLx7bam7mD1cJoFVGB6VJTtTI/n/iqMkWQN7ym1K/4qamrT3fmipo2tpfg0WSe+vOoIClMZ/YAYw+YHLLF81Q/4OCLx+rjSQknpIkqUK0PjuyALjs1hdtr+7MAigw6z8zAiVC/PTlEo5/zatjmtbTMa7slR1eanJ7UnoCGo/I0tVoQxBi1mmZvKapP1GUqVfK/xzfEqymL6qvPoPhnbVpeW9HweUYSVumtQ/QmtX0JJSbKUUw76BByuYcR0DYMkNTgRx0sYo/1JDgUPPqdHjB630wAQRAlRjp667sWN8s0YUY6eg9vKKcbwFvZ9es59n55L3KVnOB5JGKA8VBR7GQ/0qlLpQepD6LIMv4OCtq2StTb2Nadn4DcNWYUq+sPp5rPurPNNSO06imR9B7o+tF2SaQOHc6VHGFkSLUpGGNtrZ99eO2ExE2NmAcSwZhYU6EkzZhbEiK6AkaQWNN2U+OzsLcT7XAQxjFyEqgrauOjNgLAK/VYwILydCJhhRpFsAHJ+OAnQczvQ9SBbAl5B3hpjAh7GsK28MZEDBtpXxXX8TUWPan7uDdqLLP+kihfV5wsb3cF2cTJfFV4exxFVVSzHj2BaXj6Bpq7XfgyzmFGnLLzAoBzH+XTizzQ/JHw/R5/g7VhZKdLAOwfBHVp3l8e3vtL20biMWN46EAS1Z3yBOSJe38Z5uEOZ+XxsMMo4DNxRkjq0/Q5Kx6615VlLV1HyuoxZ9GXMz1BUJhepRJdXFHQRy1qlDA/uirOl3NDg7pcEiaiYutUBS7s7LtwT45brzXBY91zNg7ehJRurGRQY3zLeoyywOoPtHiXEMN6jLGhbbr1HCatjGu9Rlo49WrZ7lPa5AaYHlcRYzOD4KRCcMhUzQPdkeVWg44fL4fkDkBriXdOqLojwEYi5mAEEaRIWHp46BPKmQuC6P9VVSsbL9XK8/JWy1r+iYm2fwsSyYAq47I6HV+7dci3p6hzZXnOOFd5iMNWbgEuosdyEeacEqk0QjE/Zqk1QhD4HY7UJwpfCbKMKZ9f24PcbdQ1ZXQ3V2/PPtD7SMp5YL9tgXHV/ByQwHrjNIdkp6WTtz3ZKkjGnMxlfIPBWWNoRc728oS5hXWpI0WNbjlDenJ7CCt09LB3Ppx5yuKBFDhe0KNXvYhi9XG/OtqvELeu6sq/Dmrdjsxjj5nNYTQE6i1E4rpCm9nV9htJIdLbR5bZ0CQGmEOJFFLMTA7dFZY49UvYLSnU4qGMU60Edo1gP6uTxstabwRX1jw/+tw+HxUjab4bFSNr2KUIo6Aq71VOL9jyVZIc9wvk6nJc+cObHdYcqp/LPi858I2eX7auGMcLzrezPGz9kGj6PCG97dCCEzaMTycGjA0GsHh1CGf72KBoseyux58QZTA1R3fcLEQqBWf1ChAr+Gf1CEMPoFyKO+34hgjEwm1+IUPzK7Beyz01Fc1P3HUPE+5Wt3rXEVuWSuO2fj9FbC2YXFUQx+6hwW6xOKoxi9VJhFJLljzkEgPLmiRBV5qcncF5/h2N1mmEcu9fsHY7VbfZmxo1+szcoRscZtCajjweatdV1hkGsvjP0BoOVG1rx8J21vD+ueIaNzrM3Wmv2nr3BMbvP3uFY/WdwU2nzn+F9qcV/hsIl1nNLgHcasuSpJtIJVeUDkCo3V3N/qL71Acg4YRcxH+rnINT3U7uCQyQ67Eeiw34kOnhEooNHJJqDQ/2sGOGGVGWZx3quIhHGxJeHthd9Uo8fgFS5gx8f3gl4BmH0doIx3Y3RY1nGdDeMYSQS9M5y5LoeEOMazycYuR2qOIVKzf3a3BSW2yKlFjQ3cT8VkeN+KiLGsDqnUB16kuUqjT3fud1wdNDW6KCt0UFbCYcow8pF7JFOvWQu8XAcHhFf9fC6aZ1/Wm84wYraWe6s1HJ+zGZY19fojGH0tpPRGQMxjM4YTrzvjGE0OUZnDKNnt8zOGPvcVDQ3UEskW3w0pVwDyVH6k2Ovl0HCPkjmtdlTiYcvIGjhevAtUbrakpVjnfvlltiKwNu7g0Bgd4qs5VmHVV5b0r/eEnnXO49AmgPIVdsZJ4sqIA1oLLqaFHkVsq4JMgo8b0nYN1cGZI/yN8zahkE85rjG1R3ESvANo1CVf4Auj6xcuMgNqRt6MMvoB2JY8tzqB4ItsfqB8E5p1bQfOnN6pGZcRqmrSxv6be5PUKzpGw7JzEwOj8Iw7T8KAzGs+yR2eBSGef9RGGaPR2Hsc4OCVg7JzMwO1EgeyczkkcxMHsnM5JHMTD7JzOSThUweWcjkkYVM+1nI5JCFTA5ZyIwyqq0rKEr+ta+gDrnd5JGFTD5ZyOSThUw+WchvfIbr9iSDMijcCKJITbMbCl1CMe4tssONX1iPpS+XfU/g0iTKihtjcNe4yg3cs+UOn+DL95WUWCeXPmLglwDUtUtdPTPxByBV1q/h5QrnINzzt1HmVuquau0qSl2PTelyRr+DggpxymJadYDoIwz1CCa1ixgjqrfyLZT1/Q4K8tobE1zxwPYVg+gJ6Rt6UrdJ/uTwEq+Fo3+AEQfGSrVl7et+Zn0Ew6vYFLNSlOemVFxS0HZRAxbekSqaOat3ReMztVUU7jISCjoWE0lZlnHw4ksQKzY7Pss1CFNH0AupZmaEIFZOqzAb1AXFzIwYxcqMFaXaGpkRYhiZEWKYmbGi6J2VGfHAWpmxkwcNpH3r6XWbBiCEjQYwhKUjKTjQAAYxG3Cq30ax0wBEMdMAuu5ipQGEYaUBXCPGSgM5O9AAHFgzDaAQEy/HlmpHac+9QW/hZTlAlqxvhxR6Unx2OOdU9Hyb1Yy7hxl3DwMs8dsodjOGKGYzRqVQrGaMMKxmDEuymM0YbenNZgwH1sOMu3guu3LgvJoxCjBRlMgqjf/y3IzR7V67GVPaNmNYh8tqxtllO43uefmg2M0YopjNGIYhjGaMMKxmDG81mc0YBbzMZowv89nMOKEEwbRAkh6VV0NmFFoNko9THurBPxsyPHeZDZm33QQJJjxaDRmCmE2Q+7dR7IYMUcyGjJ4QsRoywrAack0ehlzJwZC5f9mQ84qcDYOpwJBR2Ks0KaBQug6ePRuySwDhKEC/acgeAYTkEkCoLX8bxW7IzSOAUNt+AAFiWA25eQQQanMIIOCBtRoyTNXN67mKrF6t7E8ZNbXDypyqPPzqDOcPMEioQGfCfIghb2aQetbwMwyWcgMPVeovY9BVDBkPvjweLOPBl8ejSl/q5fHQGFfHQz/ld3U81psq9fJ4NOlLuzweGuPqeDRhkFYvt6PeCbG1q+3o4b5G9MvjoTEut0MuuXXAQQndwrAmn0EQc2GAhkIgNcrUVP0c2e+gIDcs19/h5REZ+aA7xpyxNyC2hDwMYkzISzAH3BSMwRCmYMwbCNtm08OLWzzOey2lb6OYN5sYxbrZbGk/JgsxjJtNiGHebLbkEJPFA2vdbKL8fPNRreXtmGwidrAeCGLW+1y+jWK3Hohith54IDdaD8KwWg+st2e2Ho9ihnhgzUc1/CS2XH5g/VR5j8/9gZ4bKSmQY9G7rWcQqCjqZop+/7k+g8CiEfIAvC7m8RGE3H1g/SbvZxBB9nynrUjoUgqFtJ7wejhXPDcDeQRILnMVXUNjA6SfgbzRMrkKkqoqsPqqZSjAFcsqXFFyO+8OWi44yLUjjrqExgsILKKT5CX5GHPoLjAxnQ8u9Lb0NSzKbp68LQm+8L2cHD2ebupHb9r2wYA9llB2WUI5fhvFvoSyRxpB4/00AohhXULZI42gsUMaAR5Y8xKKHIQhLKomxbLPSYGtojuzcsIv6urEs8e0oWzYLAfikrTX5IkHUCvsm+matzfTCMLMBNUjYtEqfxvFzgT4KSIrE6BK/1YmQBhWJsDPsliZwOMJLzyw1oQidP8pNRmUrG+ovRReavA6l3rer6ln417rtnjYcdvO743oErA5zZ89coFaD99GsdsxRDHbMbrtY7VjhGG1Y3jryGzH6BqV2Y7hwFrtuLlYD3zMy2Y9zcN6mof19JC+jWK2HoxitZ4e9h2yEMNoPRDDbD09ODhk8cB6rIJ5vRyeHzLbn1dBBFLCCv8HTucgPaZvo/BxiL8HiU7vaGOMVW6Pe6oXMZZzq9M5BlRYcaH0dFnppYZar7RvOAgD8lqWm+KDJuNFkNQkeTQHRCXJIRkWgsTjneUfZ1BpF5sSo8xOjI2uoiifUu6X20KrSAKpQqSfovAqaNP65R4tassJ9mg/hxtiWNeM5JHD3fPX1TYLK8VM9eqgGHkJYhh5yTg5kJfgltrWF4xh64t1a48w2INj2YVji4eyFheOLS4cW1w4trhwbHHh2OLCscWBY4sDxxYXjqWvq62ZY4sDxxYHji0OHAvdj0aOhRhGjjW6QQEG9lIbOfaNv9zKsR6XuiCInWPZhWPZhWPZhWPZhWPZhWPZgWPZgWPZhWPr19XWzLHswLHswLHswLEw2GvkWIhh5Fhj0BlxLMwJsHIszk6wcmzzUNbmwrHNhWObC8c2F45tLhzbXDi2OXBsc+DY5sKx/etqa+bY5sCxzYFjmwPHwpxUI8dCDCPHGnNjEceSB8eSA8fe3mnfVlYMYuXYdyg2jn2DYuTYNyhGjn2HYuPYdz2ycexA2eZYjGHjWIxh5dgU4tfV1sixbwbFxEtvMEy8ZJ4cyG1pP+aFMYwcm7ZjXvhylZVj8TUvK8cmD2VNLhybXDg2uXBscuHY5MKxyYVjkwPHJgeOTS4cm7+utmaOTQ4cmxw4dj/m9eby6SqDxirn46P7q+s5Jl2n+YO71taHBt6AGN+iwGVBbGsOxrCtOdbyJHBug8eaEzzWnEIOxotA7GsORrGuORDFvOZAFPOag1Gsaw7ukXXNobS/5lDaX3PIocTWQPm62prXHDgoxjUHYhjXHOPkQG6raZ9ja9rn2LrdF1xqz8qxuOiflWPZQ1nZhWPZhWPZhWPZhWPZhWPZhWOrA8dWB46tLhxbv662Zo6tDhxbHTi2OnAs7fvaMYaRY2n/jALrEls5FldItnJs81DW5sKxzYVjmwvHNheObS4c21w4tjtwbHfg2O7Csf3ramvm2O7Asd2BY7sDx5b9PAuMYeTYsp9nETz808HDPx2Dg7JCEDPHvkExcixGsXIsRrFy7BsUI8e+6ZGRY2Pc51iIYeRYiGHm2Bi/rrZWjsWDYuNYjGHjWOvkQG6DzxgZORZiGDnW+JwS5NjowbHRg2OTh7ImF45NLhybXDg2uXBscuHY5MKx2YFjswPHZheOzV9XWzPHZgeOzQ4cm/c5Fr8GaIkBvoGwxAAjylPMkeX2eVIxwNd3XFBBQ4kj1jWx5eV10/2cE4xhXG+Mr3hijP315s1zr9b1pnQHwy3dY73BKNb1BqKY1xuIYl5vMIp1vcE9sq43xPvrDfH+ekMOL3MMlK+rrXm9Id5fb4j31xvazkt48wi1ab3BEKb1Br8gb2N6jGFjeutL9gjDI9MjumR6RIcrXRjEzvTVI7sQo5iZvnpkF75BsTJ99cgujHU/uxBiWJm+emQXxvZ1tTUzfd3PLsQYRqav+xncyJ3FJM8W8aqqOEK5H0CULhDlFAK9FmtrBEQwtQEVZEzU7i/kpQfDjcGOwV1qynHP1zDa4vge6BLGWBukZnxI530Z5zRGKHJUy6HliyjGCl8Yw1bh6w2GpcIXnJmqKq2XcG12HzDKRYy0MPL5vCTopcypy4uQOZaT8XiDkWWxy7nVc4z8XYwSpS8lxWtzKxXWU9XFEz+aF3ndINV+kUF0O65iNNl5j8+rGLJ3wBjbrN62WX1smdEaebwq/LNYA+7AGFIrdHz2c4zt0XiDYRoPlLdEVUaDqn7n4ekBDYwhOjo+L2K09QZHU7PyGUZbz0fqN+Q+wlinVP1I2WcYYisD7mI7erxr2Pi8Oh6dFsb5vKDHKgqtTfY4yexj1HINg+W4XJjCRYwqq0IFOoayFusy26H15+WKU0r4nRcZEQ7KF0IftcRUOHnWNT73ylgKJ7PD8+fs8Pr5+K3ybRRr2eQ3KMayySntv8SFMYwH9uTxEldKDi9xvRlYY9nkWj2MuOR9I67Vw4j3n6NsDk+ft+BhfqV9G8VuxBDFbMTI8W01YoRhNWKEYTdi9I6W2YjhwBqNGD6jpZ8CSue7rNEdFAVP8nwcJfUm39guPYGA7nBN6y6s8n0/geDeiPuPQu2gN/AlO2tvUHE2j95EeWFpfF7bNVKO0pec8jWMtNqRyAOjXsSQx60f5+UjjConglQvjymvMU0XMdLCKAHZXdz2mGMMm8fcSqwAozkE8ppHHC95XMuCIOY43hsUYxwPo1jjeBjFGsd7g2KM473pkTGOl9p+hiDEsO4omkeGYGpfV1trHA8PipGV2n6GoHVyIMZ+tbs3GMa+7Fe7Y4cL2+xxXzt5XMqCIHaG7S4M210YtrswbHdh2O7BsDnsMyzEMDIsxDAzbA5fV1srw+JBsbESxrCxknVyAAZ8UDp3UbTyEJdPFzH6NYwikZMR8I4XMZa7pDBfxVh9qeEihrjDBjPmixjyhnocPoJzDORQoyb+tHINYR34er6IIMffXjYRRvDkGkKV+GJolxA4ii8h9902lPPZRN4m22xCBNNsYgTLbNoQ0GxCBNNsIgTbbBrbgGYTnpWL7Aa1TyeFp9Usozs4xmwXjGHLVMkonOGBYct2wcnIshyOvXxAY4p8qeIt5xjO3IawGWUlzOh9yu80o+87QTNqitEJCntDSRR1eA5Pe4MxSEaE+HxEYkapbsOhHwSFwkUUY+Jedkjcy/uJexnRmCn1BiKYEm/Q5WRjG8JuG6Dzs8t2q3cdfXyKYGKMtZPuug7oE0Y8Xqo9P+cctaJ+DjpBnWc/w7HqaHDQ0bCtowm+893U0a9lUGEVo0ge0Q0ln6LAC6tGPcEYRj1J3UdPII5RTzCGTU/eYFj0BOVUrP2UOvsNL4wVgCTwT1WtlWRuwXDLyt6hdhUf42qFaOGuXk05BZ7jScdO6ZwMZRx1nO8jCNl8cGtXIe7rbA2nrQADkUW5S1I7KE5mdVhvcOsESM5mdeAs6nANoK4cTL4CwCH+3i7yGgBdApAx4GtjwDIGfG0MqnShXhsDDXBpDKqMQb02BlXGoF4bgyZdaNfGQANcGoMmXtNWr7Wg3s25tUst6OHOJ/3aGGiAay1oa+W/pAfHq8lzDNT1BTsl9sziRa/nrIzeZo4xlBUr0W70p9NcQBsPtY9ivUjZWSFJ3IeTciPFQM+dYTSeMiG5XGlGSnIXbDj8E2oGjMnVFZPra0TrC0hHTpi0nDAhnoKUgGaGSl4O36LO6i9JlAVXaVIpkOqQPFxAzygJevTj8uiXqyiFm3RJGe7voDik6uFhyesCUm7nw4I0LvIaWaT4JeAc5DUoIdMaFW4fwZS8ThBF7/3tZJApC6Fk5gq6FCFOiiukpkglPE8zeslqzIp4RMc3h/OBgaX9+rouUgfZlysDM4JYYovlIePuaWAQSCzt9yLbFJ57A6OVkqUWtUezp09ASly9UcvGKwi6OZdlWG/zuBw1PT6jQL5d+QtFnS1yeWkLOp+Q5DIyh3DuUigJbe2i7GuGl7QhFHR9X3hFH1WGM/6jUZGyJKmoferrqCAnSeWl+FU7Wl7Wj1RQykCWLXPRRPmKAlQui6elRBAfL8njXceSEFFaE0wwijUdoyTby+90FcOcSlE8nrSydgc+FAQnefkaHksLvHaneExPpv3pMWLgMUHGs+Jg8fK4Wu+fFBSDMt8cKSXsj2sJHmpfkoPaw0Ex3vp4s56WdRP9IRL+sp4W8uD8wh6cX+o+5xeP/MbiUmivuFzhKvC6ktmEHB6mKi4PUxWPi1N4UHxMaN06HGsHAxNCV6dylFy+fKv4uZxDzyDwJpicumMv5253CJKCuLlSSOfu/wLvTlmyF961Y21HA3fQjvTddsR1Zo+tXBxUdWrfAJHcqw0QzW0J6AjDjeiik+GjuQhS4spPTC4gdBUkrWzLUi6DyEm7UHfoznWQurrT2j4IhasgFBeIugn9AlJ524ZxO8T8hg2BCa5tux14rVgFqliFd1/XCnTBjZaLioIuAcIfgawaMeEhqPQMgnayJB6qwsUFpJ+DWEe2BuQYgk/8FFmFY9EFfF76A9/hlZgA11IvgrSV0vRQOucjkC5V96quVPcRSE3ihK85XgYRNhkHhHANpAUBaTEBvYcPSsVE4sy8ndhdYGK62KUsi0bLjNpCPl0ily5F4y0o4Oe1+qzVjvrFZ43CYatsVFOhzhdfJgWYv7Ey1cu5V5VCdDjVEophGU+1hOr4mU+1hOJg5lMtbov1VEsw0dF6qqWwX9OHgkdNHwoO5dbxoBhPtcgA0+pNKudBI0IhsBGslnTr8V3PI2kUUWGgEdeWYmU5qfX0FabsmzJiNrspR943ZbjbSXLFLKWKzOeDoeV0cYZGP7qo7cOdic9g1l2U8Q0ir4QiYSplTh1MXyc6pe1oGm6HUeFcomDkEAUjF0c+wfiVma/TftF0iGHn6+xQgw0PitUL+Yn1qBPDJ5kYK/enqDPUC+3DuoFpVfrOOgH5eUxQ/Cq1VYS5qRcyXkGAzpYo1VjHhrVdBDnKMUyQpGJpn4JEB5BF1hgEDexStnGs69dAhq86iK865qsgkl09TpV1HySpFIwnEJhkQ0vn6/lZg1D8a/inV7pbYJXR+LJ0FbidlSh0bFkfkutHjVnpxuO7gXUUxZ18MpjWUZDUg2Qvg0s4P6yu7CNS50GOH8GsOM34Vgb0CoN2tVVuFeSmXMXPWZZEKIeW1BmZSkQrO7yd32SHHXVt5JfMxjetMed8EsFMGWPOJxEMLRhzPjGKNeeTPJ6/wsNizPl8q75NMi2zDrK/qC9D9ZWkjocbTvxRU1ZBl/Gtisu8NgVtbkOVGnzjW8UpXngKVm628tS71qzc+hpDARTOphpPY2FUa7T9CtmILawwQ3xKhv3XIf7yp7/89m+//u1Pv/z9L3/763/d/mUKN9W6MUqKN7fY7SZdSvKV5avIFx1fQxcSy1c9voY5pCZf/fD2jQblIF/Hb9zO2vn4jdvBIGf5KvJF8sXydfzGLd03N/nq968S5CvKV5KvLF9Fvki+WL7kN4r8RpHfIPkNkt+g4zdu22fK8nX8xu0yHpF8sXwdv3GjDjp+40YTdPzGbenl4zdur3ny8Rs3KuIkX8dv3E6pXOTr+I2bd5tZvo7faDe84zdu5fi5379qkK8oX8dv3LbfNctXkS+Sr+M3bupeq3wdv3G7K1GP37hpUwvyFe8z2GTO2/yNoQetyNfxG7fEscbHiWUoeqvH1+hRa/LV7189HOej8d/1KF/p2PeNMe35+Brt6+X4Gm3p9IefO/id5c+q/NnxG7cZ7Mdv3FKFxnb1+Oy3z7g+j5+5OVKGya3Psj6PX7rN6DgjHp98+6zr8/ixo5LAf//y219++fdf/3wzyJvN/uOvf7rb5xD//n//8/43//7bX3799S//59/+87e//enP//GP3/58s+XDjMPtf+L4338Zw5vizdbjz5//yyCQMQ+RKLZ/HSZz/Mlt/Mb/pv6vf/z5Z6O3+Y+3/739RzHO/yrf/mjsom94SX5ihNx6v/1Rlj8aR650/FFZf1T/mNPtj2j9Ef0xh9sf8Wtz6+2Pbo0bVlXSvVljj0J8++u2QOIf0/ijG6H9Pw==", + "verification_key": "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\nAAAFiSRi70jt/BTMpcaOrm4=" + }, + { + "name": "constructor", + "is_unconstrained": true, + "custom_attributes": [ + "public", + "initializer" + ], + "abi": { + "parameters": [ + { + "name": "admin", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "2233873454491509486": { + "error_kind": "string", + "string": "Initializer address is not the contract deployer" + }, + "5019202896831570965": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "14225679739041873922": { + "error_kind": "string", + "string": "Index out of bounds" + }, + "17618083556256589634": { + "error_kind": "string", + "string": "Initialization hash does not match" + }, + "17843811134343075018": { + "error_kind": "string", + "string": "Stack too deep" + } + } + }, + "bytecode": "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", + "debug_symbols": "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" + }, + { + "name": "end_vote", + "is_unconstrained": true, + "custom_attributes": [ + "public" + ], + "abi": { + "parameters": [], + "return_type": null, + "error_types": { + "8095637994846897154": { + "error_kind": "string", + "string": "Only admin can end votes" + }, + "13699457482007836410": { + "error_kind": "string", + "string": "Not initialized" + }, + "17843811134343075018": { + "error_kind": "string", + "string": "Stack too deep" + } + } + }, + "bytecode": "JwACBAEoAAABBIBEJwAABAMnAgEEACcCAgQAHwoAAQACgEQlAAAAPyUAAABAKAIAAQSARCcCAgQAOw4AAgABJiUAAACXHgIAAQAeAgACADMqAAEAAgADJwIBAQEkAgADAAAAaSUAAADAJwIBAAEvCgABAAIeAgADAQoqAgMEJAIABAAAAIslAAAA0icCAgADMAoAAQACJigAgAQEeAANAAAAgASAAyQAgAMAAAC/KgEAAQX3ofOvpa3UyjwEAgEmKgEAAQW+Hj//PqT2+jwEAgEmKgEAAQVwWXvdIQFEAjwEAgEm", + "debug_symbols": "tZXLrqMwDIbfJWsWjp2b+ypHVUVbeoSEaMWBkUYV7z7OmSaFRbKYy6b5A82Hf8dOnuranZfPUz/e7l/q8PFU56kfhv7zNNwv7dzfR3n6VBB/HKuDaZQ36uBlkJmGRgUvo24U4+9RAyRhRTgRGpJwIlgEanVAiMK9BJkkhItWhIlP7Lo2KoVymqeui5FsYpOIH+3UjbM6jMswNOpHOyzff/p6tOP3OLeTvBV2N15lFOCtH7qo1ua9GspLNVnC13JNzvmMEI87iK5AADMDDG4QuENgBeE5uMTwzDZDHO8YVGYQEoQXQzSaEqNqhTmFoTUXrdh/YMX9bys25F0J5V0JZYT3ISF8MMUguGKEDOhkhIz5WyMay0ZqZc4+I5hdRth9o2isOfGYjfCmT4LfM2oVCi74BAEPoZgNU4PAO6UABoqQSpFK29sMsRSK+1JJKgKkjCAgFJPqa/uyOX7YVryEarN4+24Whj/wsikQ8UIlL9VsMCWC1r5EwEqhE+fqkK6hYolhrUxRej0nQ47jUjKwVqfa2HQMkra6mFGs1ak1DnKJWdA7yFFm7aWfdpfxGmlT356H7jW9LeNl83b++Uhv0mX+mO6X7rpMXSS9b/R4MX9gaIiO8XaWCfmG+LjGT/8C" + }, + { + "name": "get_vote", + "is_unconstrained": true, + "custom_attributes": [ + "utility" + ], + "abi": { + "parameters": [ + { + "name": "candidate", + "type": { + "kind": "field" + }, + "visibility": "private" + } + ], + "return_type": { + "abi_type": { + "kind": "field" + }, + "visibility": "public" + }, + "error_types": { + "206160798890201757": { + "error_kind": "string", + "string": "Storage slot 0 not allowed. Storage slots must start from 1." + }, + "576755928210959028": { + "error_kind": "string", + "string": "0 has a square root; you cannot claim it is not square" + }, + "1004672304334401604": { + "error_kind": "fmtstring", + "length": 48, + "item_types": [ + { + "kind": "field" + }, + { + "kind": "field" + } + ] + }, + "2920182694213909827": { + "error_kind": "string", + "string": "attempt to subtract with overflow" + }, + "3206131020419630384": { + "error_kind": "fmtstring", + "length": 75, + "item_types": [] + }, + "3305101268118424981": { + "error_kind": "string", + "string": "Attempted to delete past the length of a CapsuleArray" + }, + "3738765135689704617": { + "error_kind": "fmtstring", + "length": 58, + "item_types": [ + { + "kind": "field" + } + ] + }, + "5019202896831570965": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "5727012404371710682": { + "error_kind": "string", + "string": "push out of bounds" + }, + "6485997221020871071": { + "error_kind": "string", + "string": "call to assert_max_bit_size" + }, + "7233212735005103307": { + "error_kind": "string", + "string": "attempt to multiply with overflow" + }, + "8270195893599566439": { + "error_kind": "string", + "string": "Invalid public keys hint for address" + }, + "10676044680617262041": { + "error_kind": "fmtstring", + "length": 98, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + }, + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + }, + { + "kind": "field" + } + ] + }, + "11732781666457836689": { + "error_kind": "fmtstring", + "length": 77, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "13649294680379557736": { + "error_kind": "string", + "string": "extend_from_bounded_vec out of bounds" + }, + "14101993474458164081": { + "error_kind": "fmtstring", + "length": 61, + "item_types": [ + { + "kind": "field" + }, + { + "kind": "field" + } + ] + }, + "14225679739041873922": { + "error_kind": "string", + "string": "Index out of bounds" + }, + "14657895983200220173": { + "error_kind": "string", + "string": "Attempted to read past the length of a CapsuleArray" + }, + "15200354114977654233": { + "error_kind": "fmtstring", + "length": 144, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "15760694058516861966": { + "error_kind": "fmtstring", + "length": 128, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "16218014537381711836": { + "error_kind": "string", + "string": "Value does not fit in field" + }, + "16446004518090376065": { + "error_kind": "string", + "string": "Input length must be a multiple of 32" + }, + "16954218183513903507": { + "error_kind": "string", + "string": "Attempted to read past end of BoundedVec" + }, + "17226037485472400844": { + "error_kind": "fmtstring", + "length": 132, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "17610130137239148460": { + "error_kind": "fmtstring", + "length": 98, + "item_types": [] + }, + "17843811134343075018": { + "error_kind": "string", + "string": "Stack too deep" + } + } + }, + "bytecode": "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", + "debug_symbols": "TL3LkjQ9b6R5L996FgmQAEndyizapqcPJjNZy6wPK918V8AJum/0Pa7/LToPAc/ISFTWf/zzX/7rf/4///0//ev/+G///r/++Zf/9z/++c//81//7d/+9b//p3/79/////vf//rv/+Pv//sf//y+/zPOP/8y/p9/5p/Iv//YP/+y//7j//yL/f7+O/7+63//nX//nX//jb//fv8s73/X/e++/z34b/zuf+3+1+9/x/3vvP+948UdL+54cceLO17e8fKOl3e8vOPlHS/veHnHyzte3vHyjrfueOuOt+5464637njrjrfueOuOt+54646373j7jrfvePuOt+94+46373j7jrfvePuOd+5454537njnjnfueOeOd+5454537njnjme/X4M1eMNomA3RkA2rYTf0yNYjW49sPbL1yNYjW49sPbL1yNYjW4/sPbL3yP43sv8+GA2zIRqyYTXshnNh/BqsoUcePfL4RrYPoiEbVsNuOBe+MgJ8I88PvpH3B6NhNkRDNqyGv5GHf3AufCUFsIa/kcf4YDTMhm/kb8e+wgKshm/k88G58BUXwBq8YTTMhmjIhtXQI2ePvHrk1SN/hTa//fkqDTAboiEbVsNuOBe+ggNYQ4+8e+TdI+8eeffIu0fePfLukU+PfHrk0yOfHvn0yKdHPj3y6ZFPj3zuyP7V4BwfWIM3jIbZEA3ZsBp2w7lgPbL1yNYjW49sPbL1yNYjW49sPbL1yN4je4/sPbL3yN4je4/sPbL3yN4je488euTRI48eefTIo0cePfLokUePPHrk0SPPHnn2yLNHnj3y7JFnjzx75Nkjzx559sjRI0ePHD1y9MjRI0ePHD1y9MjRI0ePnD1y9sjZI2ePnD1y9shfDc78YDXshnPhq0GANXjDaJgN0dAjrx559cirR64aPB9Ygzf8jRzzg9kQDdmwGnbDufDVIMAavKFHPj3y6ZFPj3xuIvnZDTeRxu/XYA3eMBpmQzRkw2rYDT2y9chfDcb6wBtGw2yIhmxYDbvhXPhqENAje4/sPbL3yN4jfzUY+4PVsBvOha8GAdbgDaNhNkRDjzx65NEjjx65bifjA2vwhtEwG6IhG1bDbjgXokeOHjl65OiRo0eOHjl65OiRo0eOHjl75OyRs0fOHjl75OyRs0fOHjl75OyRV4+8euTVI68eefXIq0dePfLqkVePvHrk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YJYMZslglgxmyWCWDGbJYJYMZslglgxmyWCWDGbJYJYMZkk1Y9r3xaVe3ZiNgziJQUziIm7ieVhZcpFuk26TbpNulSXuhUlcxE08DytLLhrRiYM4iXQLugXdgm5Bt6Rb0i3plnRLuiXdkm5Jt6Rb0m3RbdFt0W3RbdFt0W3RbdFt0W3RbdNt023TbdNt023TbdNt023TbdPt0O3Q7dDt0O3Q7dDt0O3Q7dDtPLfq6Gw0ohMHcRKDmMRF3ES6Gd2MbkY3o5vRzehmdDO6Gd2MbpUl31f+erV5Njqx3E7hJAYxiYu4iedhZclFIzqRboNug26DboNug26DbpNuk26TbpNuk26TbpNuk26TbpNuQbegW9At6BZ0C7oF3YJuQbegW9It6ZZ0S7ol3ZJuSbekW9It6bbotui26Lbotui26Lbotui26Lbotum26bbptum26bbptum26bbptul26Hboduh26Hboduh26Hboduh2nlv8fkQjOnEQJzGISVzETaSb0c3oZnQzuhndjG5GN6Ob0c3o5nRzujndmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglmSzJJkliSzJJklySxJZkkyS5JZksySZJYksySZJcksSWZJMkuSWZLMkmSWJLMkmSXJLElmSTJLklmSzJJkliSzJJklySxJZkkyS5JZksySZJYksySZJcksSWZJMkuSWZLMkmSWJLMkmSXJLElmSTJLklmSzJJkliSzJJklySxJZkkyS5JZksySZJYksySZJcksSWZJMkuSWZLMkmSWJLMkmSXJLElmSTJLklmSzJJkliSzJJklySxJZkkyS5JZksySZJYksySZJcksSWZJMkuSWZLMkmSWJLMkmSXJLElmSTJLklmSzJJkliSzJJkli1mymCWLWbKYJYtZspgli1mymCWLWbKYJYtZspgli1mymCWLWbKYJeh7/f7AiaPv9eImnoeVJReN6MRBnMQg0s3p5nRzulWW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3wVTnUezPtmqzqNGJw5ijXsKv3HXr/Abt24tq/OocRPPwyqculWrzqNGJw7i51Zvf6vdaNZ702o3mvVModqN/sKl8LOoN23VbtRoRCcO4iQG8XOr907VbtT4udU7wGo3ulj1dtGIThzEz60++qp2o8YkLuLnVp+IVbvRxaq3i5/bqZlVvV0cxHKr4656q081qt2ocRE38Tys18KLf25R7wCr3ahxECcxiElcxE08D7/XzUa6Lbotui26rRq3lrk28Tzc9f+ta2efh6fcam3HiE4cxEkMYq1tF9Yc6kI8m3guRjUANRrRiYM4iUFM4iJuIt2MbkY3o5vR7Sve+P7SdFRTT3wfvUQ19cT3yCCqqafRiYM4iUGscYGL+M33a2aJauq5+FVs4zeuzcIaIQoXsVZckxznHkBUo06jEZ1Y42bhJAYx78FGNeo0biLdgm5Bt6BbjIdVLQYcxEms3KkV113mxUXcxPOw7jIvfnPw2pKqlouDOIlBTOIibuJ5+L2wNtJt023TbdNt17h18lWFF8/DqsKLRnTiIE5iEJNIt0O389yqdabRiE4cxEkMYhIXcRPpZnQzuhndjG5GN6Ob0c3oZnQzujndnG5ON6eb083p5nRzujndnG6DboNug26DboNug26DboNug26DbpNuk26TbpNuk26TbpNuk26TbpNuQbegW9At6BZ0C7oF3YJuQbegW9It6ZZ0S7ol3ZJuSbekW9It6bbotui26Lbotui26Lbotui26Lbotum26bbptum26bbptunGLDFmiTFLjFlizBJjlhizxJglxiwxZokxSwxZMgpPoyNLgEZ04iDWy8wpTOIibuJ5WAFy0YhOHMRJpJvRzehmdDO6Od2cbk43p5vTzenmdHO6Od2cboNug26DboNug26DboNug26DboNuk26TbpNuk26TbpNuk26TbpNuk25Bt6Bb0C3oFnQLugXdgm5Bt6Bb0i3plnRLuiXdkm5Jt6Rb0i3ptui26Lbotui26Lbotui26Lbotui26bbptum26bbptum26bbptum26Xboduh26Hboduh26Hboduh26HaeW/VHNRrRiYM4iUFM4iJWXGXheYibEWDF1Sp04iBOYhCTWOFYbrgZAZ6HuBnZhUZ04iBOYhA/t++xfFQvVeMmnoeVJReN6MRBnMQg0m3QbdBt0K2y5HtaF9VL1ejEQZzEIJbbLFzETSy37+1O9VI1GtGJNW4dbOXDqBOqfABWPlysEeqEKh8uDuI33++5fVR/VGMSF/Fzm7Wgygdg5cNFI9a4tX1V89/j0qiuqcbzsGp+lEXV/EUnDuIkBjGJ5Va7UzV/8Tysmp+1k1XzF504iJMYxCQu4iaexuqaajRiua3Cz+17chrVNdUYxCQu4iaeh1XzF43oRLoZ3YxuRjejm9HN6OZ0q5oPK3TiIE5iEJNYO7kLN/E8rJr/mvqiWrAanfi5ZQ1WNX8xiElcxE08D6vmLxrRiXSrmv+e6Ua1YDUmsdzquKvmL56HVfPfc8+oFqxGJ35uq66dun+4GMTPbddZ1P3DxU383HbNt/LhohE/t11bXflwcRI/t+83e6N6tBoX8XM7NZ3KB2Dlw8U/t/zVdL77h8ZBnB/WdL77h8Ykrg9rOl+WNJ6HX5ZkPeeq1q5GJ35uVrv+ZUljED83w2CLuImfm9exfFnSaEQnDuIkBjGJi7iJz61auxqN6MTPrV5xqrWrMYifW72oVZdX4yZ+bvXKUF1ejUb83OrloHq/Gifxc6tcr46wxkX83KqkqyPs4pcljZ/bLDd34iB+bl8bblRHWGMSP7fIwk08D78sySi3L0sanfi5ZQ32ZUljED+3xGCLuImf26pN/bKk0Yif26ot+bKkcRJXR1s1fEXUj1U+XHTiIE5iEJO4iN98K2GqDSy/D1mi2sAajejEQZzEICZxETeRbotui26LbpUPq46l8uFiEJO4iJtYryK1zLrXuGjEcquLq5KgIrP6xBoXcRPPw0qCi0Z04iBOIt0O3Q7dDt3Oc6s+sUYjOnEQJzGISVzETaSb0c3oZnQzuhndjG5GN6Ob0c3o5nRzujndnG5ON6eb083p5nRzug26DboNug26DboNug26DboNug26TbpNuk26TbpNuk26TbpNuk26TboF3YJuQbegW9At6BZ0C7oF3YJuSbekW9It6ZZ0S7ol3ZJuSbek26Lbotui26Lbotui26Lbotui26Lbptum26bbptumG7MkmSXJLElmSTJLklmSzJJkliSyZBROYhCTuIibeBoXsgRoRCcO4iQGMYmLuInl9iXtQpYAjejEQZzEcrPCJC7iJp6HyBKgEZ04iJNIN6eb0w1ZkoXnIbIE+LmdWnxlycVB/NxOrQ2pUT+GfIhCI9YIu3AQJzGISVzEv/mu+pS22uwufvnQaET/sCb55UPjJMaHNfUvHxoXsdxq6nEe5o9oxHKrxWe51Xyzxj2Fi7iJ5+GXBKs+zq7mu1UfZ1fz3aoPmKv5btUHzNV81xjEJH5u9bFzfZda43m4f8RyW4VlUdP5yn95Tecr/1WfKFR33nL82CJu4nn4lX+jEZ34udWTverOa8x3GR1eUYdX6nlX6v79iEZ04iBOYhCTuIibSDejm9WCdqETB7EWdAqDmMRF3MTz0H9EIzpxEOnmdPtqftX7oWrfa9zE8/Cr+UYjfm71iK7a9xonMYjltgoXcRPLrWb25cOq91nV6tf4udVjt2r1a/zc6glctfo1JnERN/E8rHy4aEQnDiLdgm5Bt6Bb0C3olnRLuiXdkm5Jt6Rb0i3plnRLui26Lbotui26Lbotui26Lbotui26bbptum26bbptum26bbptum26bbpVgNSb7epSbHTiIM5+SaouxcYkLuImnsbqUmw0ohNrFbNw96tefRPaqqeh1Y/YaEQnDuIkBrH24Sun6jHEPlSPIZZZPYaNkxjE2t9VuIibeB6Od5rVbtjoxEGcxCAmcb05VM1fPA/nj2hvDqh54CDSjTV/WPOHNX9Y84c1f1jzJ961c4I7GdzJ4E6i5msOwZ0M7iRr/rDmD2v+sOYPa/6w5g9r/iTPDTUP5E4mdzJ5bqh5IHeSNX9Y84c1f1jzhzV/WPOHNX9Y82fz3DZ3cnMnN3dycydR87swieV2CjfxPETNAz+3er5TzY2NgziJQUziIm7i5/Y9j8pqbmys+4dVOG8VZrUxrq+pOquNsXERN7FPKH/2IxrRiYM4iUHsE8r6HrPGTTwP/Uc0ohMHcRJrFVG4iedh5UPUPlQ+RM2s8uHiIE5iEJO4iJt4Hs5+dpU/PEcETmIQk7iIm3ge1tODi0akW9At6BZ0C7oF3YJuQbekW9It6ZZ0S7ol3ZJuSbekW9Jt0W3RbdFt0W3RbdFt0W3RbdFt0W3TbdNt023TbdNt023TbdNt023T7dDt0O3Q7dDt0O3Q7dDt0O3Q7Ty3arBsNKITB3ESg5jERdxEuhndjG5GN6Ob0c3oZnQzuhndjG5ON6eb083p5nRzujndnG5ON6fboNug26DboNug26DboNug26DboNuk26Qbs8SYJcYsMWaJMUuMWWLMEmOWGLPEmCXGLDFmiTFLjFlizBJjlhizxJglxiwxZokxS4xZYswSY5YYs8SYJcYsMWaJMUuMWWLMEmOWGLPEmCXGLDFmiTFLjFlizBJjlhizxJglxiwxZokxS4xZYswSY5YYs8SYJcYsMWaJMUuMWWLMEmOWGLPEmCXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWVK9luv7jDWr17IxiYu4iedhvUO5aEQnDiLdgm5Bt6Bb0C3olnRLuiXdkm7VK1F3xei1vJjERdzE87DeoeSv0IhO/Ny+rpOsXsvGIH5r+7pOsnotGzfxPKx3KBeN6MRBnMQg0m3TbdNt0+3Q7dDt0O3Q7dDt0O3Qrd6hZO1ZvUP5PpTP6rUEVq9loxGdOIiTGMQkLuImdrdQotfyohH9dgAlei0vTmJ1C/0Kk7iIm3geVt/VRSM6cRAnkW5Ot3rf8rUsZPVPru/blLL6J9f3a59Z/ZONQUziN8KqFddTiVVrq6cSFycxiElcxG9/v46ErJ7Ii1XzF43oxEGcxCCWW624av7iJp6HVfOrzrhq/mJ1WwAHcRKDmMRyq/2tiv16GrK+Sa4xifVv6wCqYi+eh1WxF43oxEGcxCAmkW6bbptuh26Hboduh26Hboduh26Hbodu57lVp2SjEZ34uX0fgGZ1SjYGMYmLuImf2/cLv1mdko1GdOIgTmIQk7iIm0g3p5vTrZ40fJ+QZnVKNs7bFpjolLyYxPWwnjR8n5BmdT+u7/PCRPcjVlzdjxeTuG7XX6L78eJ5WN2P9YKN7seLThzESQxiEhdxE8/DoFvQrer4+9Qoq6Nx7boIqmI3/sF5WBV70YjfCKcWVFV4atfr2eDF87BeeS8a0Ynf/p7a6qrji0FM4iJu4nlYdXyx3OpYqo4vDuIklludcdXxxXKrFX8FuX+14q8gG4OYH9aCvoJs7MbNrHZDYLUbNhqxxh2FNcIsrGbMX+F5WLfYF6sZ0wqdOIjfZVSrqBbCxiQu4iaeh/WyeNGIThxEujndvpvp/atlfrfN+/s14Ky2wP19Lp3VFtg4iUH8RrBa8Vc422ptX+E0DuIkBjGJ3/5abfXcxPPwK5xGIzpxECex5lsrjiQu4iaWW51x/ojlloU131p8LuImnofrRzSiEwdxEoNIt9cKnPFagTNeK3DGawXOeK3AGa8VOOvPsSbOuN4qXwxiEhdxE8/Deqt80YhOpNuhW1Xh1zmQ1dS3v9+izmrq21/nQFZTX+MgTuI3wtf/m9Wot78egaxGvUYnDuIkBvHb3+9XfrIa9Ro38Tz0H9GIThzEchuFQUziIpbbLjwPv5e6/f2KR1ajXqMTB/FzG7U7VZsXk7iIm3gezh/RiE4cRLrNbrVONOpdXMRutU406gHr8djFarWuVdTjsYuDOIlBTOIibuJ5WI/HLtIt6Za1Z3UWVcejLo2q469lIav5rtGITqwR6txWjVAX+DoP949oRCcO4re/s7bvq83GJC7iJp6HX202GrHc6vKs182LkxjEcqsTqootrNa5/X2yndUOt+uzr2qHa1zETTwPq2IvGtGJgziJdKuHUF8XUqId7uImfidfkYl2uItG/E6+whztcBcnMYhJXMRNPA/rIdRFI9Jt0K1qsz7Bqz84ur9PMrPa4fb3C0ZZ7XCNThzEb4SoY6lXyHqgUi1ujUZ04iBO4re/9f6tWtwaF3ETz8N6hbxoRCeWmxVOYhCTWG61O1WFF8utzq2q8KIRnfi51bv8anxrDGISF3ETz8Oq2ItGdCLd6tW0ird64BqTWL8Ogn+7iedhvZpWgFQPXKMTB3ESg5jERdzE04h2uItGrD2zwtqdUVi7MwvPw6rji0asEbKwRliFm3ge1qvpRSM6sfb3FE5iEJO4iJt4Htar6cVyi0InDuIkfm71kKTa1hq/cevxTTWoNRrRiYM4iTVu7W/V8cVvFfX4phrUGsutplPVfbHcaqurui+WW21fVffFcqszruq+WG61JVXdFz+3etdcDWqNn1u9Va4GtcbPrd7aV4Na4+dWb+2rQa3xc6t37tWg1lhutaCq7ovlVguq6r5YbrWgqu6L5VYLquq+WG61oKrui18F1J1jNag1GtGJgziJn1u9N60GtcZF/NxOrbhej4H1enzRiE4cxEkMYhIXkW7nuVUr2q4329WKtut9bH013v6+bzvrq/EaN/E8rOq++OZbDWqNgziJQUziIm4i5+s/It2cblXzWFBVNxbknO/gfKu6LzpxEDnfwfkOzndwvoPzHZzv5Hwn5zs538ndmXSbdKvqxoKqjrGg4HyD8606vhhEnmZwvsH5BuebnG9yvsn5JuebnG9yvsndSbol3apisaCqTSxocb6L8128+havvsXT3DzNeuX9vp4vq5Gs8avNWcZVmxeDmMQa9wuFg3o7hTUC/r+TGMQaAf92ETexXrv/prOqOazRiE4cxEkMYhIXcRPpZnT7qvB8j5tWtYGd7+HWqjaw8z2wWtUG1ngefvXWWCNEYY2QhYu4iefh+BGN6B/uwkGcxCAmcRE38Tyc5TYLjejEQSy3UxjEz+17xrSqDaxxE8/D7zW20YhOHMRJDCLd6r1p1P7We9OL52G9N43avnpvetGJ37UTtbZq3bgYxCQu4iaeh9W6cdGITqTbotuqPauLa9fu1P931+7UKrYTB3ESa4S6aE+NUAd7jOjEQZzEIH7763XZf7XZuImnsdq1Go3oxEEstywMYhIXsdys8Dy0cotCI5Zb/VhV7PeEaKFd63vfstCudTGJi7iJ52G9u71oRCcOIt2cblXz3++ArGrXatzE87Bq/qIRnTiIkxjEz23UVlfNX9zE87Bq/qIR69/OwvOwKvaiEZ04iN/MRh1LVSww69/WCeUgTmL929qzTOIifieUGOw8rHq7+J1Q1mBVbxcH8TuhrElWq9TFJC7iJp6HdU970YhOHES6bbrt2t86rKrNWVd11eb3AGhV+1PjJAbxG+F7QrSqpel8v66wqqWpcRAnMYhJ/Pa3XuqqpanxPKx6u2hEJw7iJJbbKEziIm5iuX1nXC1NjZ/b99hiVUvTifq39Wp6cRKDmMRF3MTzsOrtohHphpYmL5zEIFZLE/7tIm5itTTVKtDSBDSiEwdxEoOYxEXcRLoF3ao262Wm2pROvepVm9KJOqzYxPMwf8Qa4RR+I3yPZFa1HjVu4nn41WajEb/9zdq+rzYbJzGISVzETTwP63WzQrdajxqdOIjlVie042F9jdPFmm+VSNXmxUGcxCAmcRE38TRWO1GjEZ04iJMYxCQu4ibSzehmdKs6rmCqdqLzPRZa1U7UGMQkLuImnodVxxeN6ES61eemq+ZQn5teTOK6X0m08NVtF8/D+hqnqjd8ddtFJw7iJAYxiYu4iefhpNukW90Vf41Oq1qPzvcYa1Xr0akqrNaji/VqetGI3wgYrGoTi6/avHgeVm1eNKITv/39HlitaidqDGISF3ETz8Oq44vl5oVOHMRJLLc646rji+V2CjfxPKw6vmhEJw7iJAYxiXSrr27bdUL11W3AqvmLdr92auGr2y4OYjXB1Crqq9suJnERN/E04qvbLhrRiYM4iUH89ux7Yriqyeh8DwRXNRmd7yngqiajxkkMYo3wFU41Dp3v0d+qxqHGQZzEICbx29/avvqKtcbzsF5jLxrRiYM4ieU2C5O4iJtYbt8JVZNR4+d2aqOqNi8G8Rv31PZVxV78xj21UVWxwKrYizVuGdf978VBnMQgJnERN/E8rOq+SLekW9It6ZZ0S7ol3ZJuSbdFt0W3RbdFt0W3qu5Tl1FV98VF3MTzsKr7YnU/1mBVvLgmq3gvLiIv2l2D1dV3eNEeXrSHF229NJ8qnHppvriINcm65OqluX6s2pQajejEQZzEICZxETeRbkaLqtjv+dmqjqXGJP4N9veO24q38CF/L76PrdiLXXgIT+EoHsUYfxYf8vgJY/woduEhPIVDOIWXMHxrQ8Yhz5+wCbvwEJ7CIYwxv0OvxqY/rr2NITyFQziFl3DNuZ5IVX9Tc/6ETdiFh/AUDuHyrQdE1RP1eAsf8voJm7Dz7NYQnsIhjDV+gVnNT71v24RdeAhjLXUtbdmrvYUP+WDO5XtM2IWxV3WdHDmjI2d05IyO+B7xPfStJqnHJuzCQ3gKp3Ddw3zLra6pRiM6EevI4rpdmYWLuIk42C+wEsV92YSxSbt4vB+tF/CLQaSj09Hp6O9Ws5qkGo3oRLoNWqCIrTYGRQxGEV+u+ddzvUQRXx7CU7gO+WtRW9UL9XgJb+Hy9dpwFLrX3FDol6cwxo/iFF7CW/iQUeiXTRi+ddAo9MtTOIRTeAlv4UNGEXud+8LP1t6icC9v4UNGQV824ZrzqD1HQV+ewiGcwkt4Cx8yCn3UGaHQL7vwEJ7CIZw8OxT65S18Hi8Udz2JXiji2rdqtHqcwksYa/mupWqruntVfVWPhzDmXL4WwimMvYriLT/LM1r+ExZfF18XX7yYXw7hFF7C4jvEa7xHPvW9Yo1BTCLW8V2P1V+FBz3VX9XoRBzsKp7CIYxNqo2fiz+6ie8pU/VjNdIx6Fj35hcnMYhJpFvQAkVcT20XivjyFK751+PchSK+vIS3cB1yPdJdeLW+bMIuXL71xHSh0OsZ8EKhX97CGL8uLhT6ZRN24SE8hUMYvnXQKPTLW/iQUeiXTdiFhzDG/M5941X5+yR4bRTuZRcewlM4hGvO9SB5o6Avb+FDtp+wCbvwEC7fr0twbRT65RRewlv4kFHodXYbhX7ZhYcw1vgr3tw33KmDUdCXTRhrGcWyV7gjv7yEMefyxYs5GC/ml7FXUSxnNOWMppzRFN8pvlN88WJ++ZBDro2QayPEN8SrqhrbFpt4HtY77otYRxa/j0+q5aoxiTjYVbyFDxnFXc+dq+3q/uhy4iDScdFx0bHeYF/cxPOw3mBfpNumBYq4knujiC9v4Zp/1gWOIr5swi5ch1zP4TderS+HcAqXbz1qPyj0egh9UOiXXRjjR/EUDuEUXsJb+JBR6PXJ4EGhX3bhITyFQziFFxlFXI+ED16Vv+bIdVC4l1N4CW/hQ0ZB1/Pig4K+7MJDeAqHcAov4fKtx7cHhQ5GoV82YRcewpNnh0K/nMJLGGv8wuygiLFvuFO/PIVDGGupaylkr3BHftmEMefyxYv55SmMvarrJOWMUs4o5YxSfJf4LvHFi/nlISzXxpJrY4nvEi80haxCJw7iJGIddT3WI7R6g1gdWxfZK3JQ3PWU/qC4Lw9hbBL+ffBHk7iIdDztuKuXq9GIThzESQzieogi/h7w7x+K+LIL1/y/ftr9QxFfDuEUrkP+HqzvH16tLx8yXq0vl+/3cH3/UOjfc+n9Q6FfTmGMH8Vb+JBR6JdN2IWHMHyzOIRTeAlv4UNGoV82YYxZe45X5V17i8IF41X5sgm78BCuOZ/acxT05RRewlv4kFHol024fE+dEQr98hQO4RRewptnh0IHo9AvmzDW+CtO7hvu1C9v4UPGnfqpa2nLXuGO/HIIY87lixfzy1sYe1XXyZEzOnJGR87oiO8R3yO+eDG/vITl2ji8Nuz3E3bh6iCMwiQu4iZiHd/1iIavH3AQJxEHu4pTeAljk3bxeT/qP6IR6eh0dDrW87WLSVzETaTboAWK+NTGoIgvp/A3f/se7u/q63p8yFXEzVbsxS48hKdwFI9ijD+LDzl+whi/DihceAhP4RBO4SUM39qTOOT8CZuwCw/hKRzCGLPOfeFna2/XEJ7CIZzCS7jmbLXnVdCXq6CbTdiFh/AUDuHytTqjKvTmLXzI5ydsws6zO0N4Cocw1viFWX2Z1t23aj177MJDGGsZxdyr6jR7fMiGOc9iE3Zh7FUUT/nZEE5h8TXxNfH1n7AJu/AQFl8XL8f+f9dY9Zb98So2YRcewlM4hFN43e767fi1CeB5iF+bABrRiYM4iev+asF2lHzdWzlKHoySv2zCWE4Ng5K/PIVDOIWX8BY+99cbtuP3KoBGdOIgTmIQk7ge1m9CYcVLVoMwuDyEp7CsZslqlqxmyWpuGBTfMACbMBe0uaDNBW0uaHNBmwvam8jtO9w+/PpTrfjIalDql1N4CctqDlczfj9hE3bhITyF34LGL4mLuIlvQcN+RCM6cRCzVzyMqxm2hXmFD/8Jy2pcVuOyGpfVeAin8BLmgpwLGlzQ4IIGFzS4oDGJ3L7B7ask+B4+7GpSazSiE2sp32chu742q34jdFfvWuMm1j59H8LtgSS4bMK1T98Hb7u+Ouv+aP1u1cUg0jHoGHSsDABWBlw0ohPplrSou3b7PvzbAy/44PUTxvxr81D7l4fwFK5z9tpA1P7lJbyF4VvzwQu+1/WFF/zLUxjj1/WCF/zLS3gLHzJe8C+bcPmOOmi84F+ewiGcwkt4C5/HExX+fSC369uy/ngUL+EtfMh4wb9swphzFA/hKRzCKbyEt/Aho9a/D6z2RK1fduEhPIVDON/ZTdT65S18yLgR+D6M3BMv+Ng3vOBfTuEljLV819Kcsle4qb88hDF++eKm/nIKY/xTLGc05YxCzijEN8Q3xBev/JdDWK6NkGsjxDfFC99rUEvH9xoAg5jEGm/W9YivMKgh8BUGQCfWZL8P4fZEcV8O4ZrsrMHrlynvj27iebjpuOm46Viv6RcnMYhJpNumBYp4gofwFMb86wJHEV9ewlu4Dvn74G0HXsovm7ALw3cVY/xdvIS3MMb/Lq5AoV82YRcewlM4hMv3+3aOjVa45i18yCj0yybswkMYY37njjY3q/1Hm1uzCw/hKRzCmHMUL+EtfMh4937ZhF14CMO3zgiFfjmFl/AWPmQUOs4OhX7ZhYcwzmUWb+4b3rGDUdCXTRhrqWspZa8yhZcwxi9fvJiD8WJ+GePXdbLkjJac0ZIzWuK7xHeJL17MLx/ylmtjy7WxxXeLV1V1ZW51vzWeh3WnfrHGy7oe8c1BtSR8cxAwiTXZ70O4jf625vMY/W32ffC28S1g9aP4FrCLgziJQUziIm7ieVj36BfpZrRAEX8f/u1EEV/ewpj/d4Gj5a3ZhF24DrlubROv1pdDOIXh+12AiUL/PkzaiUK/7MIYv+aPQr8cwim8hLfwIaPQv18U2WiFa3bhITyFQziFFxlFvOrc8aq8am9RuJdTeAlv4UNGQa/acxT0ZRcewlM4hFN4CcO3zgiFDkahXzZhFx7Ck2eHQr+cwksY5/KFGdrf7r7hTv3yFA5hrKWupS17hTvyyyaM8csXL+aXpzDGr+vkyBkdOaMjZ3Tou34/YRN24SE8hUM4hemFbxWrm1h8q9jFQZzEGq8+C1n4yr8oPA/xlX/Ammx9CIf+tuYhXJOtD94WvvYPP5rERaSj03HQsd5zX3TiIE4i3QYtUMT14d9CEV92Ycwf/34Kh3AK1yHXB28Lr9aXDxmv1pfhu4ox/i4O4RTG+Kd4Cx8yCv2yCbvwEC7fUweNQr+cwkt4Cx8yCv2yCWPMOne8KteHZGhzu4xX5csm7MJDGHOuPUdBX07hJbyFDxmFftmE4VtnhEK/PIVDOIWX8ObZodCL0SLXbMI4l1mcb9/Q/ta8hQ8Zd+r1+Rja3LBXaHNrDmGMX754Mb+8hTH+d52gze3+rJuwC4uvi6+LL17MLy/hLcxrA61wzeJVVf19u+7G149dXMRN/Mbz+ixkv+/f3ft9/+7e7/t3N/rb/AdO4SW8i2vj8R289f/Gd/ACjUjHoGPQsZ6vXUziIm4i3ZIWVcReH/5Vw9vjFMb8o3gLH3IVcbMVZ7ELD+EpDN+6ABfGr4toHfL+CWP8uri2Cw/hKRzCKbyEyxeHXoV+uQq92YRdeAhP4RDGmN+5o83N60MytLk1T+EQTuEljDlH8SHbT9iEXXgIT+EQhm8WL+EtfMj+EzZhf2dXf0Lz8RQOYZzLF2Zof7v7NkzYhYcw1rKKZa/GFj7kifHLd5qwC2P8UyxnNOWMppzRFN8pvlN84ydswnJthFwbIb4hXvUC7vVQH+1vXs/m0f7W7MJDeAqHcAp/WYKjqG8mu3ge1sO3i0Z04iBOYu1RPZNHq1vzIaPmL5uwCw/hKRzCKSy+W3y3+B7xPeJ7xPeI7xHfI75HfOsPV1STEv4Y5sVz8eCPYV6E5yye928HHPw1zItJxIKieAsfMgLh+4Di4C9i4kfr71RcHEQ6Gh2NjvV3Ki5u4nlYf6fiIt2cFo6NWcVLeAtj/udjhMBlE3bhOpDvA4qD1rjmEE7h8h214QiBUXNDCFx2YYw/iqdwCKfwEt7Ch4wQGHXQCIHLLjyEp3AIp/AiIwRGnTuKfdTeotgvp/AS3sKHjBf6UXuOF/rLLjyEp3AIp/ASLt9ZZ4QwACMMLpuwCw/hybNDGFxO4SWM621/jELHvqHQL0/hEK4xZ11Lh3uFFrhmE8acvXgIT+Ea/3vOf+yX8rNLeAuLr4mviS9uAC4P4SkcwuJr4oUX9+858DG8uH+fLxzDi/vlKRzCKbyEt/C5f4XmGP42DdCIThzESQxiEs/9G1OnGuYajehErCWL8/5lqWPvj0wdwx+ZAuJCrc1BUV82YWzULh7vR/GHpoBBpGPQMeiIPzRViD80BTSiE+mWtECBfx+yHLTHXUaBX675R20ICvzyEJ7CddBR46PALy/hLVy+URc5CjnqokIhX57CGL8OE4V8eQlv4UPGq/plE4ZvHTSK/fIUDuEUXsJb+DxGe5x/H1gcRyF/H1gctMc1b+FDRiFfNuGa8/es/6A9rnkKh3AKL+EtfMi4k/8+Pzhoj2t24SE8hUM439k5iv3yFj5kvLh/H8wdtMfdfcOL+OUUXsJYy3ct+ZS9wov45SGMOZcvXsQvpzD2KorljKacUcgZhfiG+Ib44kX8cgjLtRFybYT4pnjVn4+r1wr8yciLWEldeXhpv7yEt/Aho/IvmzBOvXYZlX95CsO3ZobKv7yE4buKDxkv7ZftW0odYn1ZzMVBnMQgJnERN/E8rO9/uviNW6/h1SLXWGtZdRWi2i8v4S18HqNDrtmEaw8redEh1zyF4TuKU3gJw9eKDxlJcfnbw3qlxh+PvDiIkxjEJC7iJp6H9VeyLmI1s3gKhzBWE8VLeAtjNd8JDNzwX8Yulhdu+C8PYfju4hBO4SW8hQ8ZbwQuw/cUu/AQnsIhnMLfXlotsf5EndX1UH+izmqBX1A0DuIkBjGJi/id0a924rsvuPiFRaMRy62uk0qQi5MYxCQu4iaeh+tHrB3atU5kxOUQrh3a+PdLeAvXyeyqDWTE5TqZXfWAu4bLQxi+dfXhruFyCi/hLXzIuGu4DN86Stw1XB7CUziEU/jPd9ZNYX073Kzkrm+Hm3XbVd8O1ziIkxjEJC7i33JmvY5W993FLyQajVhuo3AQJzGISVzETTwP/UfkFYHOuuYQ5hWBzrrmLcwrYo6fMK+IOVx4CPOKQPddcwov4S3MK2LOnzCvCHTlNQ/hKRzCKcwrInhFBK+I4BURvCKCV0TwigheEcErInhFBK+I5BWRvCKSV0TyikheEckrInlFJK+I5BWRvCIWr4ibEVk8hUM4hXEytUU3I8CHfDMC/K2mnihUW17jIE5iEJO4iJt4HiICTu0YIuDyFA7hFF7CtZxTFxRuJYrRoddswvCN4iE8heGbxSm8hOG7i+H7rQude+P7zOugc6/ZhYfwFA6y42et2IXxs148hfGzo/hvzsPx/17ETTwPvyBoNCJGrh2rsh6/2plRYwDPw/kj1hj1c19JNw7iJAYxibCrTa53Dc2n+Ls+0XrXbMKYdh1K1MprP2Jzb+KQ8ydswtjvOs8cwlNY9rveKjQvYfFN8a3yHfVyjw675hCuMevOBx12zVv4kKt8m0241mI15z2Ep3AIl6/XNVgv8c1buHxxpdRL/D38eolvduEhPIVDOIWX8BaG73c5oEmvGb6r2IWH8BQu33qSjS+ka17CW/iQUd+XTdiFy7eejifq+zL22YvhC17CW/iQ/ScMr1E8hKcw1jiLU3gJw6v20A95wKv2apiwC8N3F0/hEE7hJbyFD3nC9xSbsAsP4SkcwvCN4vOSLG9s1L+5sQF24SE8hUM4hdfL4Lw5Az7kmzNg+Nbcbs6Ah/AUDuEUXsJb+JDr0cOoJ/po9muewiGcwjV+3W7g+/CaDxmZc9mEXRi+dc0gcy6HcArDt64HZM7lQ0bm1J0ZGgWbXbh868EqGgVHPTRFo+Coh6ZoFGxewlv4PEajYPN3M2RF81E8ykfr0W5CjddDO3x33WXU+OXvhfQU+aPxaD6KR/kIY37XwELN1sPU6tOr3ak2vUvx6JvzLlqP9qPT9FXpJXsEl1U8hLHz+DchnMKYbc0Blfj1cp+FSrz8zbdGRB3Wg1b06DUv4S18yF8dYofy7W6+3c23u/l2N9/uosawp/V47+4paqwe2OIr55pr5fVAFb14zZhznfFXY9iDr8Iunaavui7ZI3+EMWs+qJN63Ig/4Fn/ov5+J8ge+fdXLorGo/koHuWj9Qgu4PMYXXWjxkdXXbMLY7anuMapB3vopLtcf0Usi+ztEb5GrnkIT+EavR7fob+ueQnvdwbor7uMmrssvi6+Lr4uvi6+Lr4uvi6+Lr5DfIf4DvEd4jvEF6+xl/NWBr6ADlc6voCumRWAL6BrNjJeDeshKb4UrnkI13u+oniUj9aj/eg01TtlkD3yR+PR88jnkc8jn0c+D7ze1UNQtNE1mzBWVLuEGr1ce1oPUNBG15zCS3gLHzJeBy+bsAsPYfHd4rvFd4sv6rse4qC97jJeBy+bsAsPYfh6cQin8LfHVYVfvV86l+q75y7ZI3+EMUcx5jyLMefvLNBe12zCLow5r+IpHMIpvITr2UkRXL/8QXNdswmXaz1JQHNd8xQu1+q9wffPNZfrqdWiyi8fcv2llZpN/aEVkD8aj+ajeIQxi1Gr9XQCzXWjnkKgua55Cocw5lzrxZvry1v4kHGXfPmbde1rPWcHjUffrMujHrKD8tF6tB+dJtwT1zMTtNs1u3AIf7Od9WwE3x53uZ6c1758FX/JH436l3VeVe3NIZzFtc9V7c1wxDiHXNU+66EEGutmPXxAY92shw9orJv1DgGNdc0hXOPXBxpolJv1zh+NcrPeJaJRblpdS1W902puVb2z3uFXR9wfl2+9Lhd/X0L/U4GRDkQt+Xsz/4la89f0+Ymtokb7Whm/P49Qo31v+j9hKlzFUFFT/h7CfCJUpIqlYqs4IvynwlTAZ0JgtCgx8M8SAhPF4sZQMVWEii1iYjTs6HQVGA3bWxU3B7a3XlrnwCbWa+sTQ0XNYGDf6ib3iVSxxKfuc9//ckRUdT1hKlx2J4eKqSJU6B6g+O6y10+F7g6q7V5vKLeBw0K9DRwWCq7FVnFEoOZamApXgR3FrFF3LUIFZoCLYmMGWBxqcmAJGzPAEs5PSgbl2sJVlM+8IlUsCvS2zWkQNevpEF9H0/1HQcRIAwIjTYit4ohAwbaoGc+AcBVDxVQRKlLFUrFFoCxnQmC0BYF/VltrKMt5IFzFUDFVfNuBgasr7eIibuJ5WL1qF43oxEGcRLpNuk26TbpNugXdgm5Bt6Bb0C3oFnQLugXdqjcNp1q9aRcnMYhJXMRNPA+/Wm40It0W3RbdFt0W3RbdFt0W3TbdNt023TbdNt023VCegRpCebYwFXV1BfYOr6eBUsMLauDyRHlGXZ74graZP4hqvQZOYhCTuIibeB7aj2jEmkkaRM0kHeL7tQFMqn4HFFi/A3rRiE4cxEkMYhLhNyC2iiMCVZoToqIhA6KiIRNiqdgqjoh6I/qEqXAVQ8VUESp0BlNnMHUGEzOoA0fn2ROmwlUMFVNFqEgVS8VWoTNInUHqDFJnkDqD1BngRTpxDWWqWCq2iiMCL98tygcvOOhCmwtXJP7YNnATz8P6DnX8YH3b8kUnDuIkBrHmuHCpoX5R5o76bTFU1F4sXIR44W2RKpaKreJQoPfsCVPhKoaKqSJUYAYLYqnYKjCDOgB0oT1RM9g/iJrBNoiawR4QU0WoqBlsTAeZ0qJmsBOiZrAxnfuX0MAm7MJDeAqHMBwqX9CCNjeWhRTBZYMmtCemilrJcYhUsVRsFUcEUuRgK5AVZ0JgNGwFsqLFVnFEICtamApXMVRMFZgBthxZ0WKpwAxwGMiKK5AVLUwFZoC9Rla0mCrqeLAF98+tgJfwZ//DnuGLm8H44ubLJuzCQxjGOHHc+7dIFUsE7vBbfIPFvZjqPv6JKIGrpO7jn1gqaiXYIHydMxhf53zZhF14CE/hEE7hJSy+h77z9xM2YRcewlM4hFN4CW9h8TXxrUSJn0O4iqEC2z0hQkWqwHYnxFZxStRJ4pvjnjAVrmKoqBnYDyJU1AzMIGoGhllX4oQNiCOiHrQ/UTMwLKGy6Imh4pvB9cQ31lxO4SW8hQ95wiEgsBJs0sRKcDJzqdgqjojASrBJYSpcxVAxVdRSsHsVQuFX1ATwMAVfMPdETQDPAeb9VVgwPvsA4/kA+JDv0wFwzRcPB+rb5SiGiqkiVKSKpWKrOCIqVJ7QGWydwdYZbJ0B4gaPWybipsVSsVUcEeenwrlneC5/eQrjyR44hZdw2eH5EprerkDX2xOmwlUMFbVgPB5C69sTtWA8oELz2xNbBZ6TFOMe5rIJu/AQnsIhnMJLeAuLr4uvi6+Lr4uvi6+Lr4uvi6+Lr4sv0mVcYSpcBTZ8QkwVoSJVYMMDAhueELiHL75vpMAmDPsFMVRMFaEiVSwVW8URgVBqYSp0BqEzCJ0Bbo2wStwZXV7CW/iQcVd02YRdGLfL4Ckcwlj4FUvFVnFELCz8QJgKVxEqajRUMbr3AvGI9r0nTIWrqNHwTA8teXGXidS5AqnTwlS4iqGiDgUP69CZ90SqWCq2ikOB9rwnTAVmMCCGiqkiVGAGG2KpwAwOxBFhPxXfDPB8BZ16zUN4CodwCpdDVHCiDS/wmAl9eIEnS2jEeyJUpIpaSUyIreKIQMa0MBWYATYWGdNiqggVqWKpqBnclVbGtKiQecJU1AzwsAq9eU9MFTUDPDxCe17g4RG+gO8JzCAhjgjEDJ57oHfvCVcxVEwVoSJVLBVbxRGROoPUGaTOIHUGqTNInUHqDFJnkDqD1BksncHSGSydwdIZLJ3B0hksncHSGSydwdIZbJ3B1hlsncHWGWydwdYZbJ3B1hlsncHWGRydwdEZINkSsYBkazFVhIpvBniLjgbA5i18HqMBsNmEXXgIT2EssPJoIZzwrA1/HveJWgYevOEP5D4xVYSKVLFUbBF4+7UcQo4Ff/j2bgr+8u0TS8VWUceCJ3b4S7hPmApXIRfGGjqDESpSxVKxVciFsW5EYW43oq5wFUPFlLkholqkCp3B1BlMnYFG1NKIWhpRSyNqhVyaK/QUQk8h9BQQUXduoaeQegoaUUsjamlELY2opRG1NKKWRtTSiFo3ojC3paew9BSWnsLSU0BE4ZkuWiWfwCmgfhBRLbaKIwIRtTA0IqqFqxgqpopQkSqWCswA5YyIuuJomSGV8BgX32n4xFQRKvTiw/1WCz36I0ePJswnTIWrkKPHXwB+IlSkiqViq5DLH1+E+ISpwEoNIlSkivLZDlE+eJSNfs0WeKLUwlS4iqFiqggVqQI+dfGhQfMJU+Eq4BMQU0WoSBW468KyEWktjghEWgtT4SqGiqkCd8qYKIKrxRGB4GqBlSYE7sgxa8RTi1SBk8NpI55aHBGIJ3wqgD8b3AOkqxgqdAapM0idAeKpxVYh74vQIPqEzmCpKXIH79nQAPrEVlFD4wMs9IA+UUPjowh0gT4xVNTi8CEFGkGfSBU1A9xGoBf0iSMCt0YtMAMcI0KoxVAxVWAGOCxEDT48wPcvXoG/P/wEfA6EqxgqpopQkSqWim8Gief+aCFtUVHzhKlwFUPFVBEqMHQdCRpCE59joCP0iakiVKSKpQJLCIgjYvxUmApXMVRMFaECM0iIpWKrOCLmT4WpcDlgpEuLqSJU4OQqQ9BB2jsapsJVDBVY3ILQTYyt4ohI+GAGaSpcBXxwVaUeY+oxph5j6gxSZ5A6g/VTYSr0Qlp6IS2dwVLT+/WNxffrG8EmXM/gcVD4yobLUxhPL3B571SxVGwVR0RFyRN4dmIQrmKoqAlgk+8vboNTeAlv4dNsv/uL22ATduEhPIVDOIWX8BYWXxNfE18TXxNfE18T3/u4yCGWiq0CnxJYCdzTtMDnFD8IVzFU4HOKgAgVmMGEWCowg/vPjgjkUQv8Pi3YhYfwFA7hFIZDlpi4chYErpwNMVWEilRRK7mrr7uZJ44IhE8LU1EzcGwFwqfFVBEqUsVSgRlgboilKxBLLUwFZoALBbHUYqqoGQxcDoilAVPEUouawcCZIZauQCwNbDxiqYWrGCqmilCRKpaKreKI2DqDrTPYOoOtM9g6g60z2DqDrTPYOoOtMzg6g6MzODqDozM4OoOjMzg6g6MzODqDIzNAk+8TpsJVDBVTRahIFUsFZrAgjgjcKLUwFZjBgRgqpopQkSqWiq3iiPCfivKpFmjDV1lmfRZi+C7LJ2q0+sTDDCl1BVKqhalwFUPFVAGfUWLq+UzdHWRVi6FiqqjdqTdOZsiqFkvFVqFXSOgMQq+Q0Csk9AoJvUJCr5DQKwRZdScaeoWEXiGpV0jqHiCr6h2R4a9EP4EdhQ+yqkWqWCqwB7gOkFVXIKtamApXMVRMFaGiZhC4xJBVLY4cPeIpcL0hnlq4iqFiyjFuPfqtR7/16LcePeLpCsRTCz16jSfTeDKNJ9N4Mo0n03gyjSfTeEKTc9ZHUYbv2XxiqiifGBDY3gmxVGwVRwRCqIWpcBVDxVQBn4DYKo4IRE0L+GCleFPXYqiYKnDrsSBSxVKxVRwR9ybqClPhKoaKaiky8BLewtVShIXdv3YHNmGsEYMislpMFaEiVSwV5Y4L4P4x2+L7x2zB2OIN4SqGiuqluhzCKbyEt/Ah3z+wAzZhFx7C4pvim+Kb4pvim+K7xHeJ7xLfJb5LfBFNcSBSxVJRV1TisJFTVyCnEhuOnGrhKup9yf2RKRzCKbyENxk5lKh1pE2iBpE2iWsNadNiqdgqsJK6otBe/YSpcBVDBWawIUJFqsAvvoO38CHj144DbMIuPISncAin8BLewofs4uvii0iqTwMNLdVZnxgYeqqfCBWpYqnYKo4IRFILU+EqdAZDZzB0BkNnMHQGQ2cwdAZTZ4C7rPowwtCj/cRQMVWEilSBGfwgtoojAndZ9ZmSoXv7CVcRKtCJDT7k24cNNmEXHsJTOISxDlwMuFNauJpxp9TiiMCdUgtT4SqGiqkiVKQKncHSGSydwdYZII4W1oM4ajFUTBWhIlVgBqhW3Da1OCLuV/+ATdiFh/AUDuHy3rgqEWEttoryro+HDE3cT5gKVzFUTBW1+vqUz9DK/cRSgRlMiCMCt1ItMIOAmPq/7O8La4HnIe6P6vcwDK3YT7iKoWKqCBU1/YOFIYxabBVHBMLoYJIIoxauomZwsDCEUYtQgRkkxFKxVRwRCKP6iMPw/aN5sJ6KnPXDVlXkPJEqlopdwiBOibpu0Kq9flhPRc76YdYVOU8MFVMFZoBZR6pYKrYKzKCqs76Q9O/tFCZa6bRwN1lfSvoncCSVTwuP6NDT/USqWCq2iiOiEuoJzAB7vVyFXqwIpRapYqnQolhaFBumOMZtKlxFLRuPAtHk/USoSBVLxVZxRFQoPWEqXIXO4OgMDmaAIzmpYqnYKg4F+r6fwAwWhKsYKqYKzGBDpIqlomZQjeOGvu+Fx5Ro/H6iZoCnwGj9fqJmMDDRCq0nQkWqWCq2iiPCfypMhavQGbjOwHUGrjNwnYHrDFxnMHQGQ2cwdAZDZzB0BkNnMHQGQ2cwdAZDZzB1BlNnMHUGU2cwdQZTZzB1BlNnMHUGU2cQOoPQGYTOIHQGoTMInUHoDEJnEDoDJB9e2tEU/oSpcBU1gwBP4RBO4SW8hQ8Z+XfZhLHAKxBrV2AZCXFEINZamApXMVRMFdgu1PfRYzm6KUc3BRHVYqrAsSAGEFEtloqtQi4MdIQ/YSpcxVAxVYSK5NzQEf7EViEXRt6I2hCmwlXoDDSiUiMqNaJSIyo1olIjKl0uzXRT4SqGiilz81CRKnQGGlGpEZUaUakRlRpRqRGVQ66DvBF1hZ7C0FMYch3kjSiIqaegEZUaUakRlRpRqRGVGlGpEZUaUTn1Ogg9hdBTCD2F0FO4EXUgQkXNAB9qoJf8ia3iiEBE4Vk0esmfcBVDxVQRKlLFUoEZYAkIqivwXhIrWINBgYbxhSf9aBh/IlUsFXrYSw9762FvLbmtJXdD7Aq94Lce9tbD3nrYWw976wWvwZdHL7ejl9vRyw3xhk8u0Bf+xFaBDa19Q2v4qt9KMfSGP+EqhoqpIlSkiqViizB5mIHO8SeGiqkiVKQKvML9ILaKIwIhhg9F0FP+hKvA66tDTBWhIlUsFVvFEYEQa2EqXIXOYOgMhs5g6AyGzmDoDIbOYOoMps5g6gymzgAhhg9S0G2+8GEFus2fWCq2iiMCIdbCVLiKoWKq0BmgnRNXMro5L29h9HIW31ZOsAmjyxs8hKdwCKfwEt7Ch3z7y8EmLL5LfJFZLbB/mCmSCQ/g0Sf+hKsYKmo0PJpHz/fCA3j8RfsnTIWrGCqmijoNPGxHA/gTS8VWcSjQAP6EqXAVmMEPYqoIFakCMwiIraKOpvbj9n9fNmEXHsIwr6NBH/fCY3/0cT8xVOADUHAIp/AS3sKHjAdRl03YhYew+A7xHeI7xHeI7xDfKb5TfKf4TvGd4jvFd4rvFN8pvlN8ERZ4uUeH9xOuYqiYKkJFXRwLx4g7nhZbxRGBO54WpsJVDBVTRajQGaTOIHUGuOPBRw/o/X4CL5xgFx7CUxge2E1EB1400epdPe2GTu/mIfyNhOemaPNuTuHPYcOt7maaD7lSptmEXXgIT+EQTmHxPfRFY/fC+1e0b691/xecxIZIFUvFFoF3W3i+jVbsVb/1YWjFfiJVLBVbxRGB2xE8Ycd3+z7hKoaKqSJUpIqlAus5EEcEbkdamArMYEIMFX8z8B82FDcT9SsXhk7sJ1wFfv7+zFTxtwLHA936tt/HS3iTkQC4ONF4vXAV1vf4ut3/IYWXcI10//0hfyX+2D7G7L4CfzyEp3AIp/AS3sKHvH7C4rvEF29kDq4/vF2p38Ew9FwvfECBpusnTIWrwGioDbz1wOcL6KJugZuCFqbCVQwVdRoHO42bghapYqnYKs4Tjl7qJ0wFZjAhhoqpIlRgBgdiqajgqA9CHE3Su1raHV3ST4SKVLFUbBVHRNX6E6bCVegMvlr3aoz3apN+nMLfZVZPwr16pB8f8lflXh3WXg3Sj114CE/hEE7hJbyFD3mK7xTfiZ3F0UzsH1YzsX+Y9jwi4qfCVGA0HGe9pu/67MjR5/zEEVGv6U+YCldRp1FNQ44+5ydCRapYKraKI2L9VGA9uL6XqxgqpgrMAFfKShWYAfZ6bRVHxP6pwB5gR3Ez0GKomCpCRapYKraKIwI3BS10Bl/K1J8i/3gIT+Hvygwc1Jcwj5fwd2VObNgXL5erv/mxCbvwEJ7CIZzCS3gLi69hZ6+o/avP0RwdyruamRwdyk9sFUcEkqM+OvsTGG1CpIqlYqs4Iupe4Ik6DWQMOpSfGCqmilCRKpaKrQIzqDJAV/MTpsJVYAYLYqqAT10f6EPeA1tV7w+emCpCRapYKraKIwJZ0sJU6Azq/qE+R/FqQ34cwt/lNLAzdf/QvIW/y2nglOr+odmEXXgIT+EQTuElvIXFd4sv8mHgaJAC/b9g/7A0pECLIwIp0AKj4Thxsz9QLbjbb7FVHAr//VSYijqNeoztaBp+YqoIFaliqdgqjgjDDBLCVLiKoQIzMIhQgRkMiKViqzgicK9RT7gd7cRPuIqhYqoIFaliqdgqjoihM6hbjnoS59VN/HgIf1dm4KDqlqM5hSvYsWF1y9F8yHXL0WzCLjyEp3AIp7D4TvHFXci8AvuHmSJT8DqFbuEnlootAskROHXca9TTV0cL8BOpYqnYKo4I3GtUS7qjEfgJVzFUTBWhIlUsFZgBygD3GlfgXqOFqcAMcKUgS1rAB9cHsqTFVnFEIEtamAr44HyQMi2wUpwCnjW0qBkkJor8aVEzSBwW8gcCzcK7Ho06moWfqBnUYy1Hs/ATNYN6zOloFn4CMwiIpQIzSIgjAvlTT38cDcNPYAYbYqjADA5EqMADlx/EUoFHLlg28ucK5M/CspE/LfC4B8tG/rTAAx8sG/nTou6x7s8v4S18yPVup9mE4Y3tw11Mi6kC3tgX3MW0WCq2iiMCdzEtTIWrGCqmCp3B1BngHdHCyeD+ZuMwcH+zsf/IohahIlUsFbqe0PWkrid1PanrSV1P6npS15O6ntQdTZ1B6gyQUnfZyKK77KXrWboeZFGLIwJZ1ELXs3U9W9ezdT1b17N1PVvXs3U9W9dzdEePzuDoDO5zTywbiXOXfWQ96O19wlS4iqFC1oPe3idSxVKxVch60Nv7hKlwFUOFzsB0BjdXatlo9r3LRrNvL8F1PT5VhIpUsVRgRx3iiKgEQZ5Xr+9jFx7C8BgQGKmyq5p2HblcPbuPXbhGWuApHMJfBiL5q4/38RY+5PgJm7ALD+EpHMLiG+KLTNhX4CQwU1T+xlGi8lukiiUC9ycHh4y7kIOdxV1Ii1CRKpaKraJO4+BoUPktTIWrGCqmilCRKrAeXLSo/BZHBCq/BWaAKwWV3wIzwPWB+5MWoSJVLBVbxaFAu+0TpsJVDBXf1YHX6eq2fZzC39WBV+xqtX18yF9OOO4Eqs/2sQsP4Skcwim8hLfwIbv4uvgiNaql3tEou/FUGI2yp3rlHY2yLeqdzROmYpbA0HWvcPAcF02vTxwR86fCVLiKUSIgpopQkSqWiq3iiIifCszAIFzFUDFVYAa4UiJV1AzwKBVNr0/UDAwDVJYcPAmtpldf+Pn69KV5CE/hEE7hJbyFD7menjSL7xLfSqNjuH4rjZ4IFaliqdgqjoj9U2EqXAVmgAPaU0WoSBVLxRZx8DO4yvEdoi2Wiq3iUKAX9omaNZ5gohf2ifoZPKdE9+oTpgI/MyCGiqniO+V9OYWX8HfKeNmtztXmKv7m75TxIl9tq4+H8BQO4RRewlv4kOsmoll8h/jWe42DR67oOz14Loq+04PHmug7fcJUuAqMhqNBxQ+cBir+ClR8C1PhKoaKOg085EMP6ROpYqnYKo4IVHwLU4H1bIihYqoIFZgBroJcKjAD7GhiBviZ9VNhKlzFUDFVhIpUsVRsFTqDeoSKW57qLn3swt9liRuZai19HMJ1WeLM9xLewod8fsIm7MJDeAqHsPge+t7vGR5X1P7hSeb9RmG8GUfL6BOpYolAclTjr6Mx9OChIhpDnwgVqWKp2CrqNKoF1tEY+oSpcBVDxVQRKlIFZjAgtoojAvcVLTCDDeEqqmUKm4PAwHM09Hi2QGC0MBWuYqiYKkJFqlgqdAZTZxA6g9AZhM4gdAahMwidQegMQmcQOgOEDJ6nos/z4AkoGj2fcBVDxVQRKlLFUrFVHBFLZ4DHrpddeAjjcylwCKcwPloFb+FDvp/sgk3YhYfwFA7hFBbfLb4HO4vJHewfCgy3GnhWvu7XlV+xVGyKfb+ZfENgtAMRKlLFUrFVHBGIErxjR5fnE65iqJgqQkWqWCowgwVxRCBkWpgKzMAhhgrMYEKEilSxVGwVRwRCpoWpcBVDhc6gPprBW5zqIH28hL9XHrxxqQ7S5noW0vy98uANRHWQPh7CUziEU3gJb+FDrmchzeIb4ou0wcMNtIIePHlBK+jBY3K0gj5hKlxFjYbH5GjrPHgyjrbOFsiHFqbCVQwVdRp4z71xE9IiVSwVW8URgbcgLUwF1oPSwVuQFlNFqMAMcKXgLUgLzADbi8Ro4SqwUmw8sqQFVortRZa0WCrgg+ngbQsEvvn3CVPhKoaKqSJUpIqlYqvQGZjOwHQGpjMwnYHpDExnYDoD0xmYzsB0Bq4zcJ0B8gdPWdFu+sRUESpSxVJRrfVg5Mq6YqiYKkIFRjYIqRi0mz5hKrAChxgqpgqsYECkDrBUbBU6g9AZhM4gXMVQMVWECp1BqCnCBW9b8ZXATwwVWFxChIpUsVSUDx7X4iuBWyCQWpgKzGBDwAeXDmKnxVJRPngrg17VFoidFqbCVQwVU0XNAO+A8C3BTywVW8URcX4qTIWrwNC4XJAn9YR2oD31CVPhKoaKqQJLSIhUsVRsFUcE8qSFqXAVmMGCmCpCRapYKraK8w54oKX1CVPhKnCNBsR6Ozrwnb5PHBG4UWmBxW0I3UTERotUAR/MAG+UWhwRuCepB7jjN/UYpx7j1GOcOoOpM5g6AwRKi61CL6TQCyl0BqGm9x0Q9uC+A7piqzgiEoszCLzPwbJzqggVdXNVd3KjWlkptoq6v/rhfO77HAyA2GjhKnQGS2ewdAYrVSwVW8URsXUGW03rUcnvh03cqWKpwOJQMvuIOD8VpqLuH38ojHpk8sRUESowA5zPgU9NFB2pT5gK3Kf+IIaKqSJUpIqlYqvAbXJdIfWNuxSmwlUMFVNFqEgRjqEHBAaYEFNFqEgVS8VWgSXUkVQLK4WpcBVDxVQRKlIFZrAgtoojAoHSwlS4iiEHjDc6LUJFqsA1Wjlq940MdvS+k7liqJgqsLgNoZsYRwRiowV8MIN0FUNF+TiuqtRjTD3G1GNMnUHqDJbOYJkKV6EX0tILaekMlppuPlAc+PbcJ1zFUIHF4VLefKA40NT6xBGB2KiG5WGIjRauopbgOJ8zdYBQkSp0BkdncGQGaIR9wlS4iqFiqkgVdT71ScVwJEULU4HFJcRQMVWECjxHWBBLxVZxRCBQ6gOA4QiU+txjOAKlRagon/pAYzgCpcVWcUQgUFqYCldRM6hG74FW1idCRapYKraKI+I+NbkCQw8IDICNRzi0OCLw+KOFqXAVWAKOBLHRIlSkiqViqzgiECgtMAMcIwKlxVAxVYSKVLHkgBEoLY4IBEoLXKO4rpEUd0dXqlgqtgosDhff1k3cQ8VUAR/MAPchLZaK8pm4qrYe49FjPHqMR2dwdAZHZ4D7kBapQi+koxfSkRmMn6nAx3EHIlSkiqUCi6tLGY2p+HhxoDH1iaGillCfBo2B2GiRKmoJ9enJQGPqG+CI8J8KnYHrDFxngLcvLUJFqlgqdAZDTZEUeGEZSIoWoQKLS4ilYqs4IpAU9anTGLj1aOEqhgrMYEPAB4eFQGlxRCBQAutBoLRwFUPFVBEqUkXNIHCFIFBaHBEIlBamwlUMFVMFhsblghuMwMYjHFoMFVNFqEgVWAKOBLHR4ojYPxWmwlUMFVMFZoBjRKC0WCq2iiMCgdLC5IARKC2GiqkC12hAHO7oxHuZFqbCVWBxG0I2ceIdS4utAj41g4n7kBamonyqWX9Mk2OcNlWECp2B6QxMZ4D7kCtwH9LCVLgKnYGr6W00c4gj4jaaXWEqsDiDQPsVdhSPQFosFbWEvAMcEYiNFrWExM9IC9qYtwXtiqlCZzB1BlNnMLeKIyJ+KkyFziDUFEmR2EQkRYsjAklRjbZjIilauIqhoq6Q+vhnTNx6tEgVSwVmgEsZgZK4EhEoLYaK8lm4RhEoLVLFUrFVHBEIlBY1g4UrBIHSYqiYKkJFqlgqtggkxcKR4AZjYeMRDi2Wiq3iUARiowWWkBCuYqiYKkJFqlgqtgrMoI4RDapPmApXMVRMFcEDRpvqE0vFFoEMqc8eRyApsKOB9zItQkWqwOLq4ouhm4h3LC1cBXwwg/uNHleEivKpz3VGjKUDbBV6jFNnMHUGU2eA+5AWU0WoSBU6g6mm+GWYg4nil2FaTBWhAoszCDRJQ6C9vYWpqCXUp0kDTalPTBW1hI3zydQBloqtQmewdAZLZ4DmkRZDxVQRKnQGS02RFBubiKRoMVRgcSgZJEWLVLFU1BWyURi49bgCtx4tTAVmgEsZgYJPEQKB0mKpKJ97pggUiESgtDAVrmKomCpqBtiqRKC0WCq2iiMCgdLCVLgKDD0gMEBtPLpXnzAVrmKomCqwhIRIFUvFVnFEIFBamApXgRksiKkiVKSKpWKrODzgRKC0MBWuAtdoQCzZUbyXaXFE4L1MCyxuQ+gm4h1Li1QBH8wA9yEtjgh8wRA+Z8rUY0w9xtRjTJ1B6gxSZ4D7kBZbhV5ISy+kpTNYalq3HobPjKqV9ftODIit4ojYPxWmwlUMFfg1IZii56xFqlgqtooj4v5azRWmAr9mhlOoQDHcQaKB9YmlYqvASmu0am6lMBWuYqiYKkIFVvqDWCq2iiMCv2rXwlS4iqFiqljckGqI7ZVWQ+wT/lNhKnSlrit1XanrSj1VLBVbha506EqHrnToSoeudOhKR6jQvR661/fXdbEhU1c6XcVQMVXoSqeudOpKp6506lUVelWFXlWhKw1daehKQ1cautLQlYZeVaF7nbrX9xd5sSGpK81QkSqWCl1p6kqXrnTpSpdeVUuvqqVX1dKVLl3p0pUuXenSlW5d6darauteb93r+0UEBrFUbBVHxMFKAwJfN+AQU0WowI4mxFKxVWBH64US3516B0D37BOuYqiYKkJFqlgqtoojwnQGpqaGy2VDpIqlohaHT6Q3QugKhFALU1GXCz5d3gihFlNFqKgZGObm8KkLttpiKUwFfCbEUDFVhIpUsVRsFZhBXSHojX3CVLiKoWKqCBUpAumCz53ra1Idf+Jv1NekUoSKVLFUbBW1BHzqu3GL08JUuIqhYqoIFamiZoAPYDfSpcURgXRpYSpcxZADRrq0CBWpAgVYmbhxi3N3FLc4LYaKqQKLw8W3dRP3EYHYaIElYAbHVQwV2ERcVUeP8egxHj3GozM4MoPz+6kwFa5iqJgqQoWYnvvFSAvCVLiKoQKLC4hKpHFH2yqOCMQGPl0+iI0WrgKbCB/8KnAPECpShc7AdQauM8C9SwtT4SqGCp3BUFMkBT7sPkiKFqaiFofPmQ6SosVUESrqCsGny/2dq1dsFUcEAqV+YW8cBAo+GD0IlBahAj4TYqnYKo4IBEoLU+EqMANcIQiUFqEiVSwVW8URgUBpgaFxueCd0T0fhEOLIwLvjFqYCldRS8Cnvgex0SJUpIqlYqs4IhAoLWoG+AD2IFBaDBVTRahIFUsOGIHS4jwxfwiUFijAAxFvR2e1wFIsFVsFFucljJs4q9GVYqrAEjAD3Ie0WCqwiRPiyAD+U2EqdAauM3CdAe5DWqSKpWKr0BkMNb1fuohZ3y9dvCJVLBVYXJS4X62Ild6vVrxiqMB1kBChIlVgE3E++ALXHuCIwBe4ttAZhM4gdAZ4l9MiVKSKpUJnkGqKpJjYRCRFi1BRi6tPpCdaYJ/YKo4IJEXd+88fbj1auIqhomYQuJQRKIHDQqC0OCIQKIH1IFBauIqhYqoIFakCM8AVgkBpcUQgUFqYClcxVEwVGLouFzS64i9wTDS6PjFUTBWhIlXUEupT34lG1yeOiHoo+4SpcBVDxVRRM6gPYCcaXZ9YKraKIwKB0sJ4wIZAaTFUTBUowANxZEfxXqaFqXAVWJxD6CbiHUuLrQJLwAxwH9LCVGATJ4Qe49RjnHqMU2cwdQZTZ4D7kCtwH9JCL6TQCyl0BqGmSIofNhHPQ65AbLQwFVhcQOB3ZXFR3C+BvmKpwHWQEEcEYqMFNhHng0957gD4lKfFVKEzWDqDpTO4vyh8xRFxf1X4ClOhM9hqiqRIbCKSosURgaRY+BkkRQtXMVTUFbJQGLj1aJEqloqaQX2lz3QESn0wOh2B0mKogM+ECBWpYqnYKo4IBEoLzCAgXMVQMVWEilSxVGwRSIr63Hmi0dXqI+CJRtcnloqt4ohAbLSoJdTTr4lG1yeGiqkiVKSKpWKrqBnUB7ATja5PmApXMVRMFSEHjEBpsVRsEciQ+iB+ogW2dxTvZVqEilSBxeHiS93E+3ckrnAVWAJmgPuQFqECm4irKvUYU48x9RiXzmDpDJbOAPchLaYKvZCWXkhLZ7DU9P6BCVyW+KtTLaaKUIHFXXH+6T8jMV3+9MR0+dMTE42utq8YKqYKbCLO5/7pifu/LBVbhcxg/H4qTIWrGCqmilCRKsR0ICnqw+45kBQthopaXH0iPdEC+0SqWCrqCqlPl+fArccVuPVoYSpqBvW3ReZAoNQHoxPfwPrEUgGfCXFEIFBamApXMVRMFZhBQKSKpWKrOCIQKC1MhavA0AsCA2DjEQ4tTIWrGCqmim8J/sORVGw8sVRsFUdEBcoTpsJVjBI4xgqUJ0JFqlgqtoojB4xAaWEqXAUK8EAs2VG8l2lxROC9TAssDhff1k3EO5YWqQJLwAz2VnFEHGwirqqjx3j0GI8e49EZHJ3B0RngPqTFViEXEvphnzAVQwXOJyCwuITYKo4I+6kwFa5iqKiswmHN+0esrkgVS8VWcUTcP2J1hanAlYjF4e/XtEgVS8VWcUTgj9i0MBWuYqjQGQydwdAZDJ3B0BkMncHUGUydwdQZTJ3B/WNXP4hQkSqWCswAm3j/4JVBuIqholaKG3R8g+sTqaJWavdntg5wROBP3rXQGaTOIHUG+JN3LUJFqlgqdAZLTesOxevDuolO2SdCBRY3IZaKreKIqNxxQ5khd1q4iqECM0D9IHfqg52JftgnjgjkjuE6OKbCVQwVU0WoSBWYAa6Qs1UcCjTUPmEqXMVQMVXU0PW52UQ/rNdHWBP9sE8MFVNFqEgVtQQ8mUM/7BNHRN2uPGEqXMVQMVVgBgGRKpaKreKIQO60MB4wGmqfGCqmCpzcgDiyowiUFqbCVWBxCaGbOJeKrQI+mEH8VJgK+GwIPcbQYww9xtAZhM4gdAa4kbkCNzIt9EJKvZBSZ5BqijsUfHCAL3H1+ghr4ltcnzAVrmKomCpCRWUV3srH/dOZV2wVR4T8Uc2JL3J9wlUMFeWDJ4D4utYntoojAoEyrqjR8AAv5O/xzrh/j/eKOqxxxVKxVWBH6xrN+/d4HcJUuIqhYqoIFaliqdgqjgjTGZiaIlDqo7+JttknlgosLiGOCARKC1OBy2VBDBVTRajADDYEfOoaRdvsE6aifOojuYm22SemilCRKpaKraJmUJ/PTbTNPmEqXMVQMVWEihSBQMHnZonYwOdmaJt9IlSkiqViq8AScCSIjRamwlUMFVNFqEgVmAGOEenS4ohAurQwFa5iyAHfdLkiVKQKXKP1woK22d5R3Ie0GCqmCiwOF9/WTcR9yBWIjRbwwQxwH9JiqCgffLiFttk3gB7j0WM8OoMjM0Db7BOmwlUMFVNFqBDThfc/+ERt4Q6lhasYKrA4hwgVqWKp+LIq85oeEfX+5wlT4SqGiqkiVNQm4lOehUC54v4RzytMBVaKAe7f8bxiqggVXyoHbmjRD/vEVnFEVKfsE6bCVQwV2NGAWCq2iiMC6dLCVGA9GBoZgs+zFjIEH+wsZMgVyJAWGO1AuIraN3zAh67XJ0JFrQcvyOh6fWKrOCKQIS1MhavADHC9IUNahIpUsVRsFXVyeEC0ECh33xAoLXRHESj4GK+6XimWiq3iiEDU3EsZUdPCVQwVWClmgKhpkSowAxwjoqbFodiIGjzQ34iaFq4CMwiImgE+gdqIGny0tPFEBh8tbeROiy0CuYOPFDZyp8VQMVXAZ0JsXspogW2B25UWpmKo+Mp54mEcvgz2ia3ilIBpNak9YSpcxVAxVYSKVLFE4D4En1qht/UJVzFUYKsSIlSkiqWiVopnT/UFsE9U68kTpsJVDBVTRahIFeVzz7QemzyBleJ8EDUthoqpAivFpYyoabFUbBVHBKKmRa30XmL1gfITQ8VUESpSxVKxVRwR+6cCK8VWIWpahIpUUSvFozB0yj5xRCBqWmClKNrjKoaK/9vbF+1Mc9tYvouvcyGJEiXlVQZB4Ml4FgYMJ3CSBRYDv/tWl7opdrXrNLvEnpuZZpL/fCqJPJJIisxaKFpgLVQttCmMfNjU7kLSAmlh/9IRFBz5sCKwFqoWmha6EvbLUB4MO9JmRUhaIC1kLRQtjL8zhEEoI8Q4kmNFIC0MtDKEogXWQtVC00JXwuCdhxC1kLRAWtAjID0C0iMgPQLSIyA9gqxHkPUIBu+0u1C0wFqoWhgzykPoShgHmYcQtZC0QFrIWihaGCOoQ6haaFroShiHnxFIHDm0IiQtkBayWvrBSA+BtVC10LTQlTAY6SFofata38YRZ5BqH0ech1C1sP+dEeQcqbajD0YeqbYiRC0kLexfOoKcI9VWhKIF1sI+grGbjVTbNCK4I9X2IQxGeghRC0kLpIWshaIF1kLVgh7B7fCz62HZE20fP+P8uf3tXYHKXoz28TPPn9tf3Reh7Dm4j591/mzzZ5efN1Z6/IzzZ5o/af7M8+f8a3H+tXHk2UOBZeTUpv3hbBk5tbQfY8vIqRWhaIG10Hch7cJ+OaI9FLgJpIWshaIF1kLVQtuFMbXUlbCfckSIWkhaIC1kLRQtjBHEIVQtNC10JZQxgrGqJWphjKANYR9BHFO1s40IRQushaqFpoWuhJ1tRIhaSFrQI7ixzX3hb1zz+Mnz5/a3+xj6jWUeP7v8vDFMHx9645fHzzR/0vyZ588yf/L8WefPNn92+dnmX2vzr7Uxj2Mh2pitoTFtzNbQ89aV0IMWohYG2oDuA21MRm9a6FMY9WNFiFpIWhhz34eQtVC0wFqoWmha6EqIQQtjBGUISQukhayFfQT7m68y0mpF2Eewp7KXkVYrQlfCflkSIWohaYG0kLUwRsBDYC1ULTQtdCVQ0ELUQtLC7WwzzHavPyu/i/rN6ndVv9v8PXgmjaUdbLLHcsrIrhVhnJHSEKoWmha6Esad6SFELSQtkBayFsaMDXUYnEFjNQdn3IXBGQ8haiFpgbSQtbB/KY0J2U8oIlQtNC2MEYyB1qCFqIWkBdJC1kLRwhjB0Kc6RpCH0LTQldCCFqIWkhZIrWnTq930ajfWQtVC00JXwuCihxC1oLhoZOSKwFqoWhhfult10lyUNBelOxfdhTGjPISiBdbCmNH7v2kaQLFhikELegRRjyDqEdy56C4ULbAWqhb0CJL+o4Nk9shQGUVpRSha2KH38E0ZuboiNC10JQyS2UMxZeTqipC0QFrYR7C/myojI5f2KEIZGbkidCWMI83uaC8jI1eEpAXSQtZC0QJrYYxgaMg40jyEroRxpHkIUQtJC6SFrIUBPZZksEseEz/Y5SGQFrIWihZYC/snlLEkg10eQlfCYJeHELWQtEBayFrYR1DGMg52eQhVC00LXQmDXR5CVAs82OUhkBayFoYB9iF0NaODNh5C1ELSwvi4oXxdT+KgjYfQtDA+YR8BjcPNQ4haGJOYh6CWkULWQtECa6FqoWmhK2EQykOIWkha0COI+o8OphiXkpGR+xAGbTyEqIXxcWUI6oZCibVQtTD0gIfQlTBo4yGMSaxDUHck0nck0nck0nck0nck0nckut+R7kJXwv2OdBeiFvQIsv6jgynKmMTBFA+hK2EwxR6kKSNXV4SkBdLC/nf26EsZuboisBaqFvYRjCPOyMglHgMdhPIQSAvj7wwdHYTyEFgLVQtNC10Jg1AewhjB0JBBKA+BtJC1ULTAWqhaaEoYTMFDXcZpg8fED3J4CFULTQtdCYM2HsL+CXUsyaCNh0BayFooWmAtVC00Lewj2B25ZWTkihC1kLRAWshaKHOBR+KuCFULTQmDQ/Z4YxkZufcZHUVpRShaYC2Mj9uVb5SevU/iKD0rQtLC+IQxgnEOeQhFC2MS8xCqBmhaUMs4MnJF0CMgPYJBKA8ha6FogbWgR0D6jw6m2MNEZaTa0h7/KXnQxkMoWmAtdCUMcqhjegc5PISBNv7ooIA6Vm4Y+h55KKNyrAhZC/sI2lCXYegPoWqhqb8zDP3+3wxDfwhRC0kL+w1s7LR5xHIeQtECa0HPwTgf3D97nA8egp6dNtDGHx1W34YmDqtvQ5GG1T+EroRh9Q8haiFpgbQwZnSo5bD6h8BaGCMYSjGsfng3Rz4s7d7wMvJhaXdzlz0f9pZjPoSkBdLCPm/DWTXKyNLuiy4jOZb6/b/pShiG/hCiFpIWSAtZC/uX7i7rMtJmRahaGCMYAx1nij3QW0baLO0u6zLSZml/7lL2tNnbc+QhkBayFm5eAhpO2D05dgpdCYMChqduJMeKML70/j8jLWQt3L40D8ftyJQVoWqh7cL40p0PHsJ+phAhaiFpgXZhzMHOFCIULbAWqhaaFroSStDC+Ds8hF137p9Qxr8Zs8NBC1ELY9RDR5m0MEY95o2LFlgL+6jvCruziwhdCTu7iBC1kLRAWthHcNeQ/RghAmuhaqFpoSthRIrvs9PG3xmL1bIWihZYC+PvDI1vTQtdCT1oIe7aOxZrjxSLQFrIWihaYC1ULbQpjGqzefhzR7VZEUgLWQvjS+8ArIWqhaaF3RoHDY60WRGiFpIWSAtZC0ULrIUxo7tejxxaEaIWxpfWIZAWshbGl7YhsBbGl/YhNC10Jey8k4d3eGTXipC0QFrIWihaYC3sI9hT78vIrhWhK2HwzkOIWkha2Od6HEH3HNp4P1LvFWrj/Ti5V6idQlfC7ocVIWohaYG0sK/pOHXuSbhTYC1ULewj4LGMe1bLQ9izWkSIWkhaIC1kLRQtsBb2vzMuuCPVNu/5/mWk2oqQtEBayFooWmAtjDUdXzoY6SF0JbSghf1Lx3V5z8idAmkha6FogbVQtdC00JXQx5cOm+ukhayF8aVj3jproWphfOkduk9hZOTmETgYGbkiJC2MEbQhZC0ULbAWqhaaFroS4hhBH0LUQtICaSFroWhhaFUYgtKqUcj2rgejkK0ISQukhayFogXWgtKqkbgrgtKqSkELSqtGIVsRSAtZC0ULrIWqhaaFu1b9/vuffvjl73/78V8///3Xv/7rt59++uHP/yP/wT9/+PN//M8P//jxt59+/dcPf/7137/88qcf/u+Pv/x7/x/98x8//rr//3/9+Nv2325T+9Ov/7X9/w3wv3/+5afbr9//NP91OP+nW/juZu/7P9+id6kLxBZ0fAKJ5yDtdszdITrlCVDpCSCBUezNKMcgtvjyKQT6kC2q3ASjtnr6IRl8SHoMo9GciRqf/n05//d8i6vs/35j5jmAYh8APwBaC2cDqOf/vt6OK/u/35TxygD67Sx2X8pyNoB+/u/L7ZHC/u+30+WlAZQHQK/pbAARKaPoc2vXpuB2S7rrUYynQyCwCl3UKKbTISBlznvN9zGIW/GTc6sE2rjFax7atEVrtEFUMwbt56Md49bGaWLEZ4qJQCn3WiRjGGF+CR1H0cCahvwHdvmCAPRyb7A+1KpfRGBZkRDSOQSazNIeGJt/up1OZgJUOV69jNnc4gETgw5sS2hRH3qxXYkmAttV69bIQr6E6vmXAIzbTeHBFdthXjD4AMHITvqDLW7ej1MIxJhV6ELvXYXMCC0/PqNxPEcAqrXFx2VNt/1PMHJ6gqCAWO9hY63X00EQ4M0tZPmYyy1gOZeDrq5HPV8PpBU1RNlBQj+DoIx4r5HwXo6nEGV1TYnX17Qur2lDhyKWA8Xt9xzGFnG0f8pe4PX+KSWefUoG6rln3w+6CKcAmCw6i1pEOlvTnJYJHEHcCiwLc/bz3TBnZCOcxEbUZKTjONBstMeCbI4phcAfaEbrUzO6WtWjZmSgoT23h4puMzNHssVlnzEa4p0ghrLd++bKmlflVrr4jnArp3i6KgWduKqcO7dbkNoU4/OmWACD3ipMy5zeKl0qlOf5KGldPwqt6gf8lrxnbN+/hfQJ9Pgt6AS6l368M0fraiT9GYOX9aN6sCCeEaZ5Jmf1NS8zgrZ6Lg8eS9uo5ozE/ITBQFdpb556Z1NWsxqf+ZTR17QqN+7W6BwjodvyQ8ua2mVfEJCeyrV/C3edIyA23R+bj+9IrCyufaAeVipkXqdCrquqDpe1R6GxjhaloymdVJiAetWwurA1Li8stJMoHiG6Xb5PhwGvSvWh5Ld+y+cTisaRsty3UgPjAEx6e2v1mNEQzhcFM1gT8tlfS50yWAVKyntJvLG5UDrf4yrY83OUzeVWivsaRuWHmt4eG59iNLAyG8RjZerm8Z1GG59NroFZrZket42aldPuBQOdK8s8wMzdKaUDAqGdVnxOt/J05xiAS0sS3x2FawjiOtvClacIULtIBrFF7s5PHa2iu4LY2y30db5PI1vZAurzGNaAnjdEpbEVmt71Gk4ovYfVTQFaSpOt6fZO9PRLelq3lE7rltLzqqX0sm4pnVctBSKYLAVqKOd5hNvCyud63vvqTQFp1+2d12MyYgrXrG2LWcoRbAtMnp+t9x6lp0tL09OsPZvp6KwOtGpveBx7Us6AyDmcjgNdSEfLk/vVqcbTC+neefDcTdsfFkeV9KyyHSTvT1WHzZEOa72AtPVb7d7HbfFaC2e1TeN/UtZix9jL/N0x0MrEtBwTQVEmY1Ak5tWoCJ6MJtayxQTAZDB0nEjoNmd9HMwHkIpO6kl0nXT49xOQHGRGbm1HAEh30PUUvqrrLE7sxE8T8oGus6xMqpnPlxeFm4y6nvKyriMPsoOu1yJ+8A7II6Jo0aYE05lO2tGYDiANncbkY2ot7RpI45ntwCWeg1Bw0HUUerLpOqaQrA4QEVg/oa2fJH1iCxwxAMnQkyxkti2OAjkmEJTVQwhU1k7iaOyVr1l/l4WhkNq5wsNIg836qS9bPwpArVs/BerixaF0PhkoVBHT9EQTaZujD0B6FgoJLQAQpKalyZRsO108v45FFImaEQ+tZNte/MlIelQjUSloryNBbtxexXhDiOdjgaHjKJNyOB8ejDej/Z8rCQVwVV7+w+dA2ythJu+UfD4SeK+acextetr5xBaHq38sDnf/vePh2uU/FofbfyzL138MYbr/QxoYNbDut8wIuKR4nFV5+ayK1b1NH3lIdK7uKCDF+3Ocu/NQZfN0/gCjSrID1wowkJ5muTFvkVNluy+TWpDZibZvx714bjEoKnV7MfRQ1aJBPjgU8bwy1wAORdwgx8/gaenqyHr8GBQ7raR0JJ2PBEWmcpLQ1K1r2QQ55M9FGJzq4hxOQZ02+ZgUCXNJhMzCeXZPRMGpzesnusohnMYt9/aH5+HPntIMfyrbO4YuoQFTlK2GUgA7Z0Wx/iLHowR1HoUQzPsV8mqa96val/erFhz2KxSiMu5XEMK2X2FCM64LijCZ16WV9XVhj3Wp6+tSv3uO2N/33U+aHVwnUJSqZEkGuT24PqfV7kCrfZ1Wuwet9v8FWk2i7/S0XR1ptUNlTTMNq+dzo+ketNo9aLUv0+regHHVfPe+i2vmiyGMtIquZ1kCRbUoo+nHYWToO38oWVYeq0N6boBp23LlLVXraS4HEBSuCvJ6aPPMhFMQPB+xz3Nz7OfzAX1WEsCL+hKwxeQOIChaFR6qXnI4h4hh/SKR0IMo60UioXiV7SLxZhw2AknRYf9PcXn/T9Fh/09xef/HECYCgXraxNHUKp3raQrr5/a9a96yfqTkoB/wfZRNP1J20A/46MGmHxDCqB+IDFmGcWsBCjSkIWqfTBY6AukOakYOOX+JHJL+9h5+i2pGDml/iZbz/jCEwzmGJZ+z1nS+b6MXUypF/9ac7Xy/hAGrHFWe//yafjgOoYjVKOn06ptN/fnYnuCjqb2a1R1Ex86O76Yy0NQtgP84ymw/z3Pb8RYhD+qenkS/GG+m9UtIQrEis/GimJXZeDMvGy+KWJmNFz2fMhovhLDtEZDe40w0SzoZ+6ghKFpl1hCPaFXyiFal9WhV8ohWpfVoVVqPVr0hsyyR1ayeBr+QGYpWma8yMFplu8rgcRiVjD2Oqrx+VGWPoyqvH1V5/agKt908HYisdsyXbZebx+J2h8VFsSrj4tbosLgoVGVcXAjhsLjzcLdNfT1fXPSO6tbl5/EtQXt2Pjll9iSvl3oFXpkKq0Y81raVes6GMPNeQvdF75Z0nA4PNW3rato81LStq2lzUFPkkQmSh3Qrjn+uHc0hVpZQjMq+uHV9cZvH4vb1xe3LiwurUMgDylu5xdMAFXrIuXd7GBOadYGqY+UcFKGiIKm7FJ/K76QPQFKQ7M7nhMYjSEGXZVsFHhSeMpbgQRDWGjxIS20FWxKKTBkrtsDIlLUMj3lVQB0eqB5RHmBTAunhFJbfqFBYfqOCIWyVX/B0FHFPEcPpgMWmxJGy/cynUXIM0qT21obRAUhftltC0Smb3UIIY50lFJmyFlqCT6mM1bPyut3aV+XcbrF6dAnm1q6Oli/qgcJK1hJasGifcW0dCqOl9cpoKDL1QRktDGMtNEIoOmWtNEIwPmV6YPKGh1jIrPWLZNZinyRSz9MxCb2punWzkAiVuvYfKxpigu9y0qVez89UlBxoldZpldZplRxoldZplTxoNa3T6hv1kDToHJ7SoI8TUh3Uo62rxzozQ3euUT1yXFYPmLtoVQ/zqlxWj3lPDqFdu5HlIA+hcshAx1BgylhWlbKDnuZ1Pc3reloc9LSs62nx0NO8rqdvtGPdg1El1Tdvn3XqwSAUUeIkz1M5E9j3Cyo/GdVxKpxu+7B8wXzxm5RfqRw/BewunMX0uajrZayH8xgKSsVZFlDfUHM+QDjkpBAv56QQO+SkEC/npGAIk7sPf0qaGRik1uUVBJ5OJVxwa+92FYSn7bd+EWS/fA4QUu+5X0BQUGrWxdIFIT6C6PLWT78E+wgiBpVdz2B50fupnHn6YrvatPsnczrrFFK5uro0ew5Qb9dAXL4myuEhxtwuWk2VY0yqyHpr/zJIZKmUGrm2iyC1SvaTTm1/AWlp2WoQhNFqWnKwGhSbsuoZnNM+magnMKdw4y11vtN5ajxz2HhRcIqrlHWoujb55qw5gCBlbVm2vKbrsbR66SSiVOR4EkHvp3KR3ie56CTbwzCoW4uX0Wn/E+pw3wyzjIKKkL9gZHSskgOi8vvHeji4ozBIlmY2WSeDvkCgUcgxtepY7gsEiqA2cXGRLhu06fYBBCWlzmhMjKoIG7WjfqDwVH+sbNd+wwNERuGp+Ri8qud1L6OAPCZhx56uUqFkPvRaltkUQcBjjO1DIITtQ4yHKQSBL4V1XgrbxYulrW9HDjB9a9JGjvkUI4Zl10WGL5VMrgsIYXNdZBSUMroucsyrrosMu0gZXRf2VTl3XWDtmFUCk76cfoRRJHEiFTpvIxJhGomUGiud+0UMyWWDGNhaTDG6DJ9L2TQdQRg1HQajjJqOUnOMmo66F3GQUxwHVS/+RdNhfT9Lpxs4jNKlpCYHXZfrZRjdI9aYKazHGjPuLGXr8AJzlG0tiOBbqfWVqRIGLvpZ8OvKmEH6RZAmNRu2n5dBpLdf0b0SPwOZN7nSU76orTFLTv7tN51rK1Z6a5z+DUyVU//2m+NlmD5v200FhT4zwZpmR0zVCOPVBM0g/SrI7PNae7kGErfg6Vyj0AAMntw+vTIxxHx1jZryiDSdafshjGpg2wjor31HPw3d5QJfUc8MMxCWhbcBW6u14hDJxCCzBVWm1AAIPL5K0bDNEwG+Zr3NZC7LfSYhhPGkVdYTqjIvJ1Rldug1aV8VcKfA2sHzaNLyJQyK8jEUe72KEZYxaB5wSIVDP8OQxSVq5xjc1u9HGMN2P4LfksWDuPFdW8e4qGOUJLhDuZ2vLYpURXWw2cLvwPjRQKo8PaDK51QI308ZFxdjOCxujfNbgOFW2ANTSlPHqELEH06qdOqmBrQMPqAy1SzLDfYr6rMZTADHcDSOLPkUWbdNepkOuGfPrlykk0KPe3bL637Atv4wJbflhykQwrhnt/WHKbktP0zJ3eFhin1VAJ9C7TD6ASGG0Q/Y8zqNtfVW1Xn9+VRefz6VHZ5P5fXnUyUED79XQXX5rH6vAttA2fxecFZtfq+CXj+Z/F54Us3umXdrY7wlv4GxXv3fwJi7AmMYq7PoHYzRWYT11ugs+gCkXwWxOYsgiN1Z9E7xrF4eO1mfHvVKrIvuGXzCynme0p46ZB47wS53VClpuaPKm0+ZtdgzcPDgcdged+KB9Fm9NIYEBpLX53S9RxWEcJiOEpN4AGNG09G+qekly12ibCes82EQvNPI3SrpBvSHM8V6/AqPQvYIfbN6HQXS0dl3OSddHNsOsW+6kwdLuAbSy9zFu35D8BFIm4mm+j3VJ5Mqh5Lc0dK2r0Lcdu65R7V4/inNY2Wax8q09ZXBlsvqavTUzfVgudmhkVrJ643U4DhmnlfsT7GM+MnHSFA/dn25eQFpyzsM6k1l3GEghG2HgdNh7bNV0KOqyHVmEXNVYXD+CMTUrKsU6E6wNesqyJNobdZVUFDEWjiowFiV8SVRKagkpOklUYHRKuNLogLL/ZleEmEIW7NuqCHG/lYFPaww9qYqHr2pikdvqrLemwrOqrXpUEGxJmtV6cIOFSELflpltDtU8c9od6hYn9nuUMjKaHcQwmZ3Hk2HSmWPdanr69I81qWvr0v/Kh9a+9qUBvXUVjC4NHLQEI+2VGW9LVXxaEtV1ttSlfW2VHCzM/ZxKShmZe3jUtCrKlsflwKbUlk33U4Omy4MWtk23e5hMN2DUvs6pXYPSu3rlNrXKRXpqa2PC8OIlfEoxMFBPzg4ECqHZULl4ECoHJYJFUMY9QORobGPC8OOVMY+LoweR5nVLDoU+ufoUOif43Khf44Ohf45Lhf6xxAO+7atjwuj8JS1jwsn+ObM1MeFUck+ax8XRi+krH1cGFX9s/ZxwVuErY8Lp7J+6Obk4Kbi5OCm4rTspuLk4KZiWnZTYQiT8WJ6N/ZxYXLo9MPk0OmHyaHTz/7Kf1FDqHpoSFvXkOVOP2/IzNbHhbNDS0rOyy0p34zDqGTZ46ia14+q2eOomtePqrmuKxnado19XLg4NPrj4lBUjctyUTUuDkXVuCwXVcMQDotr7OPCBXbZMPVxwadMYx8XRjEqWx8XhuElUx8X9qj9x+u1/9ij9h+v1/7j9dp/UDusfVyYHZqmMzePxe3Li1sdmqZzXW6ajiFsl1S0Z+caJJmqUj8PP0AQljS5XPN5Tgejx1C2nA5G4SlbTgeGcMga3BZDymfEip7rQpC5uLfqp9dASBLEt03kvFcHt7i8MLDGlG1hcKUrh4UpMo5tE0HTgbJTNt+ipLltToazPJl3ILL3b79VpbwjCODUjfgftlsDJ/A5KPEvzdTjp/jjof4wN1jFcB5TQzx92cl9+e0fI6/OdmCbdRDVTnV0DXGHpSG7ypHvKkXlmGqPYWKevRg2t1s9hYEqW0lK91XKQGX7+tN/7utP/7kvP/2HELYHWtzXn/7XsPz0vwaHp//2ValgVdaf/kMM49P/dxhhGcP2bL/iCJPK2S3p4jhMJQjejMP0wtz+LecY+FuyJJdut7nTp5k1pm+Pw1TGwI5x0V6MZQwqCi9ZyxjggdjKGNS4XqPiDYbD4trKGFTcVspWxuDNQExlDGqi1aNMRW+orGUM4DhsZQzeHlRZHVTzyUG14rZUttMuBLE9+8HH1Cp1Dbef58pO62VVKy2XVYUQtnNQpfWyqpWWy6pWciiral8VwOv4EiN7duz9nE7JgwrjeoAbgtRZd6zqG9lHIDwrNHJtdBFkOoa5Vbp8KdPVDNQbyE8vZTMVYrugFQAD50WKZnDN6erkTmdECwxAwjrD4+tQmDTQLpnO5kOQSiQR7N5l+f5fi0PtHzgO45TipZWA7LbK6aLKx0CqukO+7IeIRZ2K6mXLibN5zwYJLAcVVpJ5UX0l8/GdC36kJuGu2yO1s5edtcBmKLaXbhDE+Aq5rHdjxm/luiRlx54uv5WzZSFUGGli6R9SWB2MjquLaCTRjKvk82YoGMTYL6eicJULiLXpDgYxNt2p662q6nqrqurRqqo6tKrCc2psugPTO7dYwqz3HMAbRPT6f8MQJmq6vctLNiN8DpkliMeZrg2FeT6pZKVn/bg2sAFgF4g5ihQ+eZU5/d1EOmJ1IMWKIlZGKsJvMiW9e9uQ+BLEnsZ6H4UuCP4JhOlD4FM5K6dCECsdtvplEDOnNg9O7euc2tc5tXtwanfg1PZtTq0zZrYd9OspCaGQyN7M++6dVT7Ag1MDxZjKPB4WrR4xlwMISqcOQobbgS6cguDnckY2bCEskwh+LGdiQwhhY8O+fsLsHmzYHdiwwfdUHiBWNsQgRjZsqGK/jQ0hhI0NIYSVDRuKVRnZEM+plQ3he1tWtYMUgbTDt6DGfzQzO6nEUxZ6847Rdj1sqN6fzXjxE0Sj8bKL3aXwZRCz8UIQq/EmWjZeBGE03kQOxoveU1mNF86ph/F2cRF35Sx7MV70nKrEPKsP6rpfR+NNDr6dRssXKvw2zGq8ycG301DMygXEbLwQxGq8VJeNF0EYjRdBmI03h3XjpbxuvPD1X5ogSU/Ji/lm2PpH8plyVKnmL+aLH3cbzRe9qTKaL3yXbTVf3EHTaHm5fRnEbL4QxGq++F2VyXxLXDZfGDmzmi+KZ1jNF86ph/nSDEdudnL+eLehh1W5Sd3e3HVE8mi++PGu0XxRRMNovvDdrdV8ycGB1zh9GcRsvhDEar6wrJrNfBGE0XwRhNl80esqq/nCObWaLzx/kzwniqRcZ4d6FQ09jcqS6ZW1B4/JDlHE/nVG0WcQ9RFTKaqt6EcQHOZborAOUS5CyFzw1blgmQu+Ohezs3q9Ohca4uJc6HruF+eiylzUq3PR5EPa1bnQEBfnoglltHp1FFWqdbWLo+jSHrNfnQsNcXUUUti6A8qBtW3MWXuwQI7xFVSD+YNRlqWm1AAI8qRy/QMSfnnPDT/GmmqHQYx5jBDEmseIS3VYAikYwhRIeQNhOlBmD19sdvDFdvyOygHEeqDEIMYDZcf1/iwHSghhO1BCCOuBsqPHR8YDJZ5T64ESF0Cx3cJ6XA6j4tolVqOBIFZ9j98GMRsNBLEaTeRlo0EQRqOBj7qsRgNrsRiNBs6p+RYGq9OUWXpIJdwfq9N0VCSLorQMoajTMQ4zAuNC+tWOmtZYDxiAz/a6VWPvLnQNQR6HsHqk8hlCkLPd6Rje1PpJ8lgvPF0cDqNAt/zSZ0XJ7IHRzzDMxY9qOC8o2VFcKubZkSZTO/0YSuh2LK+xOKoz9wsGUtGYirgsIoXugRLT+cRC70mfcwKqfcJCTNNv0ePpwb0jZ6Hx7M8e2yV77HQ5fBnEvF1mh3h/z8vxfghh3C6zQ7y/5/V4P55Tc8wBVskKk5uL4tVDql5HHaVIbu5ZPQg5WG6Hr6jkppt1Nyk+Gn91OC2X9SsmrLJlNf/qYbmlfBnEbP4QxGr+pS2bP4Iwmn9pDubPcd383zyhsqX7mNta5fO2Vh09fohtPpNvqq/usUU17r9ktF6Pdwdp3XoxiNXwuH8ZxGy9EMRqvWhOjNaLIIzWW5OD9aKSf1brhXNqtd7mkOHa0SMZo9E0B68qBrHqe4tfBjEbTfPwqrZ1r2pb96o2D69qc/CqtvjlLW8LfEgtpafc8pdenyhnKMxA/XMNw8O+iYJVLiC85zY94jtnD8sxxKwMyT3VaxDTU9XLKQRUVPGJ9HRV16UiXK9l2VwABCYykrftGy/GiyBp9hyhcK7qMYT1zFQMcvMMiXsnt4tDiVEWJ8ZWrqIoLxH1y2MpsyhEUYV/P0XhWbyn9ctfNDmNEvyi5WxqjGHbKTCGdauIIX5dbUkoKVKpVyfFxEpvMEy0ZF4cRG3w+GwjWAhhI1jjIR4RLLxeWQkWX/SsBJs8NDW5EGxyIdjkQrDJhWCTC8EmF4JNDgSbHAg2uRAsfV1tzQSbHAg2ORBsWidY6F20ESyEsBGs0ccJILD32Uiwb/zgVoLNHpqaXQg2uxBsdiHY7EKw2YVgswvBZgeCzQ4Em10Itnxdbc0Emx0INjsQbF4nWBi9tREshLARrDGGjAgWRvetBIvzDKwEyx6ayi4Eyy4Eyy4Eyy4Eyy4Eyy4Eyw4Eyw4Eyy4EW7+utmaCZQeCZQeC5XWChdmkNoKFEDaCNea0IoItHgRbXAi2eWhqcyHY5kKwzYVgmwvBNheCbS4E2xwItjkQbHMh2P51tTUTbHMg2OZAsG2dYMN6kCusB7nCcpALv4GyEmz2CHJFjyBXdAlyRZcgV3QJckWXIFd0CXJFlyBXdAhyRYcgV3QJcsX4dbW1Emx0CHJFhyBXXA9yvXkjOouPcTlvKg8hZm8pXRD6gwfR5k4KGMTWaQNX6TAtLYYwray1VghaWFjFxbrh4Hoy1g0nZQfLhZ2yzBsORrFuOBDFvOHg3l/WDQejWDcc/EXWDYfi+oZDcX3DIYcyVxvK19XWvOHASTFuOBDDuOEYFwdRW1n+FAxhI9iy/CG4yp2VYHG9PSvBZg9NzS4Em10INrsQbHYh2OxCsNmFYIsDwRYHgi0uBFu+rrZmgi0OBFscCHadl3CVVxvB0vLdxFprFhEsrAJsJVhcj9hKsOyhqexCsOxCsOxCsOxCsOxCsOxCsNWBYKsDwVYXgq1fV1szwVYHgq0OBFvXCTYtZ1VgCBvBpvWsiuDhkw4uPunmoanNhWCbC8E2F4JtLgTbXAi2uRBsdyDY7kCw3YVg+9fV1kyw3YFguwPB9nWChR2CbAQLIWwEa+xThB5ewA5S1ocXuJeVkWBTcNBUCGIm2DcoRoLFKFaCxShWgn2DYiTYN19kJNgU1wkWYhgJFmKYCTbFr6utlWDxpNgIFmPYCNa6OJCX8mrQ7w2EJeiHWydGloflqZ33X4wJlR40tBrHzTlNy4ohTKtqbREKX/l5bDbVZbNJzcFqEYh9s8Eo1s0Gopg3G4hi3mwwinWzwV9k3WyorG82VNY3G3JojLGhfF1tzZsNlfXNhsr6ZkPLiQhvmlubNhsMYdps6jrN13War+s0Xxy84hjETPMej7YgiJ3mi0ciIUYx03zxSCR8g2Kl+eKRSJjKeiIhxLDSfPFIJEz8dbU103xZTyTEGEaaL8vRukKwzmPvUsArhjBhPgHZ/mGfIGpOXhYYqklvQQ3lGkqO/dFdLqdYTz+HPOaEPOYEB5SscwLbbdnmBHV66L3M/jm6Bl+pn4BMhe06X/QIEuGhMUgV3e232jU+grEVFMMQpoJibyAsBcUyKnJhXZk3ILaVyfhNuXVlIIxtZTCEaWXeQJhWBjV3Lp1mi3iaZwHi8AlImtXeczgFIdTePWUpBphynCfxA0ZMDbF87vNooypovoKgArhSzr/RHEcs9AHG3qV4YHAEGCjekUKX/hlR0eqhmO8GApxYe8PGMZBe0UBgBfwqZ/qqelfQ9bWpp2uDlYRkl9iUhK9hFGkIlrbt8VxHOmqk0ee9sXO/CqKM7xyEYltVVkKNNLbLUZ1XnAw6k2GY0KK0WQmNLsP0qk42igk+hKkkrTBC5XgZps+LQQsNwKCUipq6HIP5fO/6AKRfBenzUN8LAMFLra5Ljc6f1byh/CYOh6Iu6Ecjoghbc81mmqccSfAxW5c267VrkiQ6jgM2A1ZNhnIHH0Pr+xehyJZx/4IYxv2LUPEA6/4FdcS4f0GONO9f9rWpaG1ge2PpAhW3G9w5CDI/477xbiTiekm6U+jrSMCckKxwDmh1YFcrY29NPJIcpW0JE9KTBBU2TIVt1+Y1zdbxKbYM5rU5zCuqa1+6qBqHDLQeBtxM8wr5tUVpBtWiWuAjv+J9y3iFfANiu0JCEPsVcvvA8n0c2130DYbpMvoOw3IbTQUFY+qM57TzG0Jev0VSjg67MHq7bN2FEYZ1F0avWMy7cC7ruzDu1Wvdhc1rU6/piPESmdfvkIQc/dY75BsQ2x2yLF8hm8sNsrlc2ZrHjQ2WSDRe2OwY/SKG7brm4/N8E4Ux3svhWMyagr/I6mrAKC5fZNbaNyhGrUXZDFattWP0ixg2rWV28dRXF09FdnBUwLZbFkcFOg1Q5QfVU+2qN2N8GQZqupNk9yPSJ6RPMEgyCIja+XGx8mrAD84Hy3WNmoqA/sF8AF5rIcvup7Q9HI/gFSX0S3mY3i9jyOJu2p5OQfLysqBz3l4FZxzhk0oMCR8gyJFV94Z+QYAp75KGFItuLfXBTMSc5ikx0SlGJNT5J/YkC7v9Vkt7DJ8ux7XRiZe63Gm237opa3z5mr5u+BDDaPh9fUZgU0dxKGw/22nqw6qeQwSTnqOvsOo5xDDrOYpDmfUclhsJcqlKSke366cdo8ikplIABrwfZrmrbr/Vt7xYS0Z5IEZrwRg2a8mBvsofTzNStD/xMCMwr5OTrC+rA3fa5uYaRl3H0A0uDxioXHuWC29uynZjMiMUcXU9pWF+glDFWaYyJl4QkHNIHKKt1GsI0iy86cTJawhMpwiwgytJkmGmdo6BejinMvcDjuUUI2YUroqpCJcmdfH5A5S6qlsYw6ZdbzBM+vVuRpokLSfdOHUBha+iUJB7HIV2GYVnGnalqyhleh9KvjwvND2ZORQXlH4VJSe5a2eKl1Fmt97MfB1lflG9rLtZ6DHmdnmlc5dbWQnhqi2WJmGNfBWjJXHz0mWMIBh5GYPD5XFIIICxJaPcxyhlXamvjwNwJOx9YWJ7hGDjeohgO0n0dZ63Y/A1DCPHYwwbw0MMI7/Dc02XM0nurV3CIBa34/bzXMvxeblIQJTr+Xn5djNY9F3CYdQqx/YWCA0DuVBLfSxM1RQW2xEE5axQm7cyHc08Xg9RgcE083hIu+teQVAGQAx5BkP0s6PDB8GZbeICSE1fmj+5VDVxPm4/+RwDXjOnkmy/4cUbjaULKW8hGQVSn526Fb62jY+RZJ0EcBwIwigkT7mK5pEjRsP7i+TFV/0c7BMMFkV7yon4CKOTHEC6eif7cv+P0FslF++b54qvosy3QtvvdhElqSSAjfCBqjFaY9myWJ+/A3+AYfMkvsEw+RKRXzbGpt5g9XCaBZRhQ+gox5kegb8KYiTZw3tK7Yq/qjR16O58UdO2o6X4NFknvrzqCApTWf2AEMPoB4Sctu4HfJ6ReH1ey0RJ6SJKlCdD2++MLLil9dWBGMbVgUUGHVbnaUZKvbw6WaGc82vvq5wGEWzREfglNU1trT0BDUHlb2yxIoyx0SLJ2lRWh6zPUKrke22/OV5FmUxfdR7dJ3Pb6tSSTiCiGOCLh6A+KLR+DSYlyVNOFPQdOFwEiekiSJH04FQ4XgPZPiHJzeDJ8XQE4eVkAIixhabkBqrLX9yY3w4S5Qq6cVw+BykoiGWkaYxho+kSyipN4wlJQgX5qbTY64SgKEEPUihC12f4AxR0fpX0te2Ac3oZfjOQWbGiP11zPvucedEJqV1HkfTvUK5PbZes2sABqD06bZGkXGSCIMvbKIYw7aPwU6xpBhjEmmdQ0Dssa55BRA9SWpFEg6aHEo+u371WziojQQwjI6Eag0ZGwhPCKhBc0YQspwUWOKVyGiB6uheU4zgAvxrT8UpCSdO2dDyMYdyBc3DAQIesOC/DKetZPby9KKi7Ek1vpYoe1QMEzKiz2i5O7atCztvlRNUYo/gRTKPpIWjqse3HMJMadQLDKwx8x5UFJTylfx9jUegpdJDNIm14AAR+0HzJvP3WD9w+mpctsjevB0EdHV9gClJ/L5ynF5XE53ODURLJDSGpK9wfoBB2tE0/W7qKQvNpZtZPMz9DUXldRaW9/AEKOtAaa5bhyZ1Rt0QNTW6HwXbTA2tUgc145oIQtjMX/BLrmQtPh/XMhaJdZt6GLQ2MtQ0KjHYZX1WWArTV+KoSYhhfVe5ZG+d8bXtVCWtlGl9VFsb+LdurSvvaANODSmIsbVBgWqSxtAEqV8SzHh0/PRWnD0BqiA9Nq7o8wkcg5tIGEKRJkHjz2yEQtKeHeS2+/Va76PGxOYTZDg5z/8sq8vYpTMwTJoOn73h65RUu15yurpGtt3Ps8Bpnqj7xptqXqfgExDDWnigwWmWrPbHn3IKTqK32RMFPxGyz6tD++426BlIPRfXx/DOtj2UaT6yXbTDOKsAbJDAeeMwpclLSqdufnZQkf07nNb6clPBRWMZxez55+Sgc5hOHFD2O5Qjlze0pzEDe09bxcutxeK5VHJ5rlR6/i2H0cr25286Ct6yrzL5Oa1+O1GKMm89hDgXpLEThOAOc2tf1GcrejHqgtHJ5LF0CgimEeBHF7MTAY1F5ZM+UnY7UFB0u6hjFelHHKNaLOnv02XozuaL+8cn/9uG0GEn7zbQYSdu+RAgllXVPLfLD1yIn7C24r2N66QNnfpwvqijl3y86822czXH54WFEFZsby/m88VPe4UsFwGWPDoSweXQoOHh0IIjVo8Oxe0TRYBFcCUAnJrA0nBz8QpzSul+IUVE2o18IYhj9QoyIxOoXYhgDs/mFGC6w1S9kXxvkkk0OjiGm9TpX70Ziq3nJlJbvx0weLiqIYvZR4bFYnVQYxeqlwihFtj/mEBAKLlWliv70BO7r73CsTjN+Ux7N6jV7h2N1m71ZcaPf7A2K0XEGrcno44FmbXWdYRCj74xRGNfKDbk5+M7gSKzzSh7Oszdaa/aevcExu8/e4Vj9Z/BQafOf4XOpyX+G6nRbLy7oGSwlkozVVHRGVf4ApMpDVupPxbg+ANmu2Fnsp/RzEOb13K7oEIpO66HotB6Kjh6h6OgRimZ2KKcVYc+qrHLOYz1XEYLurumi7Vlf1eMHIFWe5MentgFHEEavt435box6Zxnz3TCGNVcNqcn2paIn2187X2Dk5qriFcqV+rW1ySyPR3LNcG3YYW2qw9o45CIiu0lF9qu0HfoAtTYHbW0O2toctJXxOSvMZMQez1roxeoSEM/wECzO6s3tpnX+eNBqsMA2yfOVmsE9G70VNntj2nJTIoxh9cbAx19WbwwKXlm9MT15eGPMa4O8MVhLJF18G0q+BkJRvodir5dBwjoI8TzsqczDF5DejM6lkq6OZCZZU788EltNePvnIBD4OVn2ctJxlSNIDfT1kUibb9oiaQ4gV22HkrxzotwqmBNkxTzrWteEGAUOpUrclyoTGEpf17Y3IB5rXOP8HMBKFbY0ClU5CMrlmZUXF9SAulV0Lzc6girsImt1BMGRWB1B+KQ0S9xvOnN6pa7xDYqq61DaJRRjWLI6RK1qcugRU9N6jxiIYTwn1eTQI6am9R4xNXn0iLGvDeD66hC0qsmBGqtHqKh6RIqqR6CoesSJqk82c/VJQ64e4ZTqEU2p68GU6hBLqQ6hlIoaPVl3UPh40ryD5rg+qx6RlOqThlx90pCrTxryG5/hfD7JoCpKfYMiJc5uKOUSijU31OHJLyzP0qfLvif0ahJ2m5H6t5UbeGhbUZnDwvTYSQvr7NLDQGBjAPXuUhfTTPwBSJX9a/NyhXOQWuq3UUbw6aFq7SpKnb2ndHWjVxQU6qqymVYdIPoIQ/XELO0iRgwq4UJZ3x+goJRDY4Yrntg+YxA9gYlFde1LkwTKzUs8N47+AUZsrHJtWfu6X+LnAIZn7SlmpSj9ZWbbcqSZYU6pFNUkUm1G45HaKixWbCMUFEYsRWqzbBcvvgQxY7Pbz3wNwvQh0BNrZUbszrVyWv06ip0ZIYqZGVE7LSszwpZcRmZEGHZmRDUKzcwIJ9bIjNu534MGWlm1noScfTYawBAmGngDYfsQBxrAIGYDhu9HXVDsNIBrDlhpAL13sdIAwrDSAH5/baUB1KjLTAP4nb6RBqDTn6djS40jH2rPtYCaJ5BcIDPp5yH5uWBUQr4+8z2nhXUzhj5UqxlDEKsBtlC+jWI2Y4xiNeOG6s8ZzRhiGM0YYpjNeO9PvGrGeGI9zLiL57IrB86rGaMAU4kSWS3b1ezcjNHzXrsZx+VDeYKFuKxmnD0cDS32b6PYzRiimM0YxruMZowwrGYMnzWZzRgFvMxmjF/zGc0YvRpNEyTpWXk1ZISy+dllP34qD380ZAoehkzLboIEEx6thgxBzCb4fRS7IUMUsyETrxsywrAaMrGHIVN3MGQ4sR6GTDNythlMBYYM00mbVFDIXQfPjobsEkBoeTmAkDwCCMklgNB89vXsEUDAKGZDLusBBIhhNeTiEUBoxSGAgCfWasjwkRnN7hWkmlj2dPwcWJpTFYmfH8P0AUYRKtCZMB9iSAuNorocfobBUm/gqVb9ZYxyFUPmgy/PB8t88OX5qPIt9fJ8aIyr86E7+12dj9lipV6ejybf0i7Ph8a4Oh9NGKTVy+OoD0Js7eo4enjsEf3yfGiMy+OQR24dcFBC+TPW5DMIYq4M0FAIpEZZmqq7k/0BCnLDcv0DXt4iIx98jjFn7A2ILSEPgxgT8hKK/xuDMRDCFozh9Vsje3hx2cWL6xLZhSj2w2bziMm2th6ThRjWw2bziMm27hCTxRNrPWyi7A77Va2vx2Rh4qfVeqpHELKhN1A+KHbrgShW6+mo0J3ReiCG0Xoghtl6ukc1Qzyx5qsa7pAtjx9Ydy7v8fg9qP5FlJICFLM+bR1BoKKolym6HfSxPDDuGSX94HUxj48g5O0D6xa9n0EEOfOdjiKh7uclpNnI6+lecRgGrGJY5DFX1jU0FkD6GcgbLZOnIKmqCquvWoYCXDHPwhWZGviciq7R8uyIoy6h8QICq+gkaSwfI4XuAhPT+eRCb0uf06Ls5uBtSbDh93Ry9Hh6qI8ddvOyXQyaxxbaPLbQnsq3UcxbKEYxb6FpPY0AYli30OSRRtDJIY0AT6x5C0UN5kOYVF0Uy4aXbg4ow1hu+Fk9nTh6TDuBryG5EOekvSYHHkCpiebDdIczYjtMowIYdibwOAZ32N7JBcXOBDl4MAEq9W9lAoRhZQLYcsDMBB49vPDEWh9OoDhOajIppF+ovRRe6vA5l+rv11TfuJf3yNXDjtFbLGuaf1i3YwxitsCSv41it2OIYrZj9NrHascIw2rH8NWR2Y6RA9NsxyU72HF3sR7Yzcu2CwYH68EgZr1n/jaK3XrYwyHbed0hCzGs1sMeDtleHRyyeGI9dkGa7cPpKbP9uAsikBxm+D9wAlsp7KHlgsKt5BkkOn2jjTFmuT3uqV7EmM6tjY9PMaDCigulp8tKLzXUei3rhgMwMK+RvBTfaDJeBElNkkcpICppDsmwECTu7TPuzqDcLg4lRlmdGFu5iqJ8StQvj6XMIglFFSL9FIVnQZvWL3/RpDZK6Iv6eg43xLDuGd0jh7v3r6stCStFKvXqpBh5CWIYecm4OBADHqmN3wIxjN9iPNojjObAsW/ugDaOTSGsKysGsXLsOxQbx75BMXLsGxQjx75DsXHsuy+ycWwKcZljMYaNYzGGlWM3lK+rrZFj30yKiZfeYJh4ybw4kNug+9HIsRDDyLFGNyiaD+iltp5jsb/cyrHJQ1mTC8cmF45NLhybXDg2uXBscuFYcuBYcuBYcuFY+rramjmWHDiWHDiWHDgWBnuNHAsxjBxrDDpDjo0eHBs9ODZ7KGt24djswrHZhWOzC8dmF47NLhxbHDi2OHBsceHY8nW1NXNsceDY4sCxxYFjYU6qkWMhhpFjjbmxaD6qB8dWF45lD2VlF45lF45lF45lF45lF45lF46tDhxbHTi2unBs/bramjm2OnBsdeDYus6x+NWMjWMxho1jra930HzAx1VWjsXPvKwc2zyUtblwbHPh2ObCsc2FY5sLxzYXju0OHNsdOLa7cGz/utqaObY7cGx34Nj1mNebx6ezDBqrnI+P3q/Odky6TvMHb62tjQbegBh7UeCyIMY9B5fTt+05xvIkaG1h9RjrnoPr2Bj3nBjWaxVhEPOe8wbFuOdgFOueg1Gse84bFOOe8+aLjHtOjMsltjCGcc+BGOY9B3aQ9lFb656DJ8W252AM255jXRzIbcTrHEu8zrG0/C241J6VY3HRPyvHJg9lTS4cm1w4NrlwbHLh2OTCscmFY8mBY8mBY8mFY+nramvmWHLgWHLgWHLg2LSel4cxjByb1u8osH6hlWNxhWQrx2YPZc0uHJtdODa7cGx24djswrHZhWOLA8cWB44tLhxbvq62Zo4tDhxbHDi2OHBsWM+zwBhGjg3reRbJwz+dPPzTkT2UlV04ll04ll04ll04ll04ll04tjpwbHXg2OrCsfXramvm2OrAsdWBY+s6x+I2RjaOxRg2jrW2U4LzwQ4ci/tuWTm2eShrc+HY5sKxzYVjmwvHNheObS4c2x04tjtwbHfh2P51tTVzbHfg2O7AsZ3XeSktxwAxhCkGGMCH0N64dIfY1F09+X7pq4YKGkocsc6FzceW53U95wRjGPcbYxdPeC9w2G/etHs17jcprrc4wCDm/eYNinG/wSjW/QajWPebNyjG/ebNFxn3m5SWO3NgDON+AzHM+01KX1db636DJ8W232AM235jXRzES7gJtWW/eQNh2W/edJA3Mj2vZ3pYO9kjDI9Mj+iS6ZE8nnRBEDvTk0d2IUYxMz15ZBe+QbEyPXlkF6a8nl0IMaxMnz2yC1P+utqamT6vZxdiDCPTGxcH8RLaLLhI2yKeVRW3a8AHELkLRD6HgEW9baPA1cltowDTmUp7NMlLT7Ybwwcg3KWuHHe6CNIm0fdQroFsO4RUjg8JfE5BVZwoyIWNQqOLKMY6XxjDVufrDYapzhdcm6oKrudwcYGfQPJVkDRB6HxpNkJApY1Tl9aQFPPJlLzBINn1iFo9x6jfxchRviWneHF5pdZ6qrqM4mcrI40OUu1XmUSP5DJIk2P49vMyiJwkIEhfpvi+zvAZvnlKUbbMdM4hbzCkcuj2s59ioM46xg0PY5jmo6Fi4lVmo1Td9eHQTgNjiJZuPy9itNmRo6lV+QyjzWaSuqPcRxjzzqpbln2GIbaywV0cR48PDdt+Xp2PXibG+bqg1hW5zCP3dq9Zx6j5GgbL5TlzCRcxqmwNFekY7kEuTS25nhcvTqnjri8yIxyUZ6R8NBK526EyyttICvLRWMooN4dm6M2hi3lKHn25MIq1iPIbFGMR5c2Js9yXC2MYr+/k0ZdrQ1nvy/VmYo1FlOGbS6sRE4piWY34zUhsRkzo4msz4l7WjRhiWM2PYvo2itmIMYrZiFGNQqsRIwyrESMMuxGjrlpWI8YTazRi2FRLNwZK56esRAk14UjSTK4k1aFvOy4dQMDncE3zZazyhB9A8NeIM7CE2tHXZI+vKd/9mij9lraf106NhaJ8CyW6hpHmOFLxwKgXMaTV9fO6fIRR5UaQ6uU55Tmn6SJGmhg5AE2FhGbzn2MMm//cSqwAozuE9bpHVI88HmlBEHNU7w2KMaqHUaxRPYxijeq9QTFG9d58kTGqR3k9XxBiWE8U2SNfkPLX1dYa1cOTYmSlvJ4vaF0ciLFe++4NhvFb1mvfNYfn283j9TZ5PNGCIHaGLS4MW1wYtrgwbHFh2OLCsOzAsOzAsOzCsPx1tTUzLDswLDswLC8z7JsHY6Jo+SlAny5i9GsYWSInMVO8iDHdJZn5Ksb8lhouYog7bGNGuoghHdVviQCnGBVVyypN/Gn5GsK88HW6iCDX354XEbbgyTWEKvHF0C4hcBRfAvXVMWSgVbS6mhDBtJoYwbKaNgS0mhDBtJoIwbaaxjGA1cQZsFlOg9qnk8JxN0MvcowpLxjDlq5CKJzhgWFLecGpybIdJtLcfZzTjE76RbzlHMOZ2xAOI8+cGX1O+YNh0LoTNKNYldEJCr+mJFHUzXN4+jUYo8iMFD6fke30gFqElRwEpYSLKMYEvuyQwJfXE/gKojFT6g1EMCXeoFxm2xgggmkM8BDc5bjVu44+HiKYGGOepLuuCnrAiFThS6C96vb9ohPUffYzHKOOYgybjr7BsOgooTh3aOrq1+i83uobFMkjuqHQKQoqy2TVE4xh1RN20hN20BN20BO+pid/2YQf//bzb3/95e9/+/FfP//9139u/+73G9RvP//4n7/8dBf/+9+//k39t//6f/94/Df/+dvPv/zy8//56z9++/vffvqvf//20w3p9t/9EO7/5z9i2fa2P23/l/tf/vQDjf+kx+0/aSFu/0l8/I/S7X+U6+0/ivt/1LZvv/3f+pffb0P9/w==" + }, + { + "name": "process_message", + "is_unconstrained": true, + "custom_attributes": [ + "utility" + ], + "abi": { + "parameters": [ + { + "name": "message_ciphertext", + "type": { + "kind": "struct", + "path": "std::collections::bounded_vec::BoundedVec", + "fields": [ + { + "name": "storage", + "type": { + "kind": "array", + "length": 17, + "type": { + "kind": "field" + } + } + }, + { + "name": "len", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + }, + "visibility": "private" + }, + { + "name": "message_context", + "type": { + "kind": "struct", + "path": "aztec::messages::processing::message_context::MessageContext", + "fields": [ + { + "name": "tx_hash", + "type": { + "kind": "field" + } + }, + { + "name": "unique_note_hashes_in_tx", + "type": { + "kind": "struct", + "path": "std::collections::bounded_vec::BoundedVec", + "fields": [ + { + "name": "storage", + "type": { + "kind": "array", + "length": 64, + "type": { + "kind": "field" + } + } + }, + { + "name": "len", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ] + } + }, + { + "name": "first_nullifier_in_tx", + "type": { + "kind": "field" + } + }, + { + "name": "recipient", + "type": { + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress", + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ] + } + } + ] + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "576755928210959028": { + "error_kind": "string", + "string": "0 has a square root; you cannot claim it is not square" + }, + "1004672304334401604": { + "error_kind": "fmtstring", + "length": 48, + "item_types": [ + { + "kind": "field" + }, + { + "kind": "field" + } + ] + }, + "2920182694213909827": { + "error_kind": "string", + "string": "attempt to subtract with overflow" + }, + "3206131020419630384": { + "error_kind": "fmtstring", + "length": 75, + "item_types": [] + }, + "3305101268118424981": { + "error_kind": "string", + "string": "Attempted to delete past the length of a CapsuleArray" + }, + "3738765135689704617": { + "error_kind": "fmtstring", + "length": 58, + "item_types": [ + { + "kind": "field" + } + ] + }, + "5019202896831570965": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "5727012404371710682": { + "error_kind": "string", + "string": "push out of bounds" + }, + "6485997221020871071": { + "error_kind": "string", + "string": "call to assert_max_bit_size" + }, + "7233212735005103307": { + "error_kind": "string", + "string": "attempt to multiply with overflow" + }, + "8270195893599566439": { + "error_kind": "string", + "string": "Invalid public keys hint for address" + }, + "10676044680617262041": { + "error_kind": "fmtstring", + "length": 98, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + }, + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + }, + { + "kind": "field" + } + ] + }, + "11732781666457836689": { + "error_kind": "fmtstring", + "length": 77, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "13649294680379557736": { + "error_kind": "string", + "string": "extend_from_bounded_vec out of bounds" + }, + "14101993474458164081": { + "error_kind": "fmtstring", + "length": 61, + "item_types": [ + { + "kind": "field" + }, + { + "kind": "field" + } + ] + }, + "14225679739041873922": { + "error_kind": "string", + "string": "Index out of bounds" + }, + "14657895983200220173": { + "error_kind": "string", + "string": "Attempted to read past the length of a CapsuleArray" + }, + "15200354114977654233": { + "error_kind": "fmtstring", + "length": 144, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "15760694058516861966": { + "error_kind": "fmtstring", + "length": 128, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "16218014537381711836": { + "error_kind": "string", + "string": "Value does not fit in field" + }, + "16446004518090376065": { + "error_kind": "string", + "string": "Input length must be a multiple of 32" + }, + "16954218183513903507": { + "error_kind": "string", + "string": "Attempted to read past end of BoundedVec" + }, + "17226037485472400844": { + "error_kind": "fmtstring", + "length": 132, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "17610130137239148460": { + "error_kind": "fmtstring", + "length": 98, + "item_types": [] + }, + "17843811134343075018": { + "error_kind": "string", + "string": "Stack too deep" + } + } + }, + "bytecode": "H4sIAAAAAAAA/+y9CZhdR3UuWqf7dLtbavVRa5YtW6c12ZYlW/I8I1meZ2zZBkMwsiWMwEbGkk0MAdrMCfFsgwcMLWxj5iQ3CRm+XELmG+7lcUMGXiAJueQmwA1jQpKbhJc8trRX93/+8+86tfeu3Tqyzv4+W7t3Vf2ratVaq1atGk7N7X8a6b933Lnrlh27d990+4//t+3WHdf9+FMtTaqn/x6W/pt8H3Otj+VtuqCnliNva6EcNGquehp9rnoa/a56GnVXPY0BVz2NQVc9jcNc9TSGXPU0hl31NGa56mnMdtXTGHHV05jjqqcx6qqn0XDV05jr8tMoQmfMzQydeeF592FvEt/y0Jvvqu+jBa56Ggtd9TQWueppLHbV01jiqqex1FVP43BXPY0jXPU0lrnqaRzpqqdxlKuexnJXPY2mq57GuKuexgpXPY2Vrnoaq1z1NFa76mmscdXTONpVT+MYVz2NY131NNa66mkc56qnsc5VT2O9q57G8a56Gie46mlscNXT2Oiqp3Giq57GSa56Gie76mmc4qqncaqrnsZprnoap7vqaZzhqqdxpquexlmuehpnu+ppnOOqp3Guq57Gi1z1NDa56mlsdtXTOM9VT2OLq57G+a56Ghe46mlc6KqncZGrnsbFrnoal7jqaVzqqqdxmauexuWuehpXuOppXOmqp3GVq57G1a56Gi921dO4xuWnUYTOtW5m6Gx1M0PnOleAzvVEMNnQkGw4SDYEJAv2yYJ6suCdLEgnC8bJgm6y4JosiCYLlsmCYrLglyzIJYtlyUJWsriULP4kizPJ4kmyuJEsPiSLA0nwPgmuJ8HvJDidBI8tuDv+4/+S4GUSXEyCf0lwLgmeJcGtJPiUBIeS4E0SXEmCH0lwIgkeJJP7ZPKdTI6TyWsyuUwmf8nkLJk8JZObZPKRTA4S5z1xrhPnN3FOE+cxce42/fi/xDlKnJfEuUgG/2RwTgbPZHBLBp9kcEiMd2JcE+OXGKfEeCTKnShfohyJ8CaClXT6dS77sc7N2H9z19b9n4fS5D4olmM/SG2IyOUrP/ELQwyYq7zrH0rLDBUrf72VHy5Wfp/4Js/LJqbLY10Mtz/997aJ6bK3TbTStDyfhjyfpjxW34L8flnJ9o6NuNY2GoaDus0qhj0P22RPP31D/GFXqu9rNcIzetw+040RyzMxTa9GafWJ9npa2gCkGf8T07cW8nHfDlGa1SV5TH4srR/Sbk/TrE/qgJlDXl5XUl42VSgvmw9GealTWn2ivZ555QX7luVlwE0/ZkssbRDSfo7SDoO0n5+Ypn0K1OPK9L2kTfoFK19wDNrnEjB9xNpX34np/CYj/fDNeG28H8L8lDYMafWJVjqz0r/rQAexDoN0zH9y+vdo+u8glLHyDUF/kOi31Ft8Y74Mi/zDIn8iR+utzm5azrZMTOPl2eNp5c+fKFR+yu+4YKJQ+T4rf+HE9MemC3qmaF80Icr+cPeXP/Lf7/vF3/3onuefe9/YV+Y8MXvdrLe+853fO+K7y578/jufsbIXq7Ln/kr/ja/+hX/bNfuit//cG77y51feNWfZtt9e/p7nbvy9h5Z/66Z3WdlLVNlv/uxTb2383MOTzeO+8E+DFz3w7Zv+8ZKB07/yhZ9a+jtv+9G3vv+Ilb1Ulf3SjT/6y19qPPLGn7zv1950+jHzt33ykS//4P/8wX//dOMf/9enXv/lU6zsZWnZoj7i5ROFys+18ldMuPa63/vsR/9y831f2PA3P5r1M1dse8dPnvTeP77hO29c8vzqv33Np5Z9cszKXqnKfn3Plof2LL791O8MffG+jXuPOPJrP3z+l77xz/fsOP3b3/jmZ8b/0cpepcp2eKzs1RPtZZecePQZdzz+Pxf8xTErvrrpc588/tGlP1x19l/86sV7v/9vf/h/oeyLRdmMp8Z0r5mYTsjB6ym9uHaiUPm6ld86Uah8v5W/bmK6fM3ll7XrJwqVn6J/w0Sh8lP8e8nE9MemC3oGrOxLJ9rLrj17+PvP/cxb3un++vm/v/+f1/7GpvVjR20eO/5PnvqzI15358uWft/K3jgxXe8cfF+W2PRkTD8hnRcmU/BVaeJde3betnPPPZt3795x554tu26/Y9uenTfftuOqO7fdctuO63fcuXvnrtcxYI3+vnBCf0/oLGylc9GOPefdtuuW11551+0377izRqBDgoA11gnw+W3gW3f+eA68Z9vtdzDEcAZ0PQN6aRv0ll2v2/NjruzZvH37nT+eZzPQLEHAZYCPtYGnnGbQ2aVAt7x6287XXbKdQUcCQc1dnEPl1b/J0y++mYvRICzkmLmIo5CWQy2vtvKNYuV3WPm5xcrfaeXHipV/lZWfV6z8Lis/v1j52638gmLld1r5hcXKT01DFxUrf6uVX1ysfNPKLylWfreVX1qs/DYrf3ix8tut/BHFyt9i5ZcVK3+3lT+yWPl7zM4cBR/Nhhj2cvieY+g7MsROIf4w1SUnvakwwnKix+3DMALyCss2RJrPRvaLb30erEZErLkRscYiYs2LiBWzjfMjYi2IiLUwItaiiFiLI2LF5H1MHVrSpVhLI2LFlImYvI8pX4dHxIqp2zFl4oiIWDFt9LKIWN06PpqfNSTS8oTWrfyKYuX7rS3j+FHUyfDN10HfqJbxr2FxmtEaJqycda/56o71434YB3pNeM/CGs+JNSTSivRJ02W3C/HLypCv7crftfyrPPXD/KNp2koov4rqvrpY3fusLitEXVYBpuEnQRazCWmQ5fwdN9916+W7bmVsFF1kzzLIg2zvc+2quDIDy9HfjNkPePgk1V/UWv0Ld+y55dVbt916647tP27EbirQhmBrIvx9xLULgeUpaWT6Qg2D4Q+7UgpU8wmFUuaEqzaApVy9fNe27Vu23bH7rtt24Io+qgRTqREqfuN+x7R++jaL8uEqVvLYKk+/y36MY0Z3JaQpThimqWqWDHOvHCXo2rc+kX8FYa0Q5azu/Z7yiIHlWGJ8Uh0ildaO5FEm32iHhD8Kas+CotpTNvzh43XyGF+sfSuL0Zvvk1HEZBdklUgzLDP3A04PByuhDZgf35OnTt++nP7bIMzksVVI3/CI33Dl/o+obch7lqMyfEY8qxd+Q/xhV0pua75+xfaxHK0qRm9eCN+xPsbr1SLNsNakf6McYf5V0AbMj+/JU6dvf5v+23DtMsdytFq0B7+hHH2N2oa8ZzkqyOfgXV2GP+xKyW3N16/YPpajgi7lphC+Y32M12tEmmEdnf6NcoT5V0MbMD++J0+dvv1j+m/Dtcscy9Ea0R78hnL0nfR9KKM9TRf03Kb6Ikf5Nwy5dl7lKL/Hyh9drPyrrfwxxcq/ycofW6z8Biu/tlj5N5tsHgcf2Q6sg+95diSE2gHDH6a6FLUD64get4+XZdaLujREGi/LrBd01gs6CmtuRKx5EbGOiIjViIi1pEuxFkTEWhgRa1FErMURsVZFxIop993Kr9URsWLK6pqIWEdHxIrJ+5htXBoRq1tl9ZiIWMdGxOLTFugf1NJ/h0S5vHNLxLN64jfEH6a65KRX8/EF28dznuOL0RurUXmkh5hWH+P1CSLNsDakf+OcB/MfD23A/PiePHX6tiVleIMwk4fnPCeI9uA3nPOck+KOivZwfCmvvGJ55iGWY3kt05+IZ/XEb4g/7ErpR80nP4ov1r4TitGbG9K/WB/j9QaRZlgb079RXjH/CdAGzI/vyVOnb1tJXlG2WV43iPbgN5TXK2utbUPesxwV5PMFoXJk+MOulNzWfP2K7WM52lCM3vkhfMf6GK83ijTDOjH9G+UI82+ANmB+fE+eOn27meQIZY7laKNoD35DOXp5ijuU0Z6mC3tYxwwDsZEP4f1U+0GoHBr+sCslFzUfH5U+WvtOLESv9n2WHaSHmFYf4/VJIs2w7MQiyiHmPxHagPnxPXnq9O31JIeIybJzkmgPfkM5fC3ZM+Q9y1ExPrvzQuXI8IddGbmdliPVr0ofrX0nFaO3OYTvWB/j9ckizbDsRDHKEeY/CdqA+fE9eer07a0kRyhzbM9OFu3BbyhH95A9w/YkT9MFPTXVFznKt/EWMQwbeZWjn/8zVI4Nf9i191sROT6F6GX1g7X9VFGXhkhDHmMa0jlV0Olh9bB6WD2sHlYPq4d1cGOd2MN6QWAdCvLV06FeP/bsRE8fD1asnnz1ZPVQlNWeP9HjV6+NPd4frFg9We3JxKHIr5589frxUMTq6VBPJg5F3vfsak+HevzqYXXC6s2tem3s2eierB6sWD356tWrh9XTx5lsYw+rZ3N641Cvjb029mxOj1+9fuzJ18GL1Yt19NrYszk9O9HD6sl9T4d6vO/pUA+rm2W150/0ZKLH+x7vZxKrNw71+NXToR5WJ6xulwm7lxbvDFtJdNT9XKd46GB5yzciytXSf4dE/RI6TRf0BN9bZvjDrr3NOejVfPxXfLG2nybq0hBp3M+nCTqnCTo9rPJYJ3UpVq+NLwx+HQr16mG9MPSxZyd6WD1Z7dn7maxXrx97bezJV2/sOFjr1ZOJHr968tXrxx5WT4d6MnFo8r5nV3s61ONXD6sTVm9u1Wtjz0b3ZPVgxerJV69ePayePs5kG3tYPZvTG4d6bey1sWdzevzq9WNPvg5erF6so9fGns3p2YkeVk/uezrU431Ph3pY3SyrPX+iJxM93vd4P5NYvXGox6+eDvWwOmH1ZKKH1cPqYfWwelg9rB7WCx1L3RmW/Nd0Qc/WIYGdo/xNVv70YuVfb+XPKFb+J+1OsTPhYy3917DPgu/94dgba4Tn0vL4DfGHqS456U3dp3YW0eP2mVxY288WdWmINJaRswWdswUdhXV0RKxGRKzFEbGOiIi1KiLW0ohYCyJizY+IFVMmDo+IdVpErCURsU6PiDU3ItaaiFgxdfuYiFgxbWFMfVwYEStmP66NiBVTJmLyPqZux2xjTJmYFxGrW+1EzHodCj5Tb0w7cLyPqY9jEbFitvGMLq1XTH8iZhttrFVz4eS/pgt67uK5pmEg9jnwPce899wa4Tmn59mGP+za21lknn0O0cviq7X9XFGXhkjjefa5gs65go7COjoiViMi1uIubeOCiFgLI2KtiYgVk/fHRMTq9WM+rLURsWLKxOERseZFxIppv5ZExIrJ+5iyGpP33Wq/YspqTPmaHxErZj/GlK+YOhRTvuZGxFrapW3sVl8uZhtj+hPd2o/d6sudERGrW/2cmD5mz594YehQTDsRs14x5ev0iFhnRcSKyfuYPoCNtRYHOh3K1dJ/S8bAxmuEZ/XEb4g/7Nr7MlYMDNtnfLH2nVuMXjOkH7A+xusXiTTD2pT+PQBYmP9caAPmx/fkqdO3Nw/u/7chME+gOrzItbcHv/VBHd+Q4o6K9rBOqn45R+A2RHnmIZZjeS3Yn/2h8mr4w66UftR88qP4ouTHyqp+Zf6H9qsPi+PGlp48Q6JcDn7UQ/lv+MOuVH/XfHxRdtTavknUpeHadfCqiel8nNYvvvXNMBb3V/I0nfex7mjjhdUNcTfD9xz9MhAqB4Y/7Nr7pYgcbCZ6WTy1tp8n6tKgtOThvjtP0DlP0DlYsFCGjDfIS5YLLJejn8ZC5cLwh10pOaz5+ILtY39iSzF6c2tUHukhptXHeH2+SDOsC9K/0Z/A/FugDZgf35OnTt9+nvwJxGR/4nzRHvyG/sTHyZ9QOlZUXrE88xDLsbwW7M9gO2b4w66UftR88qP4ouTHyqp+Zf6H9uvBiGXyt8VDx6enig6W3+Khc25JOucG0tlUks4mQWdElGN9Qn6Hy3ftr0P1yfCHXSn9rfnkSfHF2ndBIXq1r7HNRnqIafUxXl8o0gzrovRvtP+Y/wJoA+bH9+Sp07cvk/1HTLb/F4r24De0/39E9h/bw/OZvHqO5ZmHWI7ltVh/ukaovBr+sCujH9PyquRH8cXad2ExeqMh/Yv1MV5fJNIM6+L0b5RXzH8htAHz43vy1OnbN0leUbbZD75ItAe/obx+PcUdymhP0wU9V6q+yFH+fw25dl7lKL/Ryl9crPyklb+kWPljrfylxcr/qpW/rFj5C6z85cXKf8bKX1Gs/L1W/spi5V9i5a8qVv4nrPzVxcofY+VfXKz8SVb+mmLlv2nlry1W/mIrv7VY+V+z8tcVK3+Hlb++WPmHrPwNxcpvsfIvKVb+n6z8S4uVf8TK31is/Pet/MuhfJ5YvpV/RbHy/Vbfn8CPok6Gb2PhyyB/LeNfw+I0ozVMWDnrXvPVHevH/tRPAD1sYxbWT+TEGhJpRfrk5S67XYg/4qmLquex8F62zYdHxLogItbciFgXRsS6KCLWxRGxLomIdWlErNGIWJdFxLo8ItYVXYp1ZUSsqyJiXR0R68URsa6JiHVtRKwjI2JtjYh1XUSs6yNi3RARK+bY8ZKIWC+NiHVjRKwTuhArea6b2P9vyXjHJSXjFWeWjFdcUTJecW3JeMPmkvGGi0rGC84vGS+43HztF8PHWvqvigXk8PuvrBGec3r+ZPjDVJec9KbmT9cQPW4fr7tdK+rSEGmsI9cKOtcKOgprYUSsZRGxlkbEWhURa0FErMMjYi2OiDU/IlYjItaSLsWKKauLImLF5P3FEbFiympMfVzTpW2MqY9nRcSKqUPdyvujI2LFtBMxx9qYdiIm72Pyq1vlK6ZvErMfY/L+ULATx0TEuiQi1mURsS7tUqzLI2JdERErJu9P69J6XRkRazQiVkyZuCAi1lURsWL2Y8x6xZTVbrWFp0bEiimrMfsxZr26lV8xZfXqiFgxZTWm/VobESum/zUWEStmTCGmTx5zrhAz9mj+vcWxr4RytfTfkjH80RrhWT3xG+IPU11y0vPG8LF9vHf62mL05oT0A9bHeL1VpBmWrd3i3mnMfy20AfPje/LU6dt/Hrb/3wZhJg/vnd4q2oPfcO/0vx7W2jbkPctRQT4vC5Ujwx92peS25utXbB+vBal+aog09plD+a2w5kbEmhcR64iIWI2IWEu6FGtBRKyFEbEWRcRaHBHruohYMXUoZj8ui4i1NCLWmohYMXU7pnzF1KGYdvVQ4P38iFgxbbTZQjvXiP7McqKT1zfH8pav5HmYa0qeh7m+5HmWq0qeR7nQ/KqXwsda+q86a5LDx7u3RnjOaZ/S8IepLjnpTfmUNxI9bh/7lC8XdWmINN5fpM5LvFzQUVgLI2Iti4i1NCLWqohYCyJiHR4Ra3FErOsiYs2NiBWT990qq2siYjUiYsWUr5g2Z15ErEOB9/O7tI1LuhQrpm4viogVk/cXR8SKKavd6gPExOqN2/mwlkXE6o3b+bB64/aB431v3D5wut2t43ZMfnWrrJ4VESsmv2LanJi8PzoiVkwdWhYRq1ttdLf6EzHbGNP3jdmPMXl/KNiJYyJijUbEujYiVsw4+daIWJdHxDo1ItZlEbFOi4h1QUSs6yNiHQq8vyQi1qURsa6IiBWTXzdExIopqzF1qFvlvlvbeCjYwpj16o0dL4yx4yURsWL6cjH5dXVErKsiYsUca2PKREx+devYsTYiVsw531hErJhrOjHjADHjEzH35/AZHNwbVkv/LXkn8pwa4Vk98RviD1NdctKr+fiC7TO+lLwfeKRG5ZGeugPYeP0KkWZYN6V/4xkczP8T0AbMj+/JU6dvW4f3/9sgzOThMzivEO3Bb31QxyuHW9uGvGc5KsjnVaFyxPdZF5Rb733WSr9Uv1rZhkjj+FQovxXW3IhY8yJiHRERqxERa0mXYi2IiLUwItaiiFiLI2JdFxFraUSsmPq4JiJWTPmKya9VEbFiyldMHYppV2PKREy72q26HVMfY+rQsohYMfXxUJCv+RGxYvoAfMYL/WU+45X3Dm0sn/V7JZaePCV/z+ahGuFZPfEb4g+79jYX8dkV/xVfrO03ibo0RBrH+24SdG4SdBTWwohYyyJiLY2ItSoi1oKIWIdHxFocEeu6iFhzI2LF5H23yuqaiFiNiFgx5SumzZkXEetQ4P38Lm3jki7FiqnbiyJixeT9xRGxYspqt/oAMbG6ddyOyfuYPkBMGx3Tn+hWWe2N2wfOrvZ88nxYPZ/8wMlXzy88cPLVrX5hTH51q6yeFRErJr9i2pyYvD86IlZMHYo5dnSrje7WMS1mG2P6vjH7MSbvDwU7cUxErNGIWJdHxLo2ItapEbFirg/F5NfVEbFOi4h1QUSs6yNixZSJyyJixeR9TN2OqY8xdWhrRKyY+ngoyNclEbEujYh1RUSsmPy6ISJWTFsY00Z3q9x3axsPhbE2Zr16vskLY+x4SUSsmP5ETH7F9MmviogVc6yNKRMx+dWtY8faiFgxYwpjEbFirlvFjDPFjH/F3F/IZzRxb2st/XdIlEvoNF3QM1IjPKsnfkP8YapLTno1H1/UPmlr3yuL0Ztdo/JIDzGtPsbrbSLNsG5O/8Yzmpj/ldAGzI/vyVOnb386a/+/DcJMHj6juU20B7/1QR2/OKu1bch7lqNXwvccfP6tUDl6Zfo+7ErJbc3Xr0q/rH3bitH7XAjfsT5G7+Zi9Pqtr7YLbKvLjvRvlEPMb/Xqo/z4njx1+vYtkpdboJzhNygteVhGMa1ffOs7QFjbBRbyDfX7r1JeKP1I/mu6oOdEtiuGgdgFZeWGUN0z/GFXShdqbAeNXpYNUnJkZRsijeNtRfs+eV/TpViNiFjzI2JdFxErJr8WRMRaGBFrUUSsxV3axnldWq8jImLF1MeY/Xh4RKyYOrQkIlbMfowpq8siYsWUr7kRsY6MiBVT7rvV5sRs4zERsY6NiLU2IlZMfsX0TWLKV7f6hTHlvlt9uaURsVZFxDoUfLlulfuYvklvTMuH1a2+XLfawpi+XExbGLMfY/KrW/2viyJidav/NRYRK6Zux9ShmPyKOQ7F1KFu5X1M+xUzLtetsaGY8hXT9+1WH7Nbx45XRsSysWOEsC09eUquNx1ZIzyrJ35D/GHX3s4c9LzrTa+Eb0XXm3g/fLfYw5h61K2x8pg2LCZWb70pH1bM2FxMHYrZjzHXA2L6Ot0ah4kpXzHr1a3rOt0ao4jZjzH3KsS093z3KvpGy4mO8kNu9tDB8pZvRJSrpf8Oifrl8JfeWSM8qyd+Q/xh197mIv6Z4r/ii9rbZmUbIo338fv2byEdhbUwItayiFhLI2Ktioi1ICLW4RGxFkfEui4i1tyIWDF5362yuiYiViMiVkz5ilmvmP0Ys14x7WpMmYjZj/MjYsXk/ZIuxYppJxZFxIrJ+4sjYsWU1W71J2Ji9XyAAzd29HyAA1evng9w4Pqx5wMcODvRrT5ATH51q6yeFRErJr+61U4cHRErpg5169jRrb5vt8rXqohYMfsxJu8PBTtxTESs0YhY10bEihm/3xoR6/KIWKdGxLosItZpXVqvmP0Ys14XRMSKKRMx+/GSiFiXRsS6IiJWTH7dEBHr+ohY3SqrPX08cG3sVvnqjUM9uWesl0TEiuljxuzHqyNiXRURK+a4HVMmYvKrW/VxbUSsmHPRsYhYMdetYsYnVkXEirmfyWIdtv8Q5/LnEp1RQWfUQwfLW74hUa7pgp6zbP/eqfCxRrhoj/vDses1wnNpefyG+MNUl5z0pvYuXkj0uH3GU2v7xaIuDZHGMZmLBZ2LBZ2GSON77GJgqf5K/mu6oOe6Idfe5hzlX2v8vAQ+sizhWJWjb5eEypLhD1NdisrSpUSP28eydIWoS0OkcR9dIehcIegorIURsS7u0nrNi4i1OiJWzDYujog1PyLWkohYiyJixeTXmohYR0bEui4iViMiVkzeL4iIdXiXtvGYiFjHRsSy+Yv5qjgusa+q/KoLPXSw/IUeOptK0tkk6IyIcrX035K+yLoa4Vk98RviD7v2NsfyRRRf8voiHLvplnH6rIhYMcfpbrUxyyJiLY2ItSoi1qEwVnSr3xyzXkdExIrp18T0dWPKxFhErJgyMTciVkx+xbRf3TrPiNmPMevVrWNHzH6MyfuYun0ozVm6jV/dOm7H1O0qxlqbr+D8ppb+OyTKVTFXM/xhqktOejUfX7B9PFe7WtSlIdKugndMQzpXCzoKa0FErCURsY6IiDUvItayiFiNiFhzu7Reh0fEWhwR65iIWMdGxFobESsmvxZGxIqpj2siYsWU+5i2MGY/jkXEmhsRK6ZMzI+IFZP3S7u0XtdFxIopEzF9k5jjdsx+7Fb7FVO+Yupjt9romFgx5WtRRCzjva3f4XzsRqKTd06I5S2fmvcl/zVd0HMzz6sMA7HxXFyOOd4tNcJzTs8pDX/YtfOzyJzyWqKX1X/W9q2iLg2Rxntrtwo6WwUdhXVGRKzrImI1ImIdERFrTZe28fCIWIsjYsWUiaURsWLKxMURsQ4FmVgYEWteRKxu1e2YvI/Jr7EubeOqiFgx+zGm3C+KiBVT7o+OiBVTJo6JiBVTJnr+1wvDRscca0+LiHUo2MK1EbFi2pwrImKdFRErpg7F5FfMMa1b/cJuHdO6dW4Vk/cxdSgmv2La6N7Y8cIYO2LOrWLawrkRsXoxhQOnQzF5H7ONR0bE6tb5UEzeL4iI1a3xwph+Ts9O5MOK6U/07MSB43232gn+zVy8J6OW/mvrv7jumWM9drBGeFZP/Ib4w1SXnPSm1n8vI3rcPl7/vVbUpUFpyXPhxHQ+TusX3/o8WFcdQli2FwLl6ErXSkf12WUeOlje8o2IcizLBfcynBUqy7yXoaDuePcyKL7k3cvAZ5m7ZU4e01526zy6W/29mH5CTB8tZhtjxshitnF+RKyYflW3xr+7dV4Y0xb24jQvDJmIuTYfU76WdGkbe/Hcnp04FO1EL05z4Hjfi3UeuH7sxTpfGLxfEBGriljnqGgz3913mqBzmocOlj/NQ2dTSTqbAulU0Z4hUa7pvM+AvXCM1bARF/sqR4xsoEZ4zumYnOEPU11y0qv5ZFHFRK3t14u6NCgteTj2er2gc72gc7BgKdnFvueYcF6dx/JbPXTOLUnn3EA6m0rS2SToKJ1J/mu6oOeNVv76YuXXm0zfAh9Zn/GO/xz6dXmoPhv+MNWlqD6r3zDA9rE+7xB1aYg0/v2MHYLODkFHYc2LiLUmIlYjItbiiFhHR8RaGhFrSUSsmPyK2caY9doaESumrM6NiBVTt2PyfmGXtrFnv14Y9itmG2Py/oiIWDHl/qyIWDF1u1v1MaaN7taxNmY/Hh4R61AYhw6FNsasV0y72q3j9vVdWq+Y/DojItaCiFgxfZNuHdN6+njg2tit4/ahME+LKRNXRMTqVrm/LiJWt8Y6lkXEqsJG25oAjpd8Z9UZgs4ZHjpY/gwPnXNL0jk3kM61Jelc22Xt2VSSzqZDtD03lqRzYyCdnhx0T3uGRLmmC3pOtrW0C+BjjXAL7gsYrRGec2H7Ai4oRs+7LwDbx+uI20VdGiKN51tFf3M9eXgtv4fVw+phFcOaKXtewM7OsRc+F2jYiFtwv0bw/iver1HQrnv3a6h9NHn2ayQPy0jROUC3Yh3ivkjfF+e/4q7BZ3/ilvVHz7ngB0vmPfr2F/3ufW970dHreDw2bMRFHuaQ2Xqojhj+sCulkzWfjCj7Zm1/lahLg9KS58KJ6Xyc1i++9WVgsUyUxTopfe/NGQ5iPf3h7i9/5L/f94u/+9E9zz/3vrGvzHli9rpZb33nO793xHeXPfn9dz5bUhdvsPKvKlZ+vpW/tVj5eVb+1cXKj1n5ncXKn2/lX1Os/GYr/9pC5WtTfX8bfG0GlZ1u++1TaLnqvsnKv65Y+eVWflex8v9h5e8oVL72fSv/+kLl3f9n5e+Ej017OfdX+m989S/8267ZF739597wlT+/8q45y7b99vL3PHfj7z20/Fs3vdvK7i5Ge8TK7ylWfraVv6tY+SOs/N3wsRlU1PVZ2TcA7b7w8kNW/ieLlT/Vyt9TrPxpVv6NUD4H75pW/k3Fyk+1/6cKla99zcq/GSuV/rvqz379sH/5+AP1//L/fn/XG/5p7SOfv+i+z37i7Ie/sP7ciWv/5n3fvcLKvqUQbTfHyr9V0O5Q7ylbNzH1JV8My8rfm5u267eyb8tftm5l367KfvNnn3pr4+cenmwe94V/GrzogW/f9I+XDJz+lS/81NLfeduPvvX9R63sO9LsOds8YOXfqWh/6cYf/eUvNR5540/e92tvOv2Y+ds++ciXf/B//uC/f7rxj//rU6//8pSevKsY7QVW/t3Fyg9a+fcUK3+Ylf/pYuWHrfzPFCs/y8q/Fz42g4q6hpX9WVF2/kb35eVfO+We4xaduuuqu9/xta2fesuCZ479RmPJd+86++5//YtdVvY+UbbDc8rAj//3VLo4af7rUJqYvI/De/LfcPp3Us781ybksbJ1yn/P2dPlPpTSG6EyhuHctI87DN9z9MXSGuE5p+eMhj/s2tteZM44TPS4fTxnnC3q0hBpx8A7piGd2YKOwlobEWtxRKzrImI1ImItjIh1eESsBV3axkURsbpVvpZGxJobEWtNRKyY8hWTX6siYsWUr5g6NC8iVkyZiGlXba/piChXS/81P2AEvucYl/tqhGf1xG+IPyzqWcQPGCF6WXxJvllf37Vn520799xz+a5t27dsu2P3Xbft6ENo1+oNMVcQFb/VXGvrMa2fvs2ifBdPtP592UR7OSew+4HuUZCmOGGY5n1im47KKIe8cOJbn8g/QlgjopzVvd9TPnlKSmXNyo8XK9/v4y3WyfBNw5BntYx/DYvTjNaw0zxruqCn5qs71o8tx1FAD9uYhXVUTqwhkVakT0Y87UL8EU9dVD1RFlmHfDMNyz/uqRfmHxW0razxaAWk5bXGWTxCXTD8pI024qTW8fwdN9916+W7bmVsFFlkzxLKZ+amz/nNDWI5+nsJfesHPHx8E9wQtbN6Jk+DsJL3JtHpDaC9AfTgGECVYWSJGRXfeYtsXvfzRkFP0XlFSTqvEHSGRLmmvdz77Ef/cvN9X9jwNz+a9TNXbHvHT5703j++4TtvXPL86r99zaeWfXJeEjYbGWutL/J/iOpr/Y5hOtVfdcr/e2dNl5ub0kvqa9OkVMPOu+u2116zY8+dO3fcvePHtni3o6eTWlwx0fr3lRPt5dTj82OYvVUZOsOP5Qcp0VLjcj5DxwKBXEFU/FZzxQ2d9aA9RQydz0AgplLYkYxyyAsnvvW5bEOkjBjHh32GzLne0FxcYg/loTlEYkOH5iyJzRqaudyAy5bwOuVdnw4ZJSW75cZprmNvDNj/9MaAg2UM6BflWGLKRmisHcnTcNntH3Lt/Gjay9f3bHloz+LbT/3O0Bfv27j3iCO/9sPnf+kb/3zPjtO//Y1vfmb8hyW16/qSVuG6xBJtJicYoxQ8uRtP/85aq+ZIzAogxhbluGJ1nhNqUQx/mOpS1KIcR/S4fSYr1r51xeiN1Kg80kNMq4/xer1IM6zj07+x3zD/OmgD5sf35KnTtxenstMgzOS5aqK1DutFe/BbH9TxsrFWeiZ3f33MdJ5rYTK1Ok1PLfj1227buX3bnh0XvO71d+24a8f2K3ft2bF78+u2X3D3jtftyT21umSi9e9LJ9rLqccUCpVoDqXNgjQeMGZRHfkbG6eaaANjZSmuYdUp/8tSJh/24/9O2dqKqQwyKiUPLFgnX6SA+ZA3UlATdCqcNIyFGqQDNWmw9s0pRm9ujcojPcRkd7Ih0gzLFuhRHjH/HGgD5sf35KnTt9eRQWpAXjZIDdEe/IYG6dVjrW1D3tcy/jVc/sbyirxheVWx6aQ+u8da2zIb0tg5Sp7LJ/b/W6f8/w8Y1LvJEUDa3H8su2hDksd0n2V10E3zBPOw/bH8bwL7czrZnz5qM7ZT2ZQRoMF0k/eTMuowQVOwgnokp2CGNeLaeRjHPtV+UNQ+9RWi57dP2L449qn2/YPJPt2fYZ+S9xOoDnns03tmyD7xZsu+iHRQ3prpu9ki7EeehPv6XdHB8qx/NVGHhL9PjGmaKB9YlsM5lv99YG8/EGBvlX/Ey8rIN+YN9o9PBxVv+jKwsnxIbrPlfzanD4njFvuQfYJeLYM+5z8B2pyF5cQ3y4/+6yzKO0J5Z3vyZo1Lyftt6XuVepw8dmC2k9z/fE6535W+s9zfC3L/iyT3yg7z38omWhssfS60OxR3gMomz1WE2yBclJWXpHnZZzhi3jT+r5Ntnkt1Uf8mT0ifIhb3KfKu6abr85vUp2OQpsLd3KeWfxDa+NvUp+jrWB1jtt++z4PvTHeM8s6nvLghtEF1nEdl1b+d6tgQdOYT7gJP/RuEM1eUG3G6rerf0PqOifqOOF1/9W8oHcR66UQrnSzZ/ROS3QWQpmTXDmfWKf9Xx6bLfdmzC4BlF9t6EqUpXzPBP3tea51xU7Px6caJ9rKWfxHlR4zk4bmW7SzImmtZ2Trl/2sx17K2LRD0krZ9fUy3DfsDN70vItpT7QBb8rfUH8gv649R184b1oHFUBfMmzxmK5kH3wG5+D9j2bRYL1QbE4zvjel8WAfMxxhmF5AHhqHsgpUbFfVi3V1INBZ4aMwX5RQNtsfIs8VA32RjSYf0xaJtTnzrE/kXZrTXCdqLOuAuEDjKvi+itDGRxrYL24t+iumZsolo9/7Eoy9ZOqHkaqGn7nyoY6Go+wJP3RX/0H74/Ab7O2Ssr4m/rX6vh29sY02+B50eR6xsnfKPpJVS8an50M5+Ua9dGZgNwDyLMJXMnALfeM7m6yesz6jL1nNVd7Ql/M3nyzhRh+QxW6hkNsuPY36oOswTOMpuIibTzKub6E//Zpf5/s15up15ff/bYD63MsU8WH1/jrl3g+8/m3B6vv+P7RzJblHffzPI7ukku6G+/4mU1sn3tzTjb58oN4fqa/ReAb7xiwivBrRQbpKH17vmAb4TbeL1D8u/Bcajc7f66Subz+15WYo35Np1JMc6w2afXBr2goLYIXKtdFH528MirR5Ql9/5pZe89K4fPvV6lnerC38LGfvPFvmNVzzPbLqg55ypTWIT0+WN9tSaG6QtoLQBSLM6JLK2luq3sGD9QviH+A2Rdje85+kLhTUnItbsglhjrlVGUQ+VHeZYh4qXJjbgng72SY1xbB/uJvuAcdwc/X6ybzw37PkFsUPtQ9YYivUaFmkh9mHOD65eedG77ji/5trtYL/4xvZBycqZIn9J/dug7APbgDqkzac0tA9WB2UfCtr6DSH8Q3wVE2H7ENoXCmtORKzZBbHMPvhi5Ggf2B+aK9qD9oHXS36KdL7g3ii5x4L3fNnfg+m/V09Mp/Ea0ogHh22YE2V4X4vlfwf4dPeSzUQ9TZ6rRP2UT4rrs++al51vrsiX1MvG3nQT5UU79lz76m137th+7Y5b7tyxh3dJMjd4hc16HcvxY7Wq07fD6G9eQa3R3ycJnE40mTOYNkR0c0rhOHLbHjU6GP6wa++lIjtu1I5RrANb9IIja7NG5ZEeYlp9lFXgHaoqEoH5eRU2a7bPkYrHUglXM+kTqA5zRXvwG2rYAzRzrHon74jTupA8Q65Uf/aHyqvhD7tS+lHzyY/ii5If3+oo8z+0X31YPnsRwj9FZ4b7Ofja94Ohn5OHIxxF+7kqLN5paPjJM+Ta25qDt8E/c2H4w66U7NR8fFG7Ejk6iWU52pg8zH8VgR8TdA4WrOT9Rem7jRm+8TCv/GH5uR46jZJ0GoKOL7pvcs4rck0X9AT7UoY/7ErpVc3Xz4ov1r6CUcxmjcojPbV6pSIJvPqpIuMq8uBb+U8ejpz/T/KlEJN9qdCZZlLHz9NsRe0ETvJ9iVYA1G5EXCW6ZqK1HZb/dWumy/1pgB8XMlcoOGMNPj3EB6Rrxeh5D0hjHVi+i50+mD49pE4D+E6+zBFphmU2CPtdrcConaA4VtXp2/8m+UZMlu/QXedJHf+KZOwgPu0W7HccqNNuvhU51a/M/7ynCQ4mrKrnML3TlofWacuBdECPfZrpPz2r8lmnJxB3ROA2RHnmYZbfMWu+phnqd1j+VeB3zJnf2kZf/EiNCTh/5lMySid9/Jol6u67DkT1Sy2Ajq9faoF0quj/mWqPT7exD7ZOZNeL7Xqn2Mq1hIXlraySQa5z3hgmlp/loTOnJJ05gXRmqj1DJekMCToVxgSDx9MDFRMsGSeby2Mg0lNxERW34piJzZ+zdvbyKiLO43GezzutzqDxFDF5PA2NQyV1PGl+a9tUPDJEDhBXjfksr1nj6bk0nqrbSXA8vXxi/798O8k8GE83e8ZT7tsK4rHBenSg4rEl43BzQ+QO68O7b5i3yX9qh7yKefVRfnxPHt5BfzXpEWKyHvnibkbb6ngp6VEVu7lD5TWGvjaJTpa+voT0Va3V+vTV8v/b6ulyL/PoK68TqDg5twfp5h1jfLo0x5O/0ykBjklUsBMt2O7wbtSC8eopu6N2jym9mQ15050lm3fs3nji6efvuOXOe+7Yk7UrjXVrPuFafkd/c7mkbrzjuSFoJA/Lz1zKx/1u39WO6k516pS3U7rSG/6Jm7y+J5bPe4OY9Q+P0benCer2BzWnQhniea3y51UsmX1TbsOsjHJvcrp+1mask2qz5d/jafOcDm3m+bea+/niQdxm+z7k2mUAMULmGAVv6PnrUBtl+LHmGJ3m2XH2Q9W+5htvVJzNt0vSN8bG2A/1LvKNYu2HmiDfCHlfy/jXcPlbyBy/k8/y3hxzjOTdfgqY7dc3wGe5n3wWnKuH6FHR9vviC0OiXfizxlmxp3oGJp8CsvzvT9teMt4gd+iyv9sn6r/vFibqU9V2X59a/j+HPv2Ap0+zxkAH9IbgG/smyv7M9uRX9kPJRXX7LcJtdez9FmoepmxNXn/ScL8GDcL6d/InuZzyJ2dl0MjSPfbx2B/t5E+qOmXlzetPYh9zWZaJLPn07aM0+Ryi+jdd0NNknvc7HYdgO4m3eSk/iPPXqH6Mz+sQVr7u2nlTg/axLfp58BU3060r3F/OleZfI1S/DT/WfpMhopclO9a+gr7fKMsH0lP9zWvVShbUep+64U2dGsE5Ds8TPku+mO/0bui+kKSOv0q+GPK+lvGv4fI33/qE5at6X0EzfffFikL6XdHx7cHsZGPemL538kU/T36Luq23T9SDTw39NPgtX/DEz6yPlE9To7Sap/3cZ53svW8NuwZt6hf1alJ+dbIKMdlPtfzfIj+14D6Tq33zmJI+8NUhOoH4ao8Hz5UxLeT06If/+NTf2bTr5Q/VqLzVhb+FxEpfLPKXXHe4Qp0exTWG5KlDWoPSBiDN6qBOjxb0X68I4R/iq7g13n6Tpy8U1mUFsezEp4opHShbkRVrRF8L83/PE3eLsYdGjf3YRrY5zmXL0X/SY3jG/8MErSl5p7z/DO0+f2trXbP2tNQz2jNC9VQYijdMQ/lCb3atdZsTUDcV/0SMWkY9Ewy154XlLu++Sl/stIKxYhTbh/XEb4g/7NrbHGt/huJLSfs5xzeedNv+jNE08BDznFBSx6EFrW2rar0369cG0L4m9Zm/oLUtvnMWyftb0ne2S28Af3VRiqlu8ub+U+s3OIfhMc7oZd14OpRRvyPSOqnb+1Rs8S1Qryw7kjeu2kzrUGVcldtUd+1jZ/JsmXCyTVnjcMiZNdwXwGOs8o8YK2vtjedI1rarF0+XO5rkuN6h/edPtGJa/jMWTWOuzYl5QQbmBQumMdeTbmAfXuJa6bH+8zfWfy6fPCZrqIN5xoghakvO8v01KDP1UdTJ8MvGF5BWrHiWqruvH7BOPJdSWP05sYZEWpE+6RN1UXwc8dRF1ZN9SEXnEvjGPBrw1Avzmw6hbFpZ49Egtafpgp4+X38NAKbhJ76x2bh0reL8HTffdevlu25lbGQVsmcx5TMT2OfaWVzPwHL092L61g94+CRN+lx6S7Ji6ysJt07t4W8sHq8UdVd0lpeks1zQ8WG9UmBZfhXGXi7yWztQ1KxsydBUn08l0OUw/BJiaOxZBnlqUNU+ly39ncSQMbPEUGkYn+ZiMWD2jAqMEAuD31is+gQtPiH1WvLuBqjeTRf0vNus7SB8ND6VXBF6N1p3e9QIyismSM/qNSzSQqKR32us/+OXrr7gf/jUzLfSrqI7N4v8JVXvHSoaiacek6cOaUOUNgBp9k1FIwueVnxHCP8QvyHyczQytC8U1mUFsSwaiebTdGemdNmHpSKHNarzoMivbIXlvxNmoxdRFE/xwYlvfa7dTrx4Yv+/FdqQ4FPhvKpc0BPzripj+3jHjFrljbn6erBgocyMuHa5qmX8a3T4G/M5xooz91kMrJGIWBVEewvf0DVT0V61c9XKqhX1UXjHNKRzIG/osjS0+XOonPJzlG5eRpjoY1j0T00LeOwaFO0a9LSrT9SPIybJv830PWnr0ws0TYz0YVmOtln+Ly2cLje5ILuNIbtQMX9WtPQ58qdRvnLIvYyWGlYn3j2fg3fJY6e5mXe/DLz7uId37Peo30Idde384N9YVysBPv33rTirU+QVnq7sqtvufKtgBXc51I2e2gWr+mGu0zxF+vx7D8rWsT1DW8d2HX2HUUpD/T4R3rPsmdqxMOqp30zbTeUjh8igooN1XkF0smzM75ONUatRWHZ3+s6rIc+AjflDzwoc1pH/DpnzGL2sFbis1Zr/J+cK3G5PnZGGc+3yzGOK5f9jGlMKzr29d4+HnK4qSLcv1DbyDXJlT1d12lGDO/bNFqXhx8t3bdu+Zdsdu++6bQeuA3CPMVcQFb+hNnBaP30bpnyXTrT+bVLb77If1Aq0fs75tcV3p46KFAwJuvatT+T37VPimX2/pzxiZJ2H6c8ol/z9TlEm5rmomZ7NFfQy54dqpuHHms2NEj1uH7e9Ieqi9o8MwzumIZ2QfYrJez0SVvLwzLCH1cPqYfWwZgLL0tS+UJ4dJQ+f70c7yDOavAvdvr0z/BsryVPuXH/43lQ+q1Bw35D3XL/iS8nxe45vPEVM3lfpi7R0uotzFNqA+fE9eXileTyd6cWU+6SORyxsbVtV5/p9G0Cq1AusezN9T9p97EJNM3QGbvkfhRn4uoWtdVYz8CweoIztw5hob9PU/k5Iy6PPySz8UjqDivUamJjGzdILnJXbftmGa9cZnyyERrFPoz5CuVV9xPuULf+boY/OTN/VXsyQPWyKHsvQYEb+Pqqf5X9RWidcGQ45k6NkFmXu1gx6W4DeWSAP+9o50UojeUrK3Xwld6jPLHcq0qf03zdeqEiikkXeDVATWGqPc43KDzrdB4ZXp/xXij4PlXPuV8v/4sB+jWRPZL8ir7hf1U4LzB8S8eX+Sh4VieXdaf0CC/ua+7WTLhse69bLPf1q5bFfsZ7cr5b/psB+Rb9oH85Ea32bLuiR/Yq84n5V4zXmD9m9wz5j8qgVjcMozXfOUNlvlIOQPsf+ybLfrxV9znMDZRd844tzrRFWu4ssjbBeu2fXnTvSEKujxxcSrbn2441GZp4o76hsjb7xlXTKfPo2jBntQadDkmw+Lf+dguU+85s8IdduYHdXEaS3bzN9TIGHXaVmPpf8AIhq8lj0viaqxeUdYdXEt+RR294Rl71An3VTrOLTapwfTxRh/rd5Rg6fh+NEHXwRYqyPav8opflO11peHNFQjHhEs/w/HTiiGe0qRjTkEY9oagaN+ZnfvluakSe8Vwl5r0Y03l/VSQ3NvKqZFXqVPLNS8uLzzHz8UfKFMtGgtKxIyz7siek0y1fFLBjbw7IQegO35ff9shzypkH5lZyofTghdil5fLKAM0eOhHS6yYmHcHXbDQ7hPCu3/M8LG2CYasXVJ4/KPqId531U6ALNoTQsh5GKfdgT02l48+q+9kFaniikkkdsD8tj6OpfXl3lyCLySc2wOCqK8oV7O35/hve+8fitIrJYV8PliOtvQNToi6QjSsd9faD2ffGvOmJ70F7MC8Dy+QLqlxrneWhjvbAs0+Z64i9Y7qM1MZ0WaRwfULqC9pl1JfRXPn28Uv3UoPzIGzVr9e3D45uDQvfhmcwr+VSRkxp8840NuN/1edJd1M8QG+y7aQXL435hrMOXYYzgG3867Wl+SwbmVzzjjmqDb9zJ62ej7fP52WwX0faxXVT2WtkRtosm1+ibYX7eT2f5/zbln02ZC/7SgNxPx3YJb0xVvhfvvbb8/w62+5sLNeZATsy/n9k5S71qW9dpTDKeNFx732TtJ0Us5Cn7jGqO3BD4bTdheSJtaG/ZpqK9ZZs6W9BV9tb0IaGzNL0xhP215L0J+f6/jHkWyh7aHJY9y78Mbihx6XtMu8E3wcU844PlZ+AXxYPPEszEL4qrmEFJuzl1lkD5Kqof8CyBOj+AWLh6vg93YjpPlXbNF4vpxFezLWo+zfqMNoLtQIhPpuhl+WRmI3w2siZwO/lkT5NPhvrF+o86zvqP8s5+A/KQ/QZ1+xraIByzMf9KsGGnEm+ULPtiLOrXidAX5zk9yvqCACxfrG+hyL/AQxvrhWWZdpZOKl003lQxn0K/gHXRN5dMnhBeqX5qUH7kTV7d5XkYju+s1yjb+IssLJ+dYi6su3NEXdEfMNnAcenlrpWmWtrBbzzOYnnLp+gsL0lnuaDjw3q5wPLZRN91O2pOXfJug6nrdlQ8VV3vU+K6Hft7JeSpQVX7qCrYZMZy9Ddj9gMePkok+jLqaXQ7iUQf0VVYA/Bum2STdD46ZnlekapgycvoHvFdf1DywrBHcIi2R7maWccPsV7qyoyQq3W+9A/3vudlt/ztn/tUyhceVOH+nxD5S16t86Aaxvj6nDqkcegdhyLf1ToFzcCDIfxD/IbIf+HEdL48faGwrimIZVfroKnkzbdV6z5P229JdRnDeDNdFxv6Xy3q4hsCMPzHm/ux7gdqg7Nv43/B68hGQu0a266yG/99G8OSh21RQbs9O1TX+QqdIZFmWFN2yull0EFoA9tRXO6s07c3pfLKrm7y8Mb/0Ou3kjreRSGsGNcDKVc9dEP+BLncnTbk70nfeTPeOXBB8NspVIZ6xP3Hspv8i4dZ2R7zxl/Ow36N5X8P2B8+Ej8g2rwH6sWHKjFMqtrFIXzLfx/5VgXHTBnC52sEK7iOLHi33YG6jizfkXiWROQKouI31AZO66dvvKnu4onWv23y2u+yH9QK1gzFCcP0/eyiz+I68a1P5B8irCwL3e/83hxiqEmmYahyyd93ijIxLxuZqeP1JY8MBv9cOR8ZLDir8B4ZxPZx29WmM7VgwbNZ31FBpKOwGhGxZkfCSh72InpYPawe1oHHUpvuRqgcjge2eDxTM+sRUY7HkYKXHs0JHUf40qP+YvS8lx4pvpSMho3UqDzSQ0y+YGqOSGOZy1qYG4E28HiC8sebD75MM1Aca1nuQzeBJXX8I5qB8jVD6l/D5W8sryx3zs28XmDdm+l70u6vLdI0Q2e6lv94mOl+fVFrnVXEKIsHfME5RmgtXxWbnH1HgJVe4CzXjuP7jtkpWQiNRnyH+qjTkVy+HsDyL4Y++j5FI7A8H6zxHfRAeixDoUfPLf8/QTTCd/R8MIOeOnqePJdPaHr/CvRm4Oj5mJI71GeWOxWZVfrvGy9U5FfJIh9l9R1frgk6vmPp6igr19259ujZQCqvaoNdyE96Yv0U3yIfZR3KqMZcUd5R2Rp9m5uBZTjJ3xieCDnKqk6rs4kYESz3ddm+MuIbqgyLUBXBNfvWO8o6BeWAVFbUrSaqxeUdYdXEt+TpdJSVNdbHYsUqs1ahlyBY/mVCpEMsphN1UJ4Ae75Z7edtrWqrL9NRlzMkD49oln8ltNU3ohntKkY05BGPaKGRMcvf6UgDqxrOIrLWs5FmqBqGHmVlTy320UGWLzSFvqODPq/6UDg6yHKijlyGmn6fLKAn+rWMNcQs3Kw9FlnH2bOOFG0WNsAw1QqDTx6V/PLPbSWPOlLE9k6tC1Z4IdCIkkdsP8ujr63JU1RXOVKBfFJr1OxGxjpaPUEzPqRzDdHM+zNc14j6KzrLS9JZLuj4sK4RWJZfbeX3bfdEW2NlSx6f6PPJnjoeUWK7p7HnCMhTg6qqrSCjGViO/mbMfuff7qlMSFGRUDfwKzohWw19dPoEHd7O9YbU9JbcUvD2kEXR0YLYaB7sUTMqw1eLlFavYZEWsk30K7921mfn3/snozUqb3XhbyGq+1KRv6R6TqjhiU+W1yFtlNJwiLE6qG2iBU+XTYTwD/HVAg9vEy2zWHRZQSzbJuq7JWOmdNmG6Z8CN4q3iVZdF+WusP4XXOwJXsxiHS9oy2q+IU7xpeSmj6nFLN/iD9bHZ98MS53SVps2+ig/vicPjxf3pTIWcxE3qeO7F7e2TY0jIXKAuGpxg+UVMZtQn4cXt7YFb2QJWcCw/DtWT5d7LMX0hVqYXg3o+X5hyMqH/sKQ5X8SbAZvp5wl2owLJ+zOjgANppu8n5RRhw+RD1JQj+R2Sg4xYH3YDqpNeeoXe5QdDPkdl5J28LeK2sGyv2Sk7KDiS8n++1xeO1jSr+y3vsp7Whfzsx1Fvw1PdvJp3s+QvVM3AfFtd8lTxa98VoGl/F3kG262+MQM2f4qfmtJLe4103ezOSi72+C9k6wrOlh+jodOvSQddbe+0kVc0TN9LHgTRH/JuU+/T/bUjWDsR1m6+tewOI1vwShoi3LfgqFua+AVWJ8OhmKVnO/1+2yLmu+NeOqi6smh8DJtHo6IxZuVlf5tE1g87mB+JQfqxgkra32HNwYUCfWpvlM3LZQI9Rl7rqd8tidTTVPGMrAc/X09fesU6qv6kraZMtdqRcvaXNJ1Cv4hdsM/UD/dpy5iOhjdKt9QVXLYLfzj0WWHOt+QkDzclyFDQvLkcUWRzsGClby/KH1nObf05Ck5dA+GysVMXASm9IUv3MGyfOle8nDYWA2x6jIehXXVIYSlXIyybheWt3yKzmhJOqOBdKpoz4gox7pZcKoTbLMNf9iVsgU1nzwpvljbfRf84mVYLLfqoqz5gs7BgpW8n5a+m/xh37P85dVbLD/PQ2e0JJ3RQDpzS9KZG0hnpvg2VpLOWJe1Z6bk4GBuz4gox/a74NQ6eEnT8IddqfGi5rNfii/WvgXF6E0taarLIRETL2lM/l4o0gwr3QzWEopXFx72UX58T546fbso3QHOlygmD9t/dSEjfsMlzc20s1xd3Fh0XMHylk/RGS1JZzSQzgutPReUpHNBIJ2Z4tvWknS2dll7ZkoOtpeksz2QTs8edE97Om0N2b1E08zaGmJLZHXK/+ml0+XuprEC47kXulZ6eW+/w/K+W/Z49zvu8J5FaYMCs0ZpWD/frY1YfjCjHNYneUrej1AruVVhalmr0+kqjsUXXXJGWjO9rUMtpfMJMt89DKFYJbfHTPXJbE+7EH/EUxdVz5Af7bgQvoWsHSl+q9NQ+OMBbLeKLOkpHqlLt0ss6Rl7jqN8tiutz7WL0kgGlqO/j6NvnZb0qjZXis6lJelcGkhnptozqySdWYKOD+tSgdVTpZbnQKtSX0Y9jW4nkcDyMy3iIfdrFhxhR0NHdMOPdb9mp1slObpT5napLNFHTN5wpzbjsUqjF61G5j7XrmJoDvhQxK9RdAe9Eo7uhHoxSR1/cUlrPmwPHhLoNJv4DZpNdNpozrMJy/9bS6bL/Sa82/0GSf3UOX7WYV+fIg+UDvPP4Kibg4rSqQs6jJXFs9vTd75n4fMpb9S5Y5Q3xkwe25nE8ovt8d3L4NvJonipDjn6aKufXLL8c3PWtdOGSt7ZpFZdQ+t6zQzXdbaoa4W7KoKvhzlQuyry3b2ctW5eI1T8xpqEaf30jW+BuWSi9W+T7H6X/RjHjK5aG5orMH1bK32S5cS3TvsXmQ7HJfo95RFD/ZCYYahyyd9vF2V8GhAiwcmTtU8nBtZ8gVVyzWphqGYa/jDVpahm+n6MLXm47b4f+cI03s4cunalsBoRsUYiYSVP0fW5HlYPq4fVw+oWLLXvaT6Vw/GT76pW97fWKA3r54vNY3leE/LFw/PSUTcvVX0EkKNMOHYz3/KuJWJ5XkvEo9LN9D2Zra5eqmlm/QrS7vSd1xI/BGuJxyzNbiPyeV+7JtrrXPIWq1F1ixX6OAMT07hZ+oM+nN0apnyJWZSGfW0YnfrgROoDdZMhluVbzCz/e6APTqE+UD+w6tMbRY9lZDAj/wjVz/KfmdZJ3VWM5edm0MuKzL0rg965QM93s6PRLil3C5Xcob6y3IX63aFyam1TcsoRG3XlCspB1rU0g073AV8JY/kvEX0eKufcr5b/8sB+jWRPFua9sVNF1tQ45JMD7C/+xUrs86xIJGJhX4f065DA5369wdOvKoKM9eR+tfw3BvYrXr+wDwfSyvar77ZD1a++2w7V+I39ymv9PI9HLN8+j+QJ6Ve1Osf9usPTryrK7bPDlv/VXWCHkVch/apWAkL7le0w9ivfGY9jHevyTNnoPaLP2ednu5BVP8W3yHfGj2VUY4Eo76hsjb4tyMAynOSb+p14VolBp0OgzHLL/ybBcqWmaiGvghvOghcFDtQNZ3yUXKmZ76d1Og2LFYhq8thqQU1Ui8s7wqqJb5imRBXLmKiq9V8coX+Ddn6iCPFMQVk+5flbfvNAs7wLw6tT/vs8o5DPC04ettaLRH70jPnSRGzDIkrDcnMz6ODoiJafR0fL/2jg6Gi0qxgdkUc8Oi6GtH6Rn/m9RORfDHk4qrQE0lilkceLiE4n08Hyr+RUzb6VN97naW+nWRnLF8rEQkpTszklC5avikgJtodlwadLycO88ckO8qbhOssJ6uVCouOzS8njkwWMLqymqAn2R8isTdkhFZ2zfIpOvSSduqDDWKH7VCz/rwgb5ZN/3/6ITvbY6qN4Y2WVrNYy/jU6/M23Qshux6KIdJT8G53FEemgLjWIzpKIdNB+868dLo1IZynkGSY6h0ekczjk4VWBIyLSOQLy8C9qL4M0xLB6HCnqYVOAo+B7jrEg+EYlwx+muuSkNzUFOIrocftYF5eLujRE2t3wjmlIR/12gcIajIhlfTvq2vuadzMtE3SWeejMCaQzWpLOqKAzIsqV1RHFG6NzVEQ6qDOjRGd5RDooB02iMx6RzjjkOYnozBd1SPyB75EfvALS1OqErQDXKf8gXDj9D+RPoa3AOmJ59F+OFO1gev+S0jD7txLK5LBH8vJmw+rEu38l3h0JaSG8s/zfWjVd7kfEO2wX6/YqSDuK0lZD2nJKWwNpiIFpDtqA31jmsLzlGxHleLw6Gr7n6K/gG4gMf9i1t7nIeHU00cO2Jw+fcTimGL260TtW0FP9MNdpniJ9wzIdU3Z2JaWhbVxDaWjPVlPaOKSdCO+ImdUm3gGL9WP5xvrxfBp9eo7loB++mNLQd15Cadhm9m+tzQOEkzy206ZOeZcdPl1mSfqu7A3b8SMFtqWtEGkJ/s8f2doWtCnIR0xLnn7xzTeGrszAqjsdN2B7aPnPSPlhco02Jocu3Wp8WQ0f2Q4VtAu3htqhLJuI9VI2KuTHgR495rvzPn7Lv/95Xtvts2lXi/wlbdrNKpZltKdWJCFtDaUNQJrVQf04UMEx5eYQ/iF+Q6TdC+95+qIh0viMT1EstoVlsRYXxLIfLUKfhP0OFTPE8YLHhoWeeq3sgHUNYWF5tmGrOmDxjsiVoo2+uUtJGxfsDxn+sGu320X8oU584fm76vuGSGN5XS3orBZ0FNbiiFgrI2JVEc9U/k3WWhXWeZGnzmodRsVN+fTOOKQ10/fED9l6uK4PzpfGoT7XTuz/l9fOvgzzpRsOb20/0vb5hRxzybubek4gnbGSdMYEnarj4BxzWRmRDuoRn3tcFZEO2tMm0VkdkQ7qNfvqi0QdEpm9jfRgDaSp9bJ3pO91yv+ToAe7PHqAdcTyGHMZF+1genvILy/ob8mYC/qDPt7dTbwbhzRl03iOYflfBry7h3iHtFm3kU8rKU3FVUZdO68QA9MctAG/+eJ8zDcsZ/wt6b8H+xiGP+xKyceUj3EM0cO2Jw/PT44tRm8q5rJW0FP9gDEXFWdBLI65qNiEso0811BxNmWDOOayqEObfH41r3/ieJ38jTF/jnNM3XIKevYgxTkQ//qJ1jSU8WVA9xHSVRUDrVGac/6YnYplsO8eY2xSsVn20fL6lVieY3GrBB0e09m+fvBwXR+0r+gPsI9m+U+Bft9LfabmSKo/2UfL259zAumMlaQzJuhU7dOwj1aVT8M+2pqIdHC8bBKdoyPSwXGIfbSjRB0Smf0M6cExkNYvyrKPZvn/bOV0uV/z6AHWEcujj7ZStIPpfZZ8tIJjovTRDKsT7z5HvFsJaSpWkBUH/jXg3e/ksCE4Jq+mNOTHGkpbC2mIgWkO2oDfWOawvOUbEeWMv9Zfx8H3Knw0wx927W0u4qMdR/Sw7cnDPtq6YvSmfLT1gp7qB/TRkKdI37DYR0M7y+tiaBvXUhras2MpDfWbfbRVHdrEPpqSfcaqwzflZ9Up/1/AetRXyE9TazxJvpuPaM1XwTpL8P4kwx927f1URK5VbFv5YTxeYVnV92+Dd0xDOr65H2Itj4jFc1mUMfbD8q4RzgmkM1qSzqigU3UMi/2wqvwj3p9UlX/UJDrHRKSDYyL7YSpel9iYfydf4lhIU745+xKW/0bwJf6DfAm0FTzu894Jzs9+mOXvT22j2b+C46z0w9ifyOLdwBGtbVFzOR/vLP85wLuhFFPxjnU71Nc6mtJwvEYMTHPQBvzGMoflLd+IKMfjVUE/JdgPM/xh197mIuPVOqKHbU8e9sPWF6M35YcdL+ipfkA/TPleiMV+GNpZjm2gbTyO0tCesY+G+s1+2OoObfL5YaszsEL9MMvfJLtR0G+SdoP3ovT8tdaySn7uhXdMQzqhPtZ4RKyevzZNh7/1/LU4dIr4ay8in6Oov/ZXK6bLnefxOWL5axd1gb92SSR/7beAd5cT71RsQ/GV/TX0o9hfQ17xOJg3bqbiK4dK3EyNVwdT3EzFpZRtZJ8M7RnHzXz+Woy4WWiMi2lm+XU3TLSmW/5bj5jG3EFxM6zXUUD7O7342gsmvuY7v8D+mjoncZSHzpxAOqMl6YwKOlWfy2N/rapzeeyvvdDWObN8jneRfVPrnD6fw/LfDD7HT3v8tZB1Tp+/ZvnvJ3+tynXOLN49GMlfuwB494iHd6zbODbyGb/eOuf+p7fOme2voZ3l+BraxljrnMs7tIn9Nazf8gysUD/M8n+C7EZBP0baDcPy3R8yJNpThb9m+MNUl6Lyr/pOnR1Q5z2srJrj3QvvmIZ0Qs9VjEfE6vlr03T4Wzf6a+MR6aAcNYnOTJ0dyPI5Pk8+hzo74PM5LP/fjU+X+4InRhRydmCVaAfT+xLZ3QNxduBPMubyoWcHLP8fAu++TLxD2qzbyCffnQzjlIa84v0+eeekWP5QOzvgu6/hYDg7gHaWzw6gbeSzA+OQlufswFEd2sT+mpJ9FePCcwQc4/KdkS3oMwX/Lir7TGXPyCqfSY3Xyf1p1g/p9bMX7dhz9V0337bzlst23LN78+u2X73tzj07t922efv2O3fs3o2VRkLoWGA6PpzH3heL74gx3qExLAzYWeOE1enwMB/QxvJsAFd3wOID2mpw478HXHs97YBLXwAOKlpWva6leqnFF5+RV5vP1WCSFXDJwno3YalLZfjvAddeT+aXDyfLgGK93kP1UgbTsI7rgPUmwsLyxxHWug5YP01YahLOfw+49noyv3w4yX/rO9TrZ6heWZtvkv+O74C1h7DU5h3DOqED1m7CwvJYFv8ecO31ZH75cJL/NnSo11uoXidA2gZKw3J8WXbeSRqWn6lJ2jyisyEinQ2Qpwnlkr83QhraVt9hKRv8T4bvVQRMDH+Y6pKT3tTgfzLR4/ZxwOQUUZeGSONA2CmCzimCjsIaj4i1kdqTNQlbt6yV5nJIC5mEWf7/Mj5d7oQUU/keG6iN4669jcsFvRq1a1DkR7w65T85rdNhrv3nNTaI8gobx1NfoGPItetXFTpi+MOuXX6K6MhGosftYx05WdSlIdI4aKF08WRBR2GtiYi1nNqTpSNbIunIU6AjF3ahjlwWQUfQhwrRkYILT8E6wgtPZXVE+bI+Hdko6tIQabyxXuniRkFHYa2NiBWqIzdG0pF3gI78RIU6YvwO1RHLf3MEHUG/OURHygTDEM/qg98QP5aOqMtSfTqyVtSlIdJwzoRpSMe3OI5Y6yNiherI6yPpyO2gI3u6UEfuyakjqu5VzL1U/OoCeM/ikZLdhig/TmlHCTqdZOTty3R9lIwk7/xTwJb/ZSAj7/LISDcsrG4tSWeroDPTC6vjEemgfG4lOsdGpIPjSpPorI1IB21l6KVsT5EeHAdpSg8sXlSn/D9qTpf7oEcPsmKWuLC6XLSD6T2T0ii58UgurBpWJ949F2mc+VpzutxHc9gQ9OnHKQ35cSyl4ZjMcV8VX8VvLHNY3vKNiHLGX+svjFtWsbBq+MOuvc1FfK3Qg5/Wvg3F6E0trKq5hOoHXFhFniJ9w/ItrPJmpXFIW09paM/WURrqd8hGOGxTyEY43wabIVH3Kvx4wx927TpaRLbGiR63j/34Y0VdVN+8F94xDemow9IK66iIWLbG0Ntk1v6tG3wh3mR2qPhCX83hCyUPj+eWf6I5Xe6vZsAX+psu8IX+NpIvdEtzutw3e76Q7zlofKETitGb8oXUGnYeX0itab8QfKF+UT/Mh7qn4klOfKt56DGNPlH2Z11rvTFtO9HAeoTEgLaL+lYY1+0P1a+DJa7La+hlYrEhPs+BOvRRxQbG7fAt0ibafl8/jHvoFVzL6zN6vr1dSC+xp4OuvQ+z9qCpvVvYX1k6X3Q/5bEdsHz7KXkdcG0HLN5PmbVxGdOOT3+ALLHDRx3Zmsf2Aq6APM30XR3OR39qHeVTl5+UvNAjWPcMf5jqUlT3VD+oA4eJbB7m/DKCfZS1z1RdmhUis1inEJnN26dqU3mSb4Mn32qRT9FK/sZ9z4bBvvhJKUbC51dubW0j0uW9yXl/cGeVqIuiM6cknTmBdEZL0hkVdHyHI0N0TdFRvDE6Vf24OscGXmg/GJx1ufelR05/Z13zjRd86L3enC53Bf1AJeoB1rGlPHz3HUCz/NekNGbiYr0s3m0l3qkDaD7eWf5vLJ8ud4OHd6zbaPv5x0+RH3w4DccG3luX9wCaugziUDmApg4fH0wH0NRYp2wjH0BDe8YH0MYhjWMDizu0yXcAzcomh6tMp6YPV122457rt922c/u2PTt3ve6aHa+/a8fuPXVAViMHW/hx+huvhsp6avR3H6UtonQ85aCekKsGCl5xEOz5Gn6sqwbUiS7fVQPqJ3XVVRX3wTumIZ3Qn0JdGRGLf74CsXtXebbSUbzxnR4pSgdHUfb0qroCoEl0qrqCKtTTey95K4shLcRbsfzvAW/lfvJWcNTgnfaGjZ7eYtGOOuV/hDy9glE36emF7rx8LIB3vlUgy/9a4N3jxDukzbqNfGL7oq79UTN2/vlcFQ1Uq/PKI5iBXQvBnp7hV7lrAX0H9vQKepZTnp7yLFU/oKeHPFUncX1XefJVA+oaC98VOsoGhXh62KYQT89ka76gY2lHQhr/nO4K0eZE737eo3dL0vc60f59skGoCzn6/JwRomMYiF0wyn9OqL5krXBgvdSKQz2gLid9/XcW9r9q+8fY5ltd+Fsf4GfZpMtE/pK25cwRozExXR5tWvLUIe0oShuANKtDEk1cS/UraIvODOGf0lfMf+HEdL48faFWjlFH8mCNuVa5Qt0x/UP9Xpq+h8yDCupg8DzI8GPNg5RN9M2DFM8aIu1t8M62pV986/NgzY+IZbZZ9TPPg+YLOvM9dOaIOis6oyXpjAo6I6JcLeNfo8PfmI7izUxHvJdEpINy0CQ6SyPSWQp5eB60UNQhGf//jnx5XIXqp7LJw7781FgAvvy3PD4F1hHL4zxokWgH0/vuDM6Dsnj3feId+lUhvLP83ztqutw/enjHuo1jEo8jyI8llDYOabzj19KcC9utg+UtX8huHfTBq5gHGX6s3ToqZqTGeGtfwRs2puZBKk6o+gHnQchTdYMTz4PQzvI8CG3jOKWhPWOfC/U75OfasU08D1L16/lC4b7QvfCOaUgn1H9ZFhHL56P0fKFWOj1fyBWiU8QXWnPU9He073l9oQdhPD82fa/SFzo+fTmQvtAG4l1RX2g38O4k4h3SZt1WMTPlJ7EvhLzieX3emDCWP9Riwmq8KunrTflC6kbNPDFh5Rf5fKGFlKZi/cqecUzY5wst7NAmny+EZfHvAZF3AbQX814KenbHUdm00l8TnkpbAGlHUFqofiIG8jfrNPrt1AbL/+K03kms8ZatGrPP+dekVOzT2jFkdCEth/z+VlKvS7dO00F5SZ6BidY64/jn86ks/+EiP8oc+4aHQxr7c0oe0b8weVT8sjpWwS+sQwi/1NpUKL9Y75FfRxKW8n+Rhz5+WR2r4BfWIYRfmD8vv4wHil8rCKvTHOcyqqthDzptEwyvTvlvB5vAt+X4bPwCgY22sUYY2I6aaMcIpWHZBHd3WuGZivOwr7kS6sKygLh1yv9GGDfuI950uvma5UvFODBusZDag+P46gCsRR7avp/oU7SxXrx3hffMKH9D2QHjTUk7MKDsAMar2A6oflL7n3y8Uv2k1sJ5z1pozGklpYXGnMbTdyWfKv6UZbNZH3A+w3Od0J8PqlEdMT/qMcueirEq/We7gfrPdgNllO0G9i3bjaI71J+iOWoVO9RZvutOy3fWzvNfANv2wQzbNpATcy+MR2eBjiaPWm8vaQvqyhagvrMt8Nng5MlrN1lvsW94rUGtmyNP2ScwHg2K/IjHJ5w+GegT+HZ9j1Na6LzP9CGRmy+mGTkmkLw3Id8vkuyhTVNzRZY9y/8lkOfP0Bwvht1YSmm+ky1qzFFypnbO4xjK5cwOlNwPHhxL4f3gZW9SD13nifFTyMl/6kSL6geMpXQ6VWljwUzbNeRTiF3D/GZbQvb2oY1gO6D2orKNUPTQRqAv/sWMGDS2I9Rnwfj1GtJ/1C/Wf9Rx1n+Ud/YbkIfsN6ifckMbhGM25v9zsGHfJt4oWfb5sWpvqfpJbHVq7JgArHEPbXWK3fcTt+pn47kuzmXrpNJF400V8w30C1gXVT+p8yM+Xql+UrezHENpobrLJ7dwfGe9RtnGE6Lfzhi3sR0qxqv8gXHA/UXPGlI3xwr+GXR3eHkrZi9W0F7PXqygNW0mYwUsn7FiBbxHrBcrmH7PihUsTivazbGC9bDf8fAM25Y3VnBkitOLFRy4WMEx0AcHMlZwWVqPTrGCE0j20KbliRVcCfJ8YvreixXIpxcrIHq9WMGBiRVcRrofK1bwd7QHHfWrm2MF14ENezXxphcryNbJXqwgn+7GiBW8OmPcxnYUiRWcQGO3miepuQKfo18u6q3sQdavOWft5eJYgeW/E3T3ncQb3686J09e/eGbo5T++LB8e4zUTUXHemhjvfhmdNZldbZ9pmMFqJ+suz6bmTwhvFL9pG6m5Rtw1TikzvTz7U04DrGtQNkeT9+VfIbubVL3auBeo8cqjhXwbepqzqL0n+0G6j/bDXWbmpJ1thvWnxgrwPwcK7D8j1CsoOBNqDJWwDf3430SSr55bmX5Pwa27X0Ztm0gJ+YTXRArQH1nW+CzwcmT126y3mLf8F0uoTersZ4NOu1D8F5Dy/+sJ1aA9oj9DDX3VfaI7Zi65yiRmz8IjBV8IlKs4PMgz5/2xAqK2o01lIZ2ADFYpnxypmIFOIZyObMDJW8wDI4V8O3yZW9YDr1dPsYN0sl/6pd8s250VjxVN4x3Y6ygE1957o5tZH1GG8F2AG0E24/VHnpqfoc2wmcj1Q3t6l4c9Fne64kVsP6jjrP+o7yz34A8ZL9hLdRF+Tw4ZmP+PwIb9r+JN0qWfX7sOpEfb8nn+brvV3gV1riHtvr1mnUe2urXa7guzmXrpNJF400V8w30C1gXVT+pX7bw8Ur1U4PyI2/y6u5aSsPxnfUaZdtkXsnnuGhHkVjBJ2jsxnpXcbsy2gZsv7pzEXHZ9/0u6G6t2Yqp7DPay7x+J8+Z1Hzdh+VbH/PJr6KN9cKyTJvraeWU7hpvqtDdmPMDxSvVTw3Xrtesg6E3PbN+oh75bnrGcbfWbG1Hp30vvnEX15X5tnXfvovkYX764qxK9laL9in998XW2G74Ytrq1y9ZzzBWgPk5VjDV/839/5b8hR0ZK+BflcN4hpJvnltZ/tXN/f8mfTyvqTEHcmIuTHE6xQqsH6vwqVHf2Rb4bHDy5LWbrLfYNyF7wdSvvrCeDTods8Q9L5i/2dz/r4oVoD3iuGbozfO8d2oc0jBWsKW5/53XYpL3JuQ7utnabhXXR5vDsmf5L2xOl1ubvse0G+OUpmJGvjHH92u2al1AybPZgZJz6eBYAf8aU8HYhPfXmNR8p6TdnIoVqDmO6geMFXT6BTJfrKBKu+ZbD+nEV567YxtZn9FGsB1AG8H2Y7mH3jiUQ1/cbITPRob6LLjmeSnFClC/fOtirP8o7765NbYP5UbZMB6zMf8Vzelyr2y2YipZ9vmxnebrHPtU83Ufli9OcbzIv95DG+uFZZl2lk4qXTTeVDHfQL+AddEXo0meEF6pfmpQfuRNXt09jtJwfGe9Hoc0jIGxfHbaT8G6mxU/NH9Axfmr+JVmnlsfD3VR+wpwHMD8r2lOl3tzsxXzBDf9hMiE+oXiEyAP2zCUiQ0BWMs9tDeK/Bs8tLFeWJZpcz2tnNJd400Vuov6xrqr+gnzh/BK9VOD8iNvLM13v/g4pB1PaaG/GG0yr+Sz0/q/b1/BcsDlX21XttAne53GLJY9NWYp/We7gfrPdgNllO0G9i3bDf4lcM7PsQLL/97m/n/N/0QZKRsr2Eh1PAHqoOSb51aWf29z/79JH9/f1JgDOTEfSnE6xQqsH6vwqVHf2Rb4bHDy5LWbrLfYNxzTUXEH5CnHCoxHgyI/4tUp/wea+/9VsQK0RydQ3cchzfcL9uxnoM5grOA3m/vfR1y77jYh3zPN1najTWN7kTwse5b/t5vT5T6Svse0G2spDe0A+9ZqzFFyptaKcAzlcmYHzK6gLFYRKzD8Ydfe5iKxAqV/OD5wrKCg3ZyKFZws6Kl+wFgB8hTpG5YvVlClXUM+hdg1zM9zd2wj6zPaCLYD45DG9uNYDz20EeiLm43w2chQnwXn519NfRal46z/qOOs/yjv7DcgD9lv2Ah1UT4PjtmY/w+b0+X+otmKqWTZ58eeIvKfDHnWUXtQ1k8JwFrvoX2qyH+KhzbWC8sy7SydVLpovKlivoF+Aeui6ifMH8Ir1U8Nyo+8yau7GykNx3fWa5Rtk3klnz4/P3lYd9eJuqI/cLDFCv6uOV3uX5utmMo++2IFeefraMM2BmD55ms++VW0sV5YlmlzPa1cN8UKVD/5bKzileqnhmvXa9bBmYwVsHzGihU89wKPFYSM+RgrwPwcK7D8h6UVMP8TZaRsrOBkqiPGM0Lm9Zb/yLSOSR/PGteYobECyz8nxTmQsQLUd7YFPhucPHntJust9s2BihUsgT7wxQo4rjkOaTFiBWelgJ1iBctJ9orGCs4FeV6RvlcZK0A7wLECNeYoOVOxAhxDuZzZgZJz6eBYgeEPu/Y2F4kVKP3zxQoK2s2pWIGa46h+wFiBmosgVjfGCjrxlefuKqaZd77B9qNIrOAs0v1YsYKnIsUKUN7Zb0Aest9wMtRF+Tw4ZmP+C8CGvYR4o2TZ58fGmK/7sHyxgtNE/lM9tLFeWJZpZ+nkTMcK0C9gXfTFaJInhFeqnxqUH3mTV3dPpjQc31mvUbYxBvaSjHEb21EkVsD+wLjA9f1OhNpj5ZufdNo7yvMT5QupvUZHZdBBm4B98pb0nfca3ZJm6uRT429r78OBtBzyPlr1PppO80HjifKNeM8L8hjPI2G/IWbC+7fT2ICxKN6TofaHqnkyy17Wb5TwfjLLfyf08UVbNSbWYRy+lZVnbENZeUbd2E1ttfz3zKw8zznQ8swyi/LMMSElzzXXbsPKxHNe34Xy/9OHkPw/2OXyr+YSPvnvFCNh+Uf/7UDI/4055H+jh6aSf2tblvxjPBHzT3rkX/F3HL7lXSP0yf8plIbljsqgg/KP/c7yb/mfD5R/o12F/COPWP5986bkyTvX4TUB9N998s/rtbHkf0sO+R/30FTyb23Nkn/D43j5r3jkX+mg7xxj3rUubMPJlIbljsqgk+XPs/xb/s8Gyr/RrkL+Y85fO8UZjCdqrdsn/7zOEUv+15H84xl3jg3lPcfuu7vC2qHObKrzAHxm83+OT5f7m/FWTOUj+e5IjDHn9WH59NPnXyva6m4MrosT9bRyFZ7/Gqj6XKvileqnBuVH3ijd4jPuoedKfHfl4Xkxlk91xj1Ud/GM+58c0Yp7dAfcvHe48h006g5Xpf++OyFCzrErWWe7wXcgcX5ei7b8P0iJ2PoGykgOWZdr0euojngOX8k3r91Z/sNW7P836eMfZti2gZyY/5LidBpnI91VU6/6rppOdpP1Vp1Nq9HfiKXWb1jPBp2e6/K9LJa/L+3XTmvRfB+Huq9J2SM+c4c6g2vRq9N68Bnd5L0J+YZXtLa76F2Mx4A8j6TvMe0G34el7jrwjTlKzhqiPI6hXM7sQMkz4MFr0YY/7NrbXGQtOvR+upJ2c2otWsUJVT/gWrQ6Q4tYvrXoKu2a7x6fTnzltWFsI+sz2gjf3TtsP8Y99NBGoC++mnS/0/057LOo33hKcD+f+ixKx333OYWcY1d75thvWAd1UT4PjtmY/wSwYecRb5Qs+/zY40V+jIPz/UHqnLkPy3e+/gSR/3gPbXVuh+viXLZOKl003lQx30C/gHWx05psCK9UPzUoP/Imr+7y+vY4pPnuysP4+3kZ4za2Q92zofwBHPOHaexG+kXHbr5TAfWa76dRawxoZ7Lup7gcdPcm4o3yI8vcT8Fzprz3U6z20O5kN5i2shtcF+eyx1aluy+U+yl4zo82kPeKqPtalO5yjEHdnWJpasxR8qnulgkdd/FumQcpVhD7HkjffbW8V9R3fyTqv+9uVt9dLGw32D/k/BwrsPy3p31h/ifKSNlYAY/jeOZGyTfPrSz/28G23ZFh2wZyYu6GeaovVhBpHK9XPY53spust9g3PH9UYynylGMFxqNBp+MUfP+y5X9LYKyA/QXfPEDF75Q9wljBXooVoO42Id87SfaKxqmeBXl+D/kbMeyGz7fmfatqzFFypvYG4hjK5cwOmF1BWawiVmD4w669zUViBaFz95J2cypWoPxw1Q8YK0CeIn08l5w8M23XfDHQTnzluTu2kfU5NJ7I9mONhx7aCPTF9wbMN0J9FpxvvItiBb67n333yavYr5rfst+gzsmqs4h8TvYTYMM+S7xRslzmTi3eh6/On/qwfDH2Tmd0ffcM9e7U0v2kzpz47tTy6S7HGHB8Z71G2cb95Z/NGLexHWotRPkDOOa/0xMrWOla0/LGA5TOs5+mfF/1uwPs+/430N2vVhznC5mv+7B887VOcT6m3YvzteZX/RQS51sJaRwrCNVP1nmU7ZY7YCqKFVxCsQJlE3yy12k/Dcte6BkStht54wFK1tluWH9irADzc6zA8n+LYgUoI2VjBSdQHTGeoeQ760zwf4Jt+3aGbct7zvh7gbGCSPu3c58F9dng5MlrN1lv1Rhfo78RS50BYz0bdM57doLnzP/miRWgPeK4JtojjoGou92VPcJYwZEpMZ7rJO9NyFdb2dpuFddHm8OyZ/mbK6fL1dP3mHaD9zipmJFvzFFyptZ5cQzlcmYHSs6lg2MFhj/s2ttcJFag9E/Nd0razalYQej9exgrUHMRxPLFCqq0a771kE585bk7ttH328C+NQy2H767+tFGoC9+JOm+spGhPgvuV3gRxQpQv1j/88YD1Nya/YYToC7K58ExG/MfDTbsTOKNkmWfH9tpvu673zPkTq0y555894V0ulNL6aTSReNNFfMN9AtYF/PeudvpTi32/313aoXq7gmUpuIBSncxBnZmxriN7VDxSuUP4Jhfo7H7YIkVnA+6ewPxphcraK9nL1bQmjaTsQKWz1ixgoFerCB3rGBHWrlujhW8CWzbqzNsW95YwWtTnF6s4MDFCu6GPjiQsYInAmMFb44UK/gAyPNEL1bge3qxAqLXixUcmFjBExXFCv798P3vB1us4BmwYZ/pxQraaGfpZC9WkE93Y8QKPlNRrODNNHZjm3x7kPmMYMwzCLhfI+sMwudAd/+YeBP7DIJvb1TIGYSVHtqd4hRMu3cGoTW/6ic17rKe4Vi2ktLUOaAyZxBYPleKdoT+vu1KwP3c4a24ajz3yV6nMwi+M0i+MwhsN9S9A0XjCKxnec8g/C+KFRT06Ss9g/AvYNv+d4Zty3sG4RuBsYLeGYR2nsY6g/APnlgB2iOOc6A9inEGYWFKrNMZhH8l2St6BmHJqulyPyJ/I4bd6J1B6J1B2Aee/vtCPYOg1tCUjYhxBsFshM9GhvoseAbhMxQr8K1NqHsHisYReNzIewZhOdiwE4k3SpZ7ZxD2P70zCPl0N8YZBJbPWGcQ/jVgzXOlwK1RfTE/2pC896lxbDH0PrVVGXTQJmCfvCN953uYzkmBZugOsMG8d+Wo+aAvDtJpPshr6mi7+W4ddQbN6rxSYCa8/yDNZ2tpGs7xToL3EyEd878sJW5+A7YzB7+vGIEyDjAcYNcLYtcIzznt56FPo+glz7BIqwfUZd1b3rB++T0DG2pU3urC31heBkT+W0R+49Ug1b3pgp7LlE4ZbUurQxr7gagXVodEl9ZS/QYK1i+Ef4jfEPmvmpjOl6cvxlyrLKC8m+0bh7SFlIY2k+2p7+7KKu6gvRl8rLsCxrADeQftuIe2L66paKs5JtfFueyxWenHoXgH7UJIG6c0HHPYb8OxKvQOWpbPcdGO0DtoxwH3bhoDlc/kk71OPhPLXqjPxHYD9Z/tRt6YDusZ2syQO2jfTuN9wVhIpXfQPgG27V0Zti1vXO2nZ9b/7N1B69rvoH0U+oBjumiPeM6H9sgX5wm9g/ZXKKabdQftUxlxHXV/Y/Jk3UH76yDPH0zfY9oNjvf07qANpte7g9aVt2szdQct2gi2A2gj2H6s8tBDG4G++K+Q7isbGeqz4B20t1FMF/WL9R91nPU/byyYxw1lw3jMxvy/BTbsT4g3vTtos3XyhXzeJM8dtKG6y3Hb0Fgwrsf8Sca4je0ocgct+wOLBO64wK25djsUEtP1nZNBWmo/GvsEWG5hBp2sGMQ70vc65f9aoE9ttKuI6SKPWN6VzfadB1LzR/SVeX6t4utK3o2m1XlcYCa830pjw5GQL/2ppKm0FZDGe49QDvg+MiU/PjmYL9rIcvB9GBv6V7diqj5YAd/y9sF8ag/agKMDsI700O4UD2DaKh7AdXGinlZO6YrxpoqxIaauKF6pflLzCB43lkHakZQWev8x6984pJnMK/k8UrRjPnzjsWG+qOu+9b6lrbgrBa5P9tTYgHrMsrdCtE/pP9sN1H+2GyijbDewb8ep7hijdiI/x6Is/1hK0OY3KCM5ZF3GonjeizEJJd88d7f8R6eZkj5ekGHbBnJiLk4zdRo3rR+rmLOhvrMt8Nng5MlrN1lvsW9WENYKgYU8ZZ/KeDTo9Hq04dUp/wroA45FoT3y/Q4Kn7deLugqe4SxqAvSeqj13ibkO5Zkr8WmuXabw7Jn+S8GeV6Xvse0G+OUhnaA9xKoMUfJmS/Wp+TZ7IDZFZTFKmJRhj/s2ttcJBal9A/HB45FFbSbU7EotfdB9QPGotQcCbF8sagq7RryKcSu+WJD2EbWZ7QRbAfQRrD9WO6hNw7l0Be/gHRf2chQn2UF4H4v9VmUjrP+o46X/W1WHjeUDeMxG/NfBTbsZuJN7N+W4Libiof7sFZ5aHdad/fF/Hmtm2PxSieVLhpvqphvxNxvpXil+knFkTluFKq7HKfC8Z31ehzSTOaVfPr8/ORh3V0p6qr8gSGBWxO49n0OYPUTRvL+lvS9Tvl3Ct/VMEdFHfrgG/fpXJF/FPJYfUapDlh2VJQzOVfybvlKyrv8LW9sD8v7GKT1i/zMm3ki/xjlSZ4G5Uc+WdoIpBnNEcJBficy8fDiVlpzRH2wb1m+5gJWv2vvvzT7lHxZ/jd55EvxcBZ8y8tDq88o1QHLjopyjfRdyZflKylfo0q+sD0sXzj+94v8zJsFIj/6Cex7L4C0uZTWgDSjOUI4bHPmL2jNNwL1qWX8a3Xlb1xXxLK9giOuXY7L0kF5tjmd0ZkNac30PWn3Q2S3G5DWL8q+MX2vU/5PgQ/0KM3jsPwcKm9p7wc9e9XW7PLGy1HXbkt89rnmOrfTZw8s/9NQz1s8sRL7VlLvGkrvGpCB9U7ZGMzPeufTU2W7USdnE9ZsgYXyzTbZeDTodB8YXp3yf9QTK0GfoUF1r+WsuxpPlB2xsoksfT5l0Khrt0VziWZD0FR91RDlGxlYfaL+qLfc7/2CtspvMoHxSmWf65T/l6Gvdm7VmC6jDrMz6jyYkX8e1cHy/5qQF58dQPkfI0zL/xuAeUpOzJ/KwPxNj6+h9NTnr3UaT9mfQD4uoDSsO4+L84E+530r0cc0lHOm6zz1VT6kr7483ljan8F49XmK+6NvkcNW9/v66mWivqF9NdvTPsaycniuJkRHkB9/tFpjDuTE/BMxpitf5UTA/7MMf8S5dn8kedguo81APXyIfBKkP4vqb2PIXwSuixhWubG+9tdqrMd59MDENG4WbzB/yPwW+9E33pxAabMgbYjoqLl/6FiKc74n5rfizvLgJu+vpnooO4z1viN9Zzv89x47rHjo47lvno31UXZ4jNKw7iZzSh4tXxXyOJMxBZZHNX4oe8J+lk9ukscnj1Y2kaH3km83JmiOeurqGx/miXbz+DCYkZ9t/tR4kgYFld+zUNTBF7tQe8sWijqPUh2wLNNW+3qS5/KJ1vZY/kFoj88eR4p5jCn5R76x/Pt4lDzM08UiP/KK96wshrQFlIYyv5DS1Fjt09lQ3bCyST++JIetRly2q6G22vIvEjLha5vPVneyR2yruyg+N/ZCjM+h7T2X5Ev5Pj77Fer7hMT2fXPUvHN65a+qOE8t41+jw9+YjqqzkmNuj+Lb3MD2cGx/bsT2qDpz7DZ5b6bviQydsmb6O9uvfiqbPDwOWf6r1kyXOz19V/FI43lemarR+1zggbKl10y4qfYnD9oXw61iPRXtK9sXny21tmD+Tj4R2xC0PSOENSKwUPZwTNuXZ2K6fCR7PJA3buuzT8kTMlahTljbQtbjUN5YDhUvQ/2DqTscfvzfrPmd6z/H095O8sHrAjj+8l5V5ZsrWbB8VYzN2B6WBd9YmzzMG+XL4/jLsoB++xilYf/PJzrKn1L2kvsY7Sv2C68lWf6bPD6dkgOf3HTyW3iOrWJrvvneTPt03SI3HI9F25NXbtiGoD3HMdrG705zZhwnx0SdrR988X7D4TbMcjrW/QZqM/vSjP2TlB/XNvo8decY692eOf78DnW4h+qwoEMdsuIMbxR18PE/edQcxcahknH4Oo5n9rBPifjDTstH0wU9NZ/+qTkVxxKwrM9G+/RWxRkU1uyIWL4xdxbRUTZgzEMHy4956DRK0lHxVuXf1jL+NTr8jeko3hidBRHpoM7wfHJhRDooB02isygiHYyHnUR05og6JOPEkzTPWwxpymfgswmW/+tHT5d7muZ5aCs4vmnl8fzRPNEOpvfhlIbZvyVQJoc9kuePDKsT754l3ikfzsc7y/97wLvnPbxj3VYxzlHXzg++m2AppCEGpjloA35jmcPylm9ElOPx6nD4nmeuGKIbiD/s2ttcZLw6nOhh25OHz3UcUYze1LmOZYKe6gc814E8RfqGZTqm7Cz7qGgbl1Ia2rMllIb6fSK8I42sNplvO+qpn29NJ3mU78+yN9O+0vxi9Ly+kpqr5PWVeH2jW30lrCf7Skqm5nnoYPl5HjqNknR8cXvlx4fIlqKjeNPzlTrTKeIrfTWSr/QqGO//isZ7tBUhvtJ80Q6m9zdd4Cv9LfEO90mF8M7yXwK8+6aHd6zbPV9pup74DfF7vlK2r6T8jSp9pfkd2sS+kqqf8neSp+nCnhBfCtuXo+/GQ2XT8GP5UsovUb6UtW9RMXrNRNZmpeXQbr4W3pF3SGcB1aFs/6nYzIHqv7Fi9Lz9p2JWMfsPdStP/ynd5P12ef1KtY+mar+S9yZkjfELjp7+jnzIGuN5z4DlXwVj/OL0Xe0L8O0jqkGd97V5Yjot0ppTfzfvI/KtW/O8L/R8aKdzgV+ap+tfA9w3irKs25h/gaiH5Teds72enMfK1in/salMJf13+lZdZ5RZrBevw1r+dYDJ67Bqr6NvrbHTXkf2UZHPiykNy6G92Ic9MZ1m+UrqxLjSCWwP68QSSPP5ipZf+dzov7Pcoy/b6SxJ8uC6PMunqutYibpyP2JfLSUstQ8Y28NyafnPFXKp+t94XkX/+/YBK5769gF34inHu5CPfAck2kG+V1PZXnU+U42JaEMW0PhV9RyVYwaHQ136RV0Nt075r4Yx+BYa122+5FyYzqr5Gc65+Cw/zs2WBWD5bKm6I3CZhzbWC8syba6nlatQt+Q+OZxrs26pfsL8IbxS/dSg/MibvPPlwyktdL5sMq/ks9O+J5/uYlyKY1bKVvlkL3SsUvq/lNKwHNsNNcYpXWK7gX3LdoPjIJyfY42W//VpX9j8C2WkbKzxSKrjEVAHJd8cQ7T87wbbtifDtg3kxHxD4Dhr/VjF/Wmo72wLfDY4efLaTdZb7BuOkyp/FnnKfr3xaFDkR7w65X8b9AHfdYD26Aiqe2j8bjGlqTWERG6eS+sx4tp1twn5fppkD20a24vkYdmz/B8Fef5Z8jdi2A3+LSW0A+ynqjFHyZnyz3AM5XJmB8yuoCxWERM3/GHX3uYicavQGHVJuzkVEz9K0FP9gDFxdZczYvnuhazSriGfQuyaipM3XHsbWZ/RRrAdQBvB9mOhhx7aCPTFnyPdVzYy1GfBdciv0poY6hfrP+o46z/KO/sNyEP2G/BebeXz4JiN+X8ObNhvE2+ULPv82HGRH+8GXELtQVkfD8Ba6qG9UuQf99DGemFZpp2lk0oXjTdVzDfQL2BdVP3kuzdd8Ur1U4PyI2/y6i7fUY/jO+s1yrbJvJJPn5+fPKy7S0Rd0R+Yqb1/sWIF/wN092tdHivwxdt7sYK0Pq6zjY0ZKwjdhxgjVsDy2elsnW/cxf2+zwbECnyyV1WsgO1GN8UKvnMQxAr6j9n/b9LH348UK/jHXqxgKu1AxQr+wxMrQHmqOlYwnspXp1jBwDGt7S4aK1gF8jyUvse0G71YQS9WsA88/feFGitAG1F1rGCcdD9WrOBJT6yA9b+bYgXHgQ07l3jTixVk62QvVpBPd2PECs7NGLexHUViBewP8N6p5LlxYvob3/vC+yIRA+vBNidrr5WV5bMHF6b1xL1W6nyKYSVtuzijbWgn1J15vPflVWAnLiNfB/nF9wshb3jvLNpPzLuvrRNO8uBaqMfVx2TTsrXkEU8bE4zrjtH5sA6YjzHsvgLfObG5opzab8Z7wxcSjQUeGvNFOUVjHmEiz9RYuKRD+mLRNie+9Yn8CzPa6wTtRR1wFwgcFc/kfUtjIq3m2mXB2ht6fwjuWzolrYDSlyydUHK10FN3nvv57lhRdVf8Q/vhu4vG/mbZGhPtrIm/rX6vh29sY9Ud7JjHyvIZpzuFzWRMtIVYr10ZmHcB5lkZe14dYJ4C3/LehcO+o9JzVXe0JfxN9c9sysvnJMwWKpkdy6DD/FB1UHH5mbzbp0m6if493znfoLpjXt7fin8r+a7Ru7UV5RvzsHxb/nd75LvTbw/tysD8GY98K76fDN/y3m0a8ttDqu5oe/ib6h+Wb45zonzzb+PMyaCjZJ/r0BA4Jt8jGZhMk+UheVi+a4JO0u8/n1ZQ8ZfvT8975+aQqD//TtpTIEv8exXqt9ewjXymxfJ/0COfse9Jt/oo+zDmKYf9NyRoNe3lP/2P4ZkuHOayZZDvQvkI8On8rbouNa5Ph8d3p+oQ0Tfb13RBTxNl2B4VIzT8YdfOiyIxQt+dlsnDMcKC5yaX4zk4lCM8B6f2+mJ/8Z2eNaC/T99pvqd0DMu+Ln1nHfsMzLN+MQPTuXK26YmxVtzY9/hbO/Oed/PdmZF1PyjyF/Pfkb6zD/lZ0M1bKr9TvvaDA32nI69F47wmy3dCLOxrjqcYj7J+p4B/i8fy/yH0Aa9b4djMe+77cta9Iequ9Lhl3CadU78TNiRwfXqP98q8On1nvf+SZ2xtiDqg3ue9+5zvAw+9p9r6psJ7p8cO9G+QWP1VDCPP75qij4a/F7ebbO/pkI9jwsnD8nVG+j0rholrV5j/f4v5irVjGOpwOrXjDKiLyZyNx+dQ3Zsu6OnDccke5W8Y/jDVJSe9KX/jHKLH7TNZSfrL+v2uPTtv27nnnst3bdu+Zdsdu++6bQeeKkaOM5UaoeI31mBM66dvsyjflROtf1vv97vsB6Ur+W8zpClO8M0c2KbNGeVYcvlbn8h/DmGdI8pZ3fs95REDy7HEsBahlT5d0GYt+ifQotu2ZtM93bXzgTVpSNAzrdtMeZ2b1rrzqE1NF/TcEKp1hj9MdSmqdecRPW5fMa1DSUEq1xOq5cG8+FwPNcP8s+hv7r3Zohw/xrER184J7tUtVKbpgp55ob1q+MOulBRN9eoWosft47nb+cXojdWoPNJDTKuP8fpGkWZYr0j/Ru3H/OdDGzA/vidPnb7NPnb/vw3CTB77HeiaSOsX3/qgjgMp7qhoz0pqm+qXLQJXrTFbPkXnvJJ0zgukU0V7rJ/MZqxO+ZnwdhHx9hxPm9Voc05gm89x2XRWlqSzUtAxPRiHNL4j8DhP2jpIO4/S1kNak9KOh3ryb59vcO1ttrSNHsxTBWbSd188drpM8t/9kE+NNOzV7ASaWBb/HqC8ycNr5Jb3RJCrtce2tgH7m3mt9MzS0MY1KU3ZF0tDm8W83uHBfJXATNrz+9Qe5lfymK1/AL7nsPXXh45lhj9MdSk6lj1A9Lh9PJY9WIzedTUqj/QQ0+pjvH5IpBnWw+nfOJZh/gehDZgf35OnTt820Vj2EOTlsewh0R78hmPZmSRHyPtaxr+Gy9/YDiJvrP+MDup6E+pzQYYNQX5iWZvzs+7/l7Omy11MYwqW575VelS0/feLNvr4XFKe54fqq+EPu1L2oebTH2wf6+tDxejNC5FvrI/x+mGRZliPpH+jfGH+h6ANmB/fk6dO324kfUXdZn19WLQHv6G+biV9Rd6XlVefzdsMaU2oz02krw9AWr8oe2v6Xqf8T4G+3kz6ivLJfVtV+3ncPy8iHfRDm/CeJQvYfuOf8Qbl/mEqh7LKOqdk/RFBW+EbRifZuONY3bYs2TBaPPZNgGzsDpCNUZfdn6OuvQ/QTmfZF8x/q9PtGszIn9WuN6ZtUb8dZeWz/Age9yz/mwGT1y2UbKEfzbF5JQ/KNiqePuI600Y+c1zdyg86vyyy3X2H4Kkaj638iKiL6e6Q03LfdEHPeSH2AfGHXanxsRbKax6PHylGb7NPThCTef2oSDOsx9K/Ue4x/yPQBsyP78lTp2+P0Hj8KOTl8fhR0R78huPxfTQeI+/LjhNK1zrZ3MfJ5j4EacrmviZ9r1P+nWBznyKbq/Sw6vavJDqPRKSDstqEd5YpZYeMf8YblNXHqNz7IA3z4XiM8vw+QVvhG0Yn2fjYsbptWbJhtFiXrgTZ+CTJBpZ/mHiDfHuE0rCveTzuNA69hvJbvQed38+pU/5f9IzHyndBueHx2PJ/xjMeKzvjG4+VLCrbqHj6GGHtFFjIZx6PFU+x/Tup/Zb/vwaOx1ZexedOpLQtkMbzFIzP8VwB1xTYv8f43GZKw/gc2+FXQRrKCMfnxj3twbgvx4vXQRqvqWDc93xKOx7SbqQ0jPu+gtIw7ruD0k6FtFdBWy3uW6e2fin9XnJ/gryLISuuzvnwX+fCxgPsK/79o3Mi0kGsiyda6WyOSGezpz1bBJ2Sa4TB+0kMf9i163URv1etSaq1qXwr27zqhFxBVPxWc62tx7R++lbFfhK1mrlFYNpIgW26MaMc8sKJb30i//mEdb4oZ3Xv95RHDLVyye2371n7SQyjTvn/HkarXTRaK1rIDx4xre5ZO8O4Dpb/e1AHPslyPpRR7dqSgdm31k3x4x+O1ZhOYKp23Ujt4jqcT3Ww/P8sPIF+ysP1Ud+Sv3GvDpblv5XMnE75X9GhPdxPlv9Hnn46T9QBdZJ5ynXgPDdm1MGtba+DsG5bdt1xT2rdHD11eGdrpDjP+27OEzhZj3EjkUKTSPZ72VKpbywBVjZpue21Tlt+/o7bduzZkdF2ttyzMmj2Of2EjKEF10KDx1DDjzWGqjV7NYbyOhaWVet/2L/4dyc6SZ9OnTfd36fX7tl1Z1aXhg6uNVEtLu8Iqya+JQ8vaWLagRKDncXoecVATU3zuVIonMwVRMVvPs536m1zqu0p4kqpzQg7Baa5UtimBzLKdTJyfSL//YR1vyhnde/3lEcMLMcSwxqS5Uqxy2H5j4Khybbmchn7+0545623FWxsGQvVqgO1sSWfVrFpNSpzCdXyYF585kLNMH/WsGiPHU8N0aqQIbNgr44U7dWyQ6bqVTWUldzeMbtG5ZFet21XOinV/tjbldavbaVnsr8JJjinpO9mkVdAnXkEWiForxC0G6K85eOjOck7bynEiSJvDTzfkxa6pZBDg0W2FL51bWu+GFvBfH2Mlo9HUZTnhwjr4Q5Y1xBW1haG5L9HOmBtJSy1jMDuriqHofIVAXXAbyyDK0Qdql4WY1nP2r734rXT37Fc1va93el7nfKfBktMW0mfsfxMtZ/1a0tEOmhTmvCe/KeWfBT/umn5cYVoz75tXWt121A2Vog68vLjMpCNHR5bz8thyvtWRx54jFT6ifl3U361VLZF1IuXym4Dj/mijOCjWn5MHr4ixPLvAsyQ5Ufljfpk0bf8iG3m5Uc1Gymz/Gh4zNO7BU9DtifjWM7LdRjc4yVGDHDzUiEGJnnbBI7lbGtxLOdlUlx+RBl5K/lJ1p63pd+HXLu+5PBF5ZKcYSldxGVMTHMuzO9aF0hnQ0k6GwQd41XR485WvmBMpp9twL6Pok4sG9jOWsa/hsVpRmvYlZIT7/HEUD8b25iFtSUnVsljnlN9cobLbhfij3jqourJiw62RWA0fdm31Yv8dTzsXaN2jsP3HO08NVReDH+Y6lJUXsaJHrePw9DHibo0RNpL4B3TkM5xgo7CmhcR66yIWAsjYh0eEWtxl7YxZj/GbOMRXdrG+RGxrouItSoiViMi1pqIWAsiYsWUiZj6GFOHYspETH4tioi1JCJWTN6PRcSKyfu5EbFi8iumLVwaESsmv7rVFsbkV0ybcyj4TDFlIua4HZP3qyNixZT7mLw/OiJWTN7HbGNMOxHTB4jJr2MiYq0lrHGBpeb1ln+9yL9C5LdYIMYJrazFQPBIRI6YRJ+PD3gEw/Bnu2k7NLUN8ea7br18162MjaEUZM8plM/C4X2uncXrMrAc/X0KfesHPHyS0NLm1HcL2a5RMKx5Yo3wuA2O8GNt1wjdecgbkLCsOsF0A7xjGtJRyysKa15ErPkRsa6LiLUqIlYjItaaiFgLImLFlImFEbEWR8SKKRMx+bUoIlZMfo1FxIrJr7MiYsWU1cMjYh0K/Tg3IlZMfsUch5ZGxIrJr24dh2LyK6a9jylfMW1OTH2MKRMxfaaYvF8dESum3Mfk/dERsWLyPmYbY9qJbvW/jomIZaGS0fRvnFevIDpqDrvTQwfLFz2JZ/nV8QNfSOYBKG9lS94E2efjt9o6XiIkY+zZSPk4JINd+UAGlqO/N9K3rJAM7wK6N32Z6V18r6D6Y7f7RKEhyvvoVLFb0LcrzviIYbUcfJyD/MN64jfEj7WrTkUkFV9K7nYbqbl2s9AvMK0+6pQA8hb1JetkwBZoA+sXqj1f/PtYSqjh2s3bVROtdQg1o0kdHziutW3I+1rGv4bL33wR8xB5LUoH5a2Zvpv+YT+ynvv6XdFRJ5MYC/sdd9DvoPx4sZTCPAnSMf+HU6YmO7/vpB+wOkPwIanPs8d1rusZoq686/4/zpwu93yKqfhs/a7kYAulrRB0FSbbzrx9py6c8mFhf62n/NYXgxn5DY/77heg7/gkhJXPkp8tGXVA+cE6ZMnPLxeQn185rnNdsex6om35/xrk59dJfrC8T354dzHKj/FIjb1V7KBXdDZTmqq7b5zzrUAqHik6N5Wkc5OgU/X4cBPR2RGRjjo1qqYj2+Ad04wOf2M6WH6nh86GknQ2CDrK10A/vOQp9P6SU5upkwW+S/UR33dPQogcIK1Y9xyouvumwer0ug/rwZxYJU/eT/XJAy67XYg/4qmLqidPycu0eUVErPMJS+nfNoFl+Tud+uZQgZq6l7yEu8/Xd+pkeIRQwfWUzw6D97l2EX8wA8vR39fTt6xQgTKjZ2TU0+h2MqPqkNlMmWtF59ySdM4NpLOpJJ1NgXQuLknn4kA6LzS+zVR7ri1J59oua8+mknQ2BdJ5ocl1Tw5a6Ww6BNpT4eV+wWFjwx927W0u4p6rVRPFlxgXcmF5pIeYVh/lNiNvk//U71koN7uP8uN78vDvXWxI417sBicPh41DXep9vzuZ4o6K9rBe5F09xPKWT9HZVJLOpkA6L7T2XFCSzgWBdGaKb1tL0tnaZe3ZVJLOpkA620vS2R5Ip2cPuqc9vt9WTuz6y9dpmjguYVkLMfJy5bEnTJe7icYKDOVc6Frp5Q3LY3lfWN4XLudlp/UCs0ZpWL/1nvph+fUZ5bA+yWP+Cf4uSR5/aIjalbP8VFhQ/doC1ol/R4W3fah/DYvTjNYwYeVtu6/uWD/uJ7zECtuYhXVjTqwhkVakT0512e1C/BFPXVQ9eYlT0bkQvnFIdKenXpjfdExd/hXjUvGs/sK5heGXCIkae46jfLx7Clm8IwPL0d+8wtYpJIrdz+ZqI7Whkxpg+Y0ZWPgjHWhGm5CO+S87fv+/yVDwtnQo4J9eMozkKakqJxU1OUXNbYi5TB7jtbr/zsqqFcur4B3TkM4OQUdhLYiItSQi1hERseZFxFoWEasREWtul9br8IhYiyNiHRMR69iIWGsjYsXk18KIWDH1cU1ErJhyH9MWxuzHsYhYMfsxpv2Kya/rImItjYgVk18xdSimPxGTX6siYvXs6oGzqzF5vzoiVky5j8n7oyNixeR9zDbGtBOLImJ1q796UUQsPsyHc/QVRCdv2AzLW76Socy+kiGlqbCbCm9hnTi8ju2sZfxrWJzGFwMVjIN4Lwby9QOGyrCNWVg7c2LFujd+h6ddiD/iqYuqZ9ZpD6QT2ubzCEstH6gYUd6+m4mw6nmiLpHDqsaeEymf/fRRn2tn644MLEd/n0jfOoVVUQw2UxqGCvlQmYqcqy5uiPKneuicUZLOGYF01pWksy6QzoaSdDYE0llRks6KQDpXlqRzpaCjVt22AAavvCXvzfR94Mf/Hb6+tU6bIU2tHlk4v075r1s/Xe7I9a08QP6Mu9a0cUg7h+pscmLpyWOmCnUvr6lCPOf0EGv4w65dZosMscqsY/usrxPTGP4DmHy0GLmCqPit5totWg1qht9W0N/jVM4Ws/pd9mMcM7rHQ5rihGEqK3t8RjnkhRPf+kT+kLV2q3u/pzxiqNspuf32HTXsdEG7TvlPSAkmxzJ30dFQRQv5YTxlOcn61XWug+U/CerAv/yORzpVu1ibj6e/UbYunND0LwYrc9p6Td8J+tw+HB2yfv2ej6ha/rOAB3ZEt5/ycH3UN+QBls36G/Pij8zw30oWT6f8Gzu0nfvf8p/n6f/jRB3wglvmP9eB8xyVUYcLRR2E1dyy6457Mn4qvQ7vyspxL3FPHCdwsh7jRiKxJr3MHdYOpmN/KwlIWm6hpilX+rYde7J+Jp5HhBUZNPucfnyHfIdcqbEyeGw2/GGnJa/pgp4aW0+jx+3jZfn1oi4NkZalpZ3oJH1qd9emfXrtnl13ZnVp6KCtjAWXd1S2Jr4lTyLOdlWyDdQ45eIpj5oZ4jfflMfyKTpnlKRzRiCddSXprAuks6EknQ2BdFaUpLNC0GGsrCnE7el7nfLfCoadf7HzPKgHYyaPHTS1/CqyuEK0x/J3ihQxL7dAGkfAFG3kJQ+EO3PWVW3yxSjLjVRXFYUMres1M1zX80RdKzyIFDzkHKiDSPmmgyixzBVExW8119p6TOORhV3aSyZa/y4yHXwA0hQneDqIbXogoxxLNn/rE/nvJ6z7RTmruy+2iRgq1mwYqlzy99tFGZ8GhEhw8rAT80BErAcFVsnbQBaGaqbhD1NdimqmurlBHXGztj8s6tIQabxm8LCg87Cgo7DOj4i1JRJW8vBxwR5WD6uH1cM62LDUOu2DVA7HT5t9qNlB2d/wxvKWT9G5siSdKwUd348g8b9Gh78xHVVnaw+O3cy3vLc5YXm+nWozpDXT92S2+tvrNU2cyWJZu32xTvnPhvMsv7c+u43I533tmmiv85DRgLQcfs1oMpu+lG5xRB9nYGIaN0t/0Id7S/qufAk+PoZ9zbe2ZfXBF6kPtkCa6gOrD99Euhr64EvUB1j+AafpuQ70WEYGM/JvofpZ/i+LZQRVv50Z9JAfyOd3ZdD7qoiuKLkz2iXlbqGSO9RXlrtQvztUTo0nSk45YrNZYKEccMTGyg863QeGx7eb/p3o81A55361/N8K7NdI9kT2K/KK+1VF1tQ45JMD7C/jScO193lWJBKxsK9D+nWzwOd+/aGnX6089ivWk/vV8v9LYL8aL6voV+RVSL9ifu5XNX5jvxpPGq59nDyesJSN9kVYVb9iH7CNtvx9KWHVryrK7bPDU/kB80DZYeRVSL+qlYDQfmU7jP36Kkrz7YvcLOhUYaPHRJ+zz892Iat+im8lF/d4bfr+jGosEOUdla3RtwUZWIaTfMOwKrPcmjvodAiUWW75lwiWKzXF+igTZe0p+aMPwYsChj/s2kWiSOjR53ruq1j6r7q5gdVMLV5xP3WiE1FUk8dWC2qiWlzeEVZNfMM0Jaq4PmiiqrZDWlncDqlm2DxTUJYPRSArsprlXRhenfKv9YxCPi84edhaPyLyo2ds9VHtf4TSsNzODDo4OqLl59HR8m8MHB2NdhWjI/KIR8dHIa1f5Gd+PybyPwp5OKr0GKSxSiOPHyE6nUwHy7+SUzX7Vt74GS67vZ1mZSxfKBMPU5qazSlZwPuyk6cOaWUjJdgelgWfLiUP88YnO8ibhussJ6iXDxMdn11KHp8sYHTBomFDgI10mi7oOdroqNVnw8bhNUef3YJ1skcN1fZtmOqSk97UUN1P9Lh9PFTXRV0aIu1yeMc0pFMXdBTW4ohY10XEWhoRa25ErDURsRZExIrJr1URsWLK18KIWPMiYsWUiUZErFpErCURsWLKxBERsWLKxPyIWDHtakzdjimr3WpXY8pETPsVU4diykRMfi2KiBWTX4dHxIopqzHr1Ru3Dxy/YvqrMW10TB/grIhYqyJidatMxLQT3ToOxZzDxGzjkRGxenb1hWG/YvbjFRGxYvKrW21Ot/qFYxGxYupjzLE2Zj92q796fZfWK6ZdPToiVkw70a02Oma9YvK+W+3EqohYh8K8Nua4vaxL6xVzXhuzH2PqY8w5TMy4b0ysmDLBOlRL/8Y8J8H7iZCO+e2HokquFW/ntVjDQOyBgtg1wnOutZ6O8EcEPavXcEZa0/mfH97yudFP/8wNn6xReasLf+P9CYMiv1rTNl4dBuVz8OpmtYfDaFtaHdIGKG0A0qwOyb9rqX6DBesXwj/Eb4j8fCottC/GXLsemRzZvpgHII1PST0g6Dwg6DRE+Qc8dDaUpLNB0GEs3CuGp6X5vhDLf2JqF9R9IWoPzAZRP8vvO32C9VG84ZNN6jR8iH3AejVEHc4gOg9FpJO11yr5++GIdNQpdrXvriwd3FfFP3j2aEQ6uEdrBdF5LCId3Bd4HNF5X0Q674M8eG1u8vf7IQ339lo9Hhf1MFv8BHzPYYvrIe1A/GGqS056U/u7niB63D7e3/WkqEtDpN0N75iGdJ4UdBTWqRGxrG9HXXtf84+Zvl/Qeb+HzrmBdDaVpLNJ0BkR5crqiOKN0XkiIh3UmU1E58mIdFAOmkTnqYh0noI8JxGd+0UdEn/gNSdMf0/++wCk9VPZ5LGT+HXKf++Z0+VuTzFNBtFWYB2xPPpjj4t2ML07ac7yNJTJYY9a4s6OsDrxbg/x7nFIC+Gd5d8OvHsD8Q7bxbr9QUh7gtI+BGlPUtokpCEGpjloA35jmcPylm9ElOPxai98z9FfAyG6gfjDrr3NRcarvUQP2548PHf7cDF6daP3jKA3KejNdZqnSN+wTMeUnX2a0tA2TlIa2rMPURrq94nwjphZbbpsYv+/auxi+cb6PUhp6NM/RGnoh/N5CPSd+SwOtpn9W2vzAOEkj81T65T3/SdMl3kkfVf2hu344wLb0j4g0hL8405qbQvaFOQjpiVPv/jmG0OfzsCqu/Y5X/KwPbT8v0S2HW1MDl261fjyIfjIdmiyIHaoHZpM30cEPauXslEh8ahHj/nuvI/f8u9/ntd2+2za1SJ/SZsm41FGW8WjJiltANKsDioeVXBMuTmEf4jfEGn3wnuevmiINL5rtSgW28KyWA8XxLKYG/ok7Heoc204XvDY8KCnXk93wLqGsLA827APdsDim6meFm30zV1K2rhgf8jwh1273S7iD3XiC8/fVd83RBrL64cEnQ8JOgrr4YhYT0fEqiKeqfybi6nOKgb7kKfOF4s6q7jpxdQe9AGb6fu+s68n6PrgfAnnw9dO7P+3TvmvgfnSl2i+hLR9fiHHXPLefnZuIJ1rS9K5VtCpOg7OMZenI9JBPbqW6HwwIh20p02i86GIdFCv2Vd/SNQhkdlvkB5MQlq/KPuO9L1O+f/xjOly/8ejB1hHLI8xFxU7YnrfI798L5QpG3MxrE68+wHxDudeyqbxHMPy/xnw7ofEO6TNuo18eprSJiHtg5SGvOIYmKU5aAN+88X5mG9Yzvhb0n8P9jEMf9iVko8pH+PDRA/bnjw8P3mmGL2pmMuzgp7qB4y5qDgLYnHMRcUmlG3cS2kqzqZsEMdcHurQJp9fzeufOF4nf2PMn+Mclve3Qc9mpwvEan31+onWNJTx9wPd0Q2t9VUx0BqlOeeP2alYBvvuMcYmFZtlHy2vX4nlORb3QUGHx3S2r0s36PqgfUV/gH00y//z0O/LqM/UHEn1J/toefvz3EA615akc62gU7VPwz5aVT4N+2iTEelMQp4m0dkbkc5eyMM+2hOiDonMbiQ9+DCk9Yuy7KNZ/heDHpzs0QOsI5ZHH+1p0Q6md0ZKo+SYKH00w+rEu7OId09Dmi+GwnHgk4F35+awITgmf4jSkB+TlPYspCEGpjloA35jmcPylm9ElDP+Wn89B9+r8NEMf9i1t7mIj/Yc0cO2Jw/7aB8pRm/KR3te0FP9gD4a8hTpGxb7aGhneV0MbeOzlDYJac9Q2l5IYx/tgx3axD6akn3Gwj2+ys+qU/4bUv1KdO068tPUGk+S7y8pXwXrLMH7kybT92HX3k9F5HqS6HH7OL65V9RF9f3b4B3TkM5eQUdhPRkRi+eyKGPsh+VdIzw3kM6mknQ2CTpVx7DYD5uMSGcS8mwiOnsj0kE5aBKdD0ekg2Mi+2EqXpfYmLvJl3gG0pRvzr6E5f/T06fL3UO+BNoKHvd57wTnZz/M8r+F/LCC46z0w9ifyOLdRMBczsc7y/+rwLu3e3jHuh3qa+2lNByvEQPTHLQBv7HMYXnLNyLK8XhV0E8J9sMMf9i1t7nIePURoodtTx72w54vRm/KD/uooKf6Af0w5XshFvthaGc5tjEJac9R2l5IYx8N9Zv9sA91aJPPD/tQBlaoH2b5nyK7MQm4Ze3GZPre89fC/bV74R3TkM5eQUdhlY37I1bPX5umw996/locOkX8tV+P5K+9FHyO/zoD/tpvd4G/9ruR/LWzgXd/4FkvYd1GPk1SGvpReykNecXjYN64mYqvHCpxMzVeHUxxMxWXUraRfbK9kMZxM5+/FiNuFhrjYppZft0NE63plv/rEF/7a4qbqf3YSb5Xb2zN1/PXWsseTPE13/kF9tfUOYknPHTODaSzqSSdTYJO1efy2F+r6lzeJqIzGZHOJORpEp29EemgvIX6a7WN09/R3ob6HJb/L0+bLldPMZVfgXXE8qH+2tQeo5TGTKxzZvFuNvGuqL/2OeDdqId3rNs4NvIZv9465/6nt86Z7a+hneX4GtrGWOucT3ZoE/trWL8nM7BC/TDLv4bsRkE/RtoNw/LdHzIk2lOFv2b4w1SXovKv+k6dHVDnPaysmuPdC++YhnRCz1U8FRGr569N0+Fv3eivVXWPQpPozNTZgSyf4wLyOSYhLcTnsPzbwOe4mHwOpB1yduCDoh1M7wqyu3uhTFm7a1idzg5cRbz7IKQpm8a8s/znA++uId4hbdZt5JPvToanKA15xft9LM25sDkplme+YTker9DPq8Jfm4mzA777GgrOH2b07ADaWT47gLZxL6WhPZukNN/ZgSc6tIn9NSX7KsaF5wg4xuU7I1vQZxoNlUH2mcqekVU+kxqvk58BXp2+pz8DfNGOPVffdfNtO2+5bMc9uze/bvvV2+7cs3PbbZu3b79zx+7dWGkkNAe+Yzo+nMfeHxbfEeOpDo1hYcDOYses0+FhPqCN5dkAfqgDFh/QVoMb/z3g2utpB1z6AnBQ0bLqdS3VSy2++Iy82nyuBpO9hPXhDljvJiwsz4uLGCziejK/fDhZBhTr9R6qlzKYhvVcB6w3ERaWf46wPtIB66cJS03C+e8B115P5pcPJ/nv+Q71+hmqV9bmm+S/j3bA2kNYavOOYX2sA9ZuwsLyWBb/HnDt9WR++XCS/z7eoV5voXp9DNI+TmlYjn+YO+8kDcvP1CRtJ9H5eEQ6H4c8TSiX/P0JSEPb6jssZYP/J+F7FQETwx+muuSkNzX4f5Locfs4YPIpUZeGSONA2KcEnU8JOgrrqYhYn6D2ZE3CnqdJ2JOQFjIJs/zrYRL2cZqEIY8+Tm1UfsyTgl6N2jUo8iNenfL/XFqn5KKii9LLk5WOPJVRFxwzk8cX6Bhy7fpVhY4Y/rBrl58iOvIJosftYx35pKhLQ6Rx0ELp4icFHYU1GRHrSWpPlo58NpKOLAId+a0u1JHfj6Aj6EOF6EjBhadgHeGFp7I6onxZn458QtSlIdLQf87SxU8IOgrr2YhYoTryp5F05D9PnS73/1aoI8bvUB2x/H8ZQUfQbw7RkTLBMMSz+uA3xI+lI88QvU468qyoS0Ok4ZwJ05COb3EcsZ6PiBWqI9+OpCPfBB35XhfqyA9z6oiqexVzLxW/ugDes3ikZLchyj9FaU8IOp1k5D826vooGUnebf7edqESyEjtxNb2Kz4fyIXVrSXpbBV0ZnphtaoFz61E55mIdHBcaRKdZyPSQVsZeinbohOnvyf/PQdpSg8sXlSn/G8APVjq0YOsmCUurD4p2sH0jkpplNx4JBdWDasT75rEu6LjzI3Au5U5bAj69GzjkR/PUBqOyRz3VfFV/MYyh+Ut34goZ/y1/sK4ZRULq4Y/7NrbXMTXCj34ae37eDF6Uwurai6h+gEXVpGnSN+wfAurvFkJbePzlIb27COUhvodshEO2xSyEc63wWZI1L0KP97wh127jhaRrU7+Ivvxz4i6qL55L7xjGtJ5RtBRWE9ExLI1ht4ms/Zv3eALbSI6h4ovdH0OXyh5eDy3/P9+ynS5l86AL/SKLvCFXhnJF/or4N0tPV/I9xw0vtDHitGb8oXUGnYeX0itab8QfKF+UT/Mh7qn4klOfKt56DGNPlH2Z11rvTFtO9HIGwPaLupbYVy3P1S/Dpa4Lq+hl4nFhvg8B+rQRxUbGLfDt0ibaPt9/eC78LvgWl6f0fPt7UJ6iT0ddO19iO3N2kP2EcC3b1k6X3Q/5TMdsHz7KXkd8NkOWLyfUvGA4/MfS41+YoefOLE1z4fTPE9DnqfSd3U4H/2p5ymfuvyk5IUewbpn+MNUl6K6p/pBHThMZPMw55cR7KOsfaZ7RVtCZBbrFCKzeftUbSpP8n3Ck+9DIp+ilfyN+54Ng33xT6cYCZ9fubW1jUiX9ybn/cGdD4q6KDrnlqRzbiCdTSXpbBJ0fIcjQ3RN0VG8MTpV/bj6JqLzQvvB4KzLvX+P5rfq0Lvvcm/L/1aY3/43mt+iHmQd6gw9gGb5v0CxgUkoUzY2MJm+d+LdF4l36gCaj3eW/2bg3Zc8vGPdVj+Ops4M8OG0vZDGe+sszUEb8Jvv0KPlO1QOoPkueCroO8/oATQ11inbuJfS0J5NUprvB4Mf7tAm3wE0K5scrjoqfZ8+XHXZjnuu33bbzu3b9uzc9bprdrz+rh2799QBmaljK5zTlhivhsp6avR3H6U9ROl4ykE9IVcNFLziINjz5Z+xLXvVgDrR5btqYFLURV1VcR+8YxrSmRR0FNbTEbH45yt6V3lm0/Fd5VnVT+1sIjpVXQHQJDqTEelMQp5QT2/wpOnvaA9DvRXL3w/eyjD9FDmOGpOulZ5ho6f3sGhHnfKPpgklo27S0wvdeTk3gHe+VSDL/3cnT5ebT7xD2qzbyCe2L+raHzVj55/PVdFAtTqvPIIZ2LUQ7OnNxK4F9B3Y09tbjN6Up6c8S9UP6Ompn4xELN9VnnzVgLrGwneFjrJBIZ4etinE0zPZul/QsbTHIe1BSvuAaHOid8d59O6R9L1OtDeTDUJdyNHn54wQHcNA7IJR/nNC9SVrhQPrpVYc6gF1Oenrv7Ow/1XbP8Y23+rC3/oAP8smXSbyl7QtZ44YjYnp8mjTkqcOaU9Q2gCkWR2SaOJaql9BW3RmCP+UvmL+Cyem8+XpC7VyjDqSB2vMtcoV6o7pH+r3o+l7yDyooA4Gz4MMP9Y8SNlE3zxI8awh0t4G72xb+sW3Pg/W/RGxzDarfuZ50P2Czv0eOueKOis6m0rS2STojIhytYx/jQ5/YzqKNzMd8X4kIh2UgybReTQinUchD8+DHhR1SMb/beTL4ypUP5VNHvblLf+7wZff7vEpsI5YHudBD4l2ML2dMzgPyuLda4l36FeF8M7yvwZ49zoP71i3cUzicQT58QilZe0kwjTnwnbrYPk8u3XQB69iHmT4sXbrqJiRGuOtfQVv2JiaB6k4oeoHnAdl/XQmryopO8vzILSNvPsc7Rn7XKjfIT/Xjm3ieZCqX88XCveF7oV3TEM6of7L+yNi+XyUni/USqfnC7lCdIr4Qnsj+UKzYTx/dgZ8oY91gS/0iUi+0HdPmi73aeId0mbdVjEz5SexL4S84nl93pgwlj/UYsJqvCrp6035QupGzTwxYeUX+XyhBylNxfqVPeOYsM8XerBDm3y+EJbFvwdE3gegvZj390DP/v6kbFqPuda0ByDtfZQWqp+IgfzNOo1+O7XB8v+PtN5JrPGWrRqzz/nXpFTs09oxZHQhLYf8/lZSr0u3TtNBeUmegYnWOuP45/OpLP9jIj/KHPuGj0Ea+3NKHtG/MHlU/LI6VsEvrEMIv9TaVCi/WO+RX48TlvJ/kYc+flkdq+AX1iGEX5g/L7+MB4pfHyCsTnOcy6iuhj3otE0wvDrl/ybYBL4tx2fjHxDYaBtrhIHtWC/aMUJpWDbBffm6/e8zFedhXxN/BpBlAXHrlP+fYNwYOrkVs9PN1yxfKsaBcYsHqT0hP0mNWA95aE+K/B/y0MZ6YVmmzfXEn2LcR2tiOs14U9IODCg7gPEqtgOqn9T+Jx+vVD+ptXDesxYac3qa0kJjTnjDE8unij9l2WzWB5zP8Fwn9OeDalRHzI96zLKnYqxK/9luoP6z3UAZZbuBfct2o+gO9UVpX1S5Q53lu+60fGftPF8H8/alGbZtICfmshQn0dGzQEeTR623l7QFdWULUN/ZFvhscPLktZust5OQxmsNat0ceco+gfFoUORHPD7hdDT0gc8n8O369sXAffM+04dEbi5N68ExgeS9CfmOJ9lTt9apmwb51rorQJ43pu8x7cajlOY72aLGHCVnauc8/5yx7yb1gvvBg2MpvB+87E3qoes8MX4KOflvr6Cn+gFjKZ1OVdpYMNN2DfkUYtfUWlPI3j60EWwH1F5UthGKHtoI9MUvJd1XNjLUZ8H49V6K8aB+sf6jjrP+o7yz34A8ZL9hEuqifB7+6XHLvxVs2K3EGyXLPj/2wyL/Xsjj+9myDwdgPeWh/YzI/2EPbawXlmXaWTqpdNF4U8V8YxIzTEzjZvUT5g/hleondTvLhyktVHcnKQ3Hd9ZrlG08IXprxriN7VAxXuUP4Jh/PI3dB0us4PWgu+/oxQraaHM9e7GC1rSZjBW8o6JYwWt7sYLcsYKHD4JYwUfBtj0WKVbweC9WMJV2oGIFz3RJrOD3A2MFH48UK/hDkOdP9WIFvqcXKyB6vVjBgYkV/H5FsYJtB2ms4H+CDfubXqygjXaWTvZiBfl0d5LSisQK/qaiWMHHaexW8yQ1V+Bz9E+Keit7MOla27EX6qL2bXCswPJ/B3TXndKKqfTHFyvopD98c5TSHx+Wb4/RsyL/Mx7aWC++GZ11Getp5WY6VrAXM0xM43aymckTwivVTw3Kj7xRZ/p53xuOQ3spDcchthWTkIY6xvIZurdJ3auBe43mVhwr4NvU1ZxF6T/bDeVvK11iu4F9O0l1t/7EWAHm51iB5R9N+6LkTagyVsA39+N9Ekq+eW5l+VfBHTFjGbZtICfmghTnQMYKUN/ZFvhscPLktZust9g3fJdL6M1qrGeDTvsQvNfQ8i+HPuBYAdoj9jPU3FfZI7Zjk5CGsYLz0np0ihWsIdkrGiu4AOT52PQ9pt2YpDS0AxwrUGOOkjMVK8AxlMuZHSh5g2FwrMDwY92wrPTPFysoc4N08t9zgp7qB4wVIE/VDePdGCvoxFeeu2MbWZ/RRrAdQBvB9uNDHnqTUG6vtcFN2wifjVQ3tKt7cdBnGfTEClj/UcdZ/1He2W9AHk661nY8C3VRPg+O2Zj/crBhNxFvlCzvhW88dqmb9p+DPDxf9/0Kr8LyxQrUr9d8xEMb68W/VvMR+lvppNJF400V8w30C1gXVT+pX7bw8Ur1U4PyI2/y6u6zlIbjO+v1JKSZzCv5jBUrWENjd9W3K2eN3erORcRl33cn6O5PEW+UfVY3E7P9wPxob3jOpObrPizf+phPfhVtrBeWZdpcTyundNd4U4XuxpwfKF6pfmq4dr1mHQy96Zn1M/Sm573pu5LPTvtefOMurivzbeuTAtcne3tF/knIw7KnbjZX+u+LrbHd8MW0sW/ZbvAN3pyfYwWW/2coVoAykkPWZazgOaojxjOUfPPcyvJPgm27L8O2DeTEfDAwVjCZfqvCp0Z9Z1vgs8HJk9dust5i34TsBUOecqxgMv0+6HTMEve8YP6nPLECtEcc1wy9eZ73Tqlfv0jk5rMUK5iEfE3I92GSPbRpbC+Sh2XP8v8WyPNz5G8g7aJ2g+OWKmbE+uOcX84aojyOoVzO7EDJuXRwrIB/jalgbML7a0x74RvHCgrazalYgZrjqH7AWEGnXyDzxQom3XT99+WdKFb/vOshnfjKc3dsI+sz2gi2A2gj2H486aGnYmFoI3w2MtRnwTXP36Nfc0H98q2Lsf6jvPvm1uw3PAd1UT4PjtmY/7+BDfsq8UbJss+P7TRfn6T2qPm6D2uvh/ZHRf7nPbSxXliWaWfppNJF400V8w30C1gXfTGa5AnhleqnBuVH3uTV3ecoTf0ao9JdjIF9NWPcxnZMwjfW3UlRV/QHVJy/il9p5rn1R6EuvBbK4wDm/1vQ3f9LvLFfDHYuTCbULxTjrw6zDUOZ+HgA1pMe2p8Q+T/uoY31wrJMm+tp5ZTuGm+q0F3UN9Zd1U+YP4RXqp8alB95Y2mhvxj9UUrDMcr3i9Em80o+O63/+/YV4C9B8q+2K1vok71OYxbLnhqzlP6z3UD9Z7uBMsp2A/uW7Qb/Ejjn51iB5R88df+/5n+ijOSQdRkrQCysD8YKUL55bmX5l6V1TPp4+FSNOZATcyTF6RQrsH6swqdGfWdb4LPByZPXbrLeYt9wTEfFHZCnHCswHg2K/IhXp/yLoQ84VoD26GNU99BfsGc/A3UGYwVnpvUYce2624R8R5HsoU1je5E8LHuW/xyQ5/H0PabdeJbS0A6wb63GHCVnaq0Ix1AuZ3bA7ArKYhWxAsMfdu1tLhIrUPqH4wPHCgrazalYwScFPdUPGCtAniJ9w/LFCqq0a8inELuG+Xnujm1kfUYbwXYAbQTbj2c89NBGoC9+Jum+spGhPgvOz6+nWAHqF+s/6jjrP8o7+w3IQ/YbPgF1UT4PjtmY/3ywYTcQb5Qs+/zYT4n8n4Q8H6H2oKx/KgDreQ/tT4v8n/LQxnphWaadpZNKF403Vcw30C9gXVT9hPlDeKX6qUH5kTd5dfcTlIbjO+s1yrbJvJJPn5+fPKy7HxF1RX/gYIsVbAPd3UO8UfbZFyvIO19HG/aJACzffM0nv4o21gvLMm2up5XrpliB6iefjVW8Uv3UcO16zTo4k7ECls9YsYLmCzxWEDLmY6wA83OswPK/jWIFKCNlYwWfpDpiPCNkXm/5Hwfb9s4M2xYaK7D87+mCWAHqO9sCnw1Onrx2k/UW++ZAxQoeCYwVcFwzdqzgM4GxgicjxQp+DeT56RmIFaAd4FiBGnOUnKlYAY6hXM7sQMm5dHCswPCHXXubi8QKlP75YgUF7eZUrEDNcVQ/YKxAzUUQqxtjBZ34ynN3FdPMO99g+1EkVvCZimIFiyLFClDe2W9AHrLf8Emoi/J5cMzG/J8DG/bHxBslyz4/NsZ83YflixX8nMj/aQ9trBeWZdpZOjnTsQL0C1gXfTGa5AnhleqnBuVH3uTV3U9SGo7vrNco2xgD++OKYgXsD3T6bSH2m9QeK9/8pNPeUZ6fKF9I7TV6IoMO2gTsk7ek77zX6K8CfWqjXVLeR6veR9NpPshnZ9B2854X5DGeR+KxAc+4/MfGtKGuVTbY3iM9rKuaJ7PsZf1GCe8ns/zfET67T55957/yyjO2oaw8o27sprZa/h/OrDzPOdDyzDKL8pz1+/RIs+babViZeM63u1D+66ft//dQkP/Z0NZulH81l/DJf6cYCcs/+m8HQv7/NIf8f8JDU8m/tS1L/jGeiPmP8Mi/4q9P/jutEfrk/1OUhuWeyKCD8o/9zvJv+VcEyr/RrkL+kUcs/755U/LknevwmgD67z755/XaWPL/2Rzy7/O9lfxbW7Pk3/A4Xn6iR/6VDvrOMeZd68I2fJLSsNwTGXSy/HmWf8t/RqD8G+0q5D/m/LVTnIH9edQNn/zzOkcs+X+e5B/PuHNsaFJg+M6x++6usHY8A3VROmK4fGbzstOmy73itFZM5SNNwrcq5rw+LJ9+drobg2mruzG4Lk7U08pVeP5roOpzrYpXqp8alB95o3SLz7iHnivZS2nq7goln+qMe6ju4hn3qza24u7tgJv3Dle+g2ZStE/pv+9OiJBz7ErW2W7gep8T+Xkt2vLflvaFrW+gjOSQdbkWzXfV4Dl8Jd+8dmf53wa2bVeGbRvIiXln4Dhr/VjFmk3Mu2o62U3WW3U2rUZ/I5Zav2E9G3R6rmt4fNb7zcKvU/aI7+NQ9zUpezRJaagzuBY9mdaDz+gm703I9w6SvaJ3MT4D8vzu9D2m3eD7sNRdB74xR8lZQ5THMZTLmR0oeQY8eC3a8Idde5uLrEUr/VPndEvazam1aBUnVP2Aa9HIU7Ve4luL3gv135d3olj9897j04mvvDaMbZx0rWloI3x377D9CL2rH33xSdL9Sdfejg8KXP5dCSyb4F5A8w3UL999TiHn2NWeOfYbPgJ1UT4PjtmY/+Ngw/4r8UbJss+P7XTOfC+1R50z92H5ztf7zooq2urcDtfFuWydVLpovKlivoF+AetipzXZEF6pfmpQfuRNXt3l9W11jl3pLsbf/2vGuI3t2AvfWHf3irqiP6DuvCo6dk9SGuo11oPbyDYIcdnn/wPQ3a8Qb2LfT8FzJrV/14flu4uvk91g2r37KVrzq34KuZ9C3deidJdjDJOQxvORvZCGczqWz06/KeYbd/FumdkUK1BrmWXugfTdV8t7RbEc2w3Uf9/drJOUhn27l+rO/iHn51iB5f8mxQpQRnLIuowV8DiOZ26UfPPcyvL/B9i2v8+wbQM5Mb8bGCuINI7Xqx7HO9lN1lvsG54/qrEUecqxAuPRoNNxCr5/2fL/a2CsgP0F3zxgUtBV9ghjBctO3//O8dzkvQn53Omt7S4ap1p+OpRL32Pajb2UhnaA962qMUfJmdobiGMolzM7YHYFZbGKWIHhD7v2NheJFYTO3UvazalYgfLDVT9grAB5qu7v8cUKqrRrvhhoJ77y3B3byPocGk9k+zHpobcXyqEvvox0X9nIUJ8F5xs1ihWo/UdKx1n/fffHqfkcjxtZe5qyzsmuARt2BvEm9p1az1B78t6p5Yuxdzqjy7R7d2q15lf9pM6c+O7U8ukuxxgmIY31ei+k4f7yMzLGbWyHWgtR/gCO+Y7GbvW7xkXjAUrn2U9Tvq/63QH2fbeA7l5PvIkd5wuZr/uwfPO1TnE+pt2L87XmV/0UEufD373gWMEkpPn0k3UeZRvHXZbPWLGC393Qiqtsgk/2Ou2nYdl7RrRP6T/bjbzxACXrbDesPzFWgPk5VmD5t6d9Yf5nwXukZKzgY1RHjGco+c46E/xGsG23Zti2gZyYr0lxZmj/du6zoD4bnDx57SbrrRrja/Q3YqkzYKxng855z07wnPku6APf7+xxXHMS0jgGslfQVfYIYwWPU6wAdbcJ+X6KZE/F9dHmsOxZ/qdAnt9K/kYMu8F7nFTMyDfmKDlT67w4hnI5swMl59LBsQLDH3btbS4SK1D6p+Y7Je3mVKwg9P49jBWouQhi+WIFVdo133pIJ77y3F3d+aJshG8Ng+3HXg89tBHoiz9Ouq9sZKjPgvsVfj31WZSOs/7njQeouTX7Deo+WbRBOGZj/g+DDftl4o2SZZ8f22m+zuswar7uw/LFKTqdM/DdF9LpTi2lkxXeNyHnGzHv3O10pxb7/747tUJ1l++82wtprNco2xgD++WMcRvboeKVyh/AMf+nDtJYwW+C7n6pFytoo8317MUKWtNmMlbwpYpiBRO9WEHuWMFfHwSxgn8G2/Y3kWIFf9eLFUylHahYwQ+6JFaw4Iz9751iBf83Uqxg8RnT5f69FyvwPb1YAdHrxQoOTKzAbITPRhaJFdx9kMYKjgIbtpF404sVZOtkL1aQT3djxApYPmPFCv4vjd3YJt8eZD4jmDeOUBN1sXbgfg32uyz/WaC7VxJvYp9B8O2NCjmD8LSHdqc4BdPunUFoza/6KeQMAo5lT1OaOgdU5gwCy+fToh2hv2/7NOCeRbECNZ77ZK/TGQTfGSTfGQS2G+regQN1BuHlaV+U9OkrPYNwJ9i2mzJs20BOzJtTnN4ZhAN3BuF26AOOFaA94jgH2qMYZxAepFgB6m4T8u0h2St6BuERkOc3pO8x7cZeSuudQQim1zuD4MrbtZk6g6DW0JSNiHEG4UHSfWUjQ30WPIOwkWIFvrUJ1HHW/5k+g/Ak2LBPEW96ZxCydbJ3BiGf7sY4g/CpjHEb24HjdugZBPYH1Jrn0wK3RvXF/GhD8t6nxrHFSUjz3af2wQw6aBOwT96Rvtcp/68G+tRGu6S8Dyp5992Vo+aDvjhIp/kgr6mj7Z6kNHUGzeqs1ukT3i+l+WwtTcM53knwfiKkY/4/ozketjMHv68YgTIOMBC7XhC7RnjOaT8PfRpFL3mGRVo9oC7r3vKG9cvvGdhQo/JWF/7G8jIg8t8i8huvBqnuTRf0XKZ0ymhbWh3S2A9EvbA6JLq0luo3ULB+IfxD/IbIf9XEdL48fTHmWmUB5d1sH9558yClTUIa29O9kBYSC2a7g/Y05A7avwQf6/sBY9gkfMu7D6bsHbS+O9J9cU1FW80xuS7OZY/NvTtoW2Ub+0et1bDfhmPVXkrLuoOW5TP0d4Q6/X7MD05oxd0rcH2y18lnYtmbFO1T+s92A/Xft6c0JKbDeoY2E/Nn3UH7HzTeF4yFVHoH7YIz9/+b9HHtTI2ZN65WT3FmyP/s3UHr2u+gbUAfcEwX7RHP+dAe+eI8k5SWdQftiWk9Ot1Bu4hkT819rGzyZN1BewrI89L0Pabd6N1B27uDdh94+u8L9Q5atBFsB9BGsP34oIde1h20J5LuT7r2doT6LJOA+43UZ1E6zvqPOs76nzcWzOOGsmE8ZmP+s8GGXUW8iX3eZC+1p3cHrXwOqjtoQ3WX47ahsWBcj7kqY9zGduyFb6y7e0VdlT/wkMBV913XXLsdConp+s7JIC21H419Aiz3YAadrBjEO9L3OuW/MdCnNtpVxHSRRyzvk5DWL/Izv/eK/JOQh+fXKCe8Lwp5bDStzk8JzIT3X6Sx4XHI937XmvYBSOO9RygHfB+Zkh+fHNwv2shy8FoYG94SMG5+AL7l7YP7qT1oA/YGYD3uod0pHsC0JyENyzJtrqeVU7pivKlibIipK4pXk5DHeKXmEXsp7f2Q9jilhd5/zPqHso2/W8Ty+bhox/3wjceG+0Vd9633USxK7Vv0yZ4aG1CPWfY+INqn9J/thu831lBG2W5MQhrbDetPjEVhfo5FWf6fTfvC5jcoIzlkXcaieN47CXVQ8s1zd8v/YbBtD2TYtoGcmA8HjpvWj1XM2SYhA9uCvZDWL/LntZust9g3HyCsDwgs5Cn7VMajQafXow2vTvmf9sSi0B5NUt1Df7vtA5SGOoOxqM9RLAp1twn5niXZQ5vG9iJ5WPYs/++APD9PsagYdoN90klI470EluacX858sT4lz2YHzK6gLFYRizL8Ydfe5iKxqL1ED9uePByLKmg3p2JRzwh6k4IexqKQp0jfsHyxqCrtGvIpxK75YkPYRtZntBFsB9BGTFLakx56aCPQF/8c6b6ykaE+ywcA9zU030D9Yv33/d7KJKSF/DYrjxvKhvGYjfk/DzbsL4k3SpbL/LYEx91UPNyH5fv91U7r7r6YP691cyxe6aTSReNNFfONmPutFK9UP6k4MseNQnWX41Q4vk9SmvptViWfPj8/eVh31RlD9AdMNnZAvuNca9pOSFvhWutzv6gP5j+D8j+Q/j2Ykd/w6pT/74S/NUp5kvd1GfSwfviNfQQs/0AGFtobbN+rM+r+beGvG+aDon7rRP0sv4oZYqzI6qN485DTtLPiNfy755b/HwLnHyZTJW2D/N1z5BvbBh+Pkod5+rDIj7ziWMTDkPYApR0HaQ9SGurOTqrDDlGHM+Ab6zXKnZVN+vFX0gpY/2+BfN2o1/Wz9v/bSa9fkUEP6+fTayyfV6/3ZNR9FtQ9RK9fIerXTXo9V7RH6bXJVE+vO+v1FlGHUL22svvG6+NacR+DtH5RD+5jy7/cI7PvE3XdCd+Yv+8X+d8Heaw+o1QHLDsqyj1CaehvbaE6PC74gPlZdy3/0cCHWzyybvUqKesjStYxnsuyjut6IfHfJ0V+9EWNJ8oXfYywHhNY2NccQzMeDTrdB4ZXp/wnCttv9XsEynNMf0vOuq8QdR9x7TqDOnVzumF9VOTj8eNRQdM3thqdrLHS8Fh3zxb8qhEN1AOs1+UTrZiW/0Uee6B4iX4By6CyH4+Jdimevo/SHoU0kwWln5avirEI28/66Wtr8uS1ldb/ao65gtJQN1j+Vwg6aMNZ/pWcJjL04rWtuGq82QxlX5O+s8y+OOd4g2N8Xh5affKONw9TGvL+EapDp/HmdtfKB8v/0pkdbzb3xpv28Wa7Z7xB34/Hm0dy1n2zqPuIa9cZ1KmPHbv/3WRQ+ak1qo+iyWXRRg5m5De8OuV/nWe8wX0n/a6dTyOEaflf77EHvnE0eVgGFe/VuKF4+hilYd1NFpR+Wr6S+nme0k9sP+unr63Jk3cstv5vuHZ7yPuUUDceJTpqThYq/yhDjx/bivswpCmZvTV9r1P+t3vkS+mNihn45BHlxOoz6rL5pOSL9+kiT8+jOqhxF/NzzNHyvzdwvIkkz/MOtP9kPFH+08OEpeIC2Nc83hiPBp3uA8OrU/73ecYbjO08RnU/L2fdN4u6K31DnbqDxhuc0/B449NxLot0ssYbw2PdnfSMNypGh/acxxvL/4zHHihe+sYbZT8eFu1SPPWNRSYLSj8tX0n9nK/0E9vP+ulra/IUtZUN164/HGtD3WD5V3HfUPlHGbqJxhuOdyMWykWN6pgVY52dvnOM9TMeeew0lhaNb466bL6Oirobn5Q8Wr6S8ni9kkdsP8ujr63Jk1dXeb6txmdL88XafeskyeObb1vZRIYuOLY133GAUUv/tb0zuEaZg+d9NcKzOuM3xB+muuSkN7UfaR3R4/ZZ3yU6My99v2vPztt27rnn8l3btm/Zdsfuu27b0YfQrj2qhlxBVPxWc62tx7R++jaL8l080fq39Wy/y36MY0Z3PaQpThimaSW2aX1GOeSFE9/6RP51hLVOlLO693vKIwaWY4mp0Xe0miOCdp3y/ylYzdu2ZtMdce18GKG/7xT0KtS6sUND6+YSquXBvPjMhZph/ln0N/eoxbFDtI5j3V9PpSiRvq+l79bzR0FZ219raeOAbXfH7DvPdXZrvhVUB/Uv1h2/8fgVw1Lw+mTybKVy66HcjQF1WC/q3BDlLd+IKFeUNw1PnY0OWpNm+p701ffOmv6e/Hc8pClLxOunlv/ms6fL/UOKabxEjbU6Kj7zXoa8fH6FoFM1n19BdI6PSOd4yNOE9+S/jYTFfLZ+Mj5vgLSNVO5USMN8OMpthO+nCtoK3zA6yWD/2bptWTJotOqU/yKQwcGzW9uvRlMefZ3zyzzL5WBG/uOofpZ/dlonNY+fuifMabvG65SWfxQwz8rAdM5vK33tQpkayWjXPNEutQfEyqux5URKG4c0s+E4ttQJY2n6fci190cOL0GeecqqN+YzuiuK0Q2egxj+sGvnYRFvSK2LYvuKeUPIfeYKouK3mmttPaZ1moNcMdH6d5E5iLICRwlMtUp/XEY51kL+1ifyryAspUFsnVV5xMByLDGqXPL3bFEmRAMK+uf9oRpg+LE0oFO/m6xa29eJuqhd0rPgHdOQjtrRrLDGCWs8sM5JH85P31OtvXbPrjt3pGrr6Ok06ViRUY0+Ud5RWVZtduyPEk1C1eHBymhnDcKGV6f8p4rBylfeuTCxxy6qwvAbfiyxDxUhtSHMyvoG+Zpr78MZEtXksRGhJqrF5R1h1cS35FG+5BCVmykxvsDjcw2J8onvNDLWSruTn81zPct/qcfnVHMDFV2x/KeL/DgfmfJzqQ5YdlSU43nm6ZB2PNXhDMEHzL/HtfLB8l8DfPCtJVu9qtgri3umByZcS7vOgbR+kf//b+9NoC07qvPguv0G+qmf+iEG8xPj6GFgwY8ZJSBi6NZrzUhIarrFJBBoaglhsIQGGyFH/xMigAM/QtBSd7+e7utWj5onJAEmcTA4Bid2DLEtFgmGyCaGBAeH2CuJMcnpPvvd7373q33qTK+74Z61evV9p3btvatq7127dlXtw2OxSsCvABjrkymC53HBvxEXjjXrgfXReNBjYPhGCf4CRw9wnf5q4v0lJXlXOqzWtX06RWtQpMlT6cscmkpmjU7MbsTWyJc7a1AV+0G+eA1q8O9x7IEXp8gelkFlP14u2qX69FVUhjEJjAcdwD07iLONs7LYftZPr63ZU9VWToW4zVO6wfL/EkEnVf5Rhji2iHuJhnepwGvwfD6PYRbGi+D/KcjjCWQTng084PlprG/lIfTcu9uI9+mQ9CS7d4Z/gngpSW/BvUs9F1duXc/eDvYKYsV3ndDfeiwr8uJOn+3/u8q6Xp2oUqea1Ono2yP1WHL53RIBfxvhuk3UM95HnPqIA+uxxLAWxU6kxrTok6BFvLeIdPFEAfNif79a0DOtu51gQ+hp3QZq03RIet6aqnWGf4J4qap13mm87KmmdXy22qi8hbAaDMLi8xbgDOF5mc+jt07U48d6jM9b7oGY/Ebyh1Bi2R9S56aU/VJLUD5jinSeU5POcwQdk+QJKOO90mWird6+iJXhORrbY7WyW0S7+L6ownmrg/PToiwbuxet6IdDa9SJ/J89I+Id9+ltgld15wRDHjFt2+DQwfoGNynq1W2P4pl9DGxr1r8P0B6Yuk+DdS/Lf/N9mv/nvF69h0nfvLyX6l5V1X7+ZUGn7X5mndrUIB28vzMNv7N/6psb2M82TtbPeN9nM9XDnG0Ihx4B5kNR+YoUfsNRJINfeZ1uW0wGjdYowf9kba/e71eUQc6FhGPA82HRnavLgm7XeAQ+1q4/cmINt4n6index29yeM8e70yAwbUt8y8hOjH5eZzkZw7KlPzYmc9Rgv9LkJ9vkfygh9ZG+z29Rk+OVw1K77gvVT3U0Zcn8KC+uzMl6hvcpKhXVzYUz0Wy8X2SDcyXpmSD780a/B+CbPxXkg20n5wvEXlmH7BsPz9H0Gm7n9m/29ogHZUb0/pG5UrHfrZxUrnutlO9LpQhHM5vKp8z4lD4U+e3f3idbltMBo0W5+V+CGSws6K//Vjfk0HOQafyjnfC4Fh7Y9Ahvscj8JxvfCGPfN4WFRtW+opyw7bc4JcBTo4Nq5xtarXsyeI20S7Vp/y9jtR8cUx7POj2x2TlKU6fWv2xSHu4Tw3+6U6fqj7y+rQr4LeLdqlctl3CpSJtKg+o16fYfsPHffos0afKb+HcGeg7sA+p/DCVh8LTMeWbsI79ssP7baK+ii3wWTmMLWykMowt8FoM7zbNURnGFjjOob5xyLEF1D+OLbDsW2xhlNr60vx9zRi8PNN3G/E2AfCdyP8hpM2nOFZHEZ224iZM5/YG6SAui8irNRue/MIyo8PvmA7W99aGy2rSWSboMC60ydMAw2dgDX4V6PUrySarbyEsg3e8JlDfbTAdQPtWJkJt9TdXqz9ibSlaa7M9wLaXkUOkNUG4yrbd413lclG5WdgnU7jmSuJaKsqqjImXo0bZdsWL4jOmG0jH28v3YmMI762hrY/Qlyu7/xrrIxVLy/RyKv+d78ycsu7i6y5/w5WXM24UWeyeXyQ4U+8lYVCU5iK4Av39i/RuBPDhs1jmUtF5UU06LxJ02g4bv4joxJaOF6/ovUcxTk0/YvA7YOm4zlk6xlSvE/wjGcxf7OjEZIS/98A0dkLCFZV3OzxvBBpMN/t9fISHK8ntqzjlSbePw8rIzwSVoRvH6X3QXRwR71jm1gs6jCvmcli/snv86yVdDu/QA/JkdVXInvtB0fGmVKzv0cHjSVXovFjQqeuSKDqKZ7Usm85/Z2N8M9mSTVCm3EM+dmfwnwJb8hHHliCP/Leyy2xLjF7MlrB8GvzHHVvCbja2U/GMy2mmq2zJQh+RLanoaklbwts8yM/LiP+ycyHWX6y58GVEp+0tVOX2sX0p62ar7ckifdy2QtNU+sjzGsK/FfRxPmFuT9n2bNv2Mq7UOcjg9zU4B21I4G80DOpU9vul0OYYriDeGTzOfxwK2kSwGx3YmN3Kfr83/92mfmXPabP9dGJy/3BJub8y/81yfzLI/aMk97jE4vbyknqzaIOVb4F2p+Ido7rZcy7h3Ux4UVbemsPynDK9sof/X9CxqC3Ei/o/e1LGFHHxmCp7mvHzuzSmaosB6/KYGvwyaOPv0ZjiFgCHeJtov73fBu+ZLm9/bidY9TneSSoLof4Yqe1I+7sb4vzzEYEtol7bW738+eTtDdJBXG+b7acTk93HSXa7UKZk97r8N38G9M9X9Op9i2QX67Psoq3j45sqZJbhX7Wyn+d5gLN+On92sK7B7yB4xJE97IvvzN/HfHGrO0rwfyF8cWtbV9DL2va9FbptOB5d4H8H0V6AB1vyfRoP7C8bj+VhsG9YB3YCLwibPWYruQ/+BuTir1fEabFedEUbMxw/XqHhkAeEYxxmF7APDIeyC1ZvueCLdXeeaHQdGupT34oG22Pss51A32TjjoLynaJtQbxbIuDng25vELR3FODtCjzKvu+gsq2ijG1XCIO2K3v4CpX6tCXaRKUvMZ1QcjXv8L6TeJ8XvHcd3ruCDtoPz2+wv1Pm+o742/h7P7xjG6uOGSCM1eVjBsfkdkvFL9TRIeTrygjOpwFOPrrRDb3HcL4S3vH2ijdOyM/yENdzxTvaEn7n+TJB8JA9ZguVzMb8OO4PxYM6+qPsJh/9UcepUnUT/enfPcx8/+et1O0s6/u/BNZzL8hxHqm+P8d+Dwffnz+jMfT9Q3gNyW4Xysr4/iMguytIdlN9fz5eVeT7W5n17xJRj68UGL1LwDc+hfAtA1ooN9ljcQzrLzx+GESbOD5u8GfAfLTyPJ++svncngtzfEvDoI6UiLev8uTScHcr4k6Ra6WLSM/4Up+mH03g5UsPvfVt1/148/tZ3o0Xfpcy979OwNf8lP0KlS7BaC/sIUNZl8rGoMx4yGTthcTffEX+UvoP8U+Jsl+H32XGQuGaaxDXxoq4jgn9Mop6qOwwxzpUvDSzATcW2Cc1x7F9uIHsQ8XjaK/w5nPDvb0i7lT7EJtDka8JUZZiH47+0ernnP6Rq07phEE7OCLepRzrfo2Ar6l/L1P2oZu/U/ZhO5WhfTAelH3oVuQvpf8Qv4qJsH1IHQuFa65BXBsr4jL74MXI0T6wP6SuqaJ94P2Sm0jnKx7jlHvwfJYDzz1lz+rZXhnvIW1y8LANC6JObE/0t8Cn+wjZTNyXzJ5zBX/KJ8XzEh9fGYfbIuCy8l/I3+dHGk9fd+3ad1909bpL16675Op1146Efi65N3iHjU8tqsdaOErvPk1/8w7qMvr7eIGniKY61XQC/Ga6KSe4ThA8KzoratJZIei0fUlhBdFBKZ3Of2cStYFWaegBqFMta2YP/s9ewMve2Ks3R6s0pO3186rQz0vZfl6VSOekmnROEnTaHs+TqD1ocbnfyp4iwfocXYmdNNi3UtOMnXhjuTH4v1zdq3dXgtx4bVQn3rzTkIZrUwGuNYQL63tJDSYS6HiJASYS6aS0x6NzKNtjuNSpMBwD/piHOnFvuDYX4FpLuNQlBe8kV0fgVHS8E3PeibG5mnTmEuksVnvW16STetJuVU06qwSdtk9oriI6MXv7x2RvVSIX74SxwX8D7O2/J3uLK/ef9X5uY2cHx6xoPL+TsLPjjafBfwHG84mE8VR9Ezu5hHS9sVaJNToCl3fal/sB4dWc0mK0KPkzZhwxrhgZX7jM2CV63D5reyYXT8t/56u/VeuueflxJ5zyf5d+1191bSxy9GQkGvp32RA+0N9cL+NtlGA2CBrZw/KzheB43O0940/hqQi2qFzZum2RdoaQZuuwftmLyTY+fDH5b2GHh09oK59MJWzw/AG1O6duq+H7oyL1bgiaP2sz8qTabPA/cdo8V9Bm9t9jtzXxb4YbEW1YGgZlAHGoPj459PNeVp6w/mLNnScTndicNnFi7z32Q+z0+W/mv/n0+T6Y0yZznN6ti7bbz/6rSr/7mwATW9uMRnDyTq7BPz1ve82dFRll5ejwMsF/1r5n0JiqtntjavCbYUz/UcKYevqhkrl6tmCjA6/Wiir24/mNNj58im06pDydP0+RUcQ/QbyUlIcFf0MlTML2VfU3DO+3oUHIf5G/wfU8f4NhY7rHPsBmel/kbyieYrBl/Q2Mi2wh2LKxSaxvcCafFRPQT3OfjwR9yjB2m21J0PNk7AZ2J4Kf41xWfzQM9g3OTWyLXpLbn8yXWJX7EmosTonwF0LaWGD9xYoTn0J01jdIR2VSUD4Oy3BZHwfrx+aDmAx+MP9d5KusoHnNi18jXY5fnwXz2gzNa6n7Hl5yc25/2eTmKX5Mkf5wH6X6MQb/DvJjKmZ/WM2n9wwH4q7oI61O0QnEPynocXIjLEs5IbLj66/60syV77iV5yjjhd+lxFreKODr+SvhbHVCBHe6s2cUyjZT2RiUGQ/qhEhF/+bslP5D/FMCHk+4lxkLheusirjsVIdakx4qWxGLVZjd4Ln2YphrU26Te3t46rY7+/jcRrY5IcTl6Kf0GD7r/ycJWpwU0mCvgHafQp9a2SR4NRsx4tAI4l0nxPuGaahTMv809PM2l8Cbip8gjvURPjMcas+N5bZshggv9oJ0zqlJ5xxBx5uT+H+jw++8/btziE7Mn7mB/Blvfyj7fWP+m/eHXg3+zI3kz2D92B5lJ2jfmG2g1Y/demV7YvA3g17xDS6VdelG4CsmZ+jPqA++MA8fW4S4DLdpNAza1uw5eTbINhVl/TB45TN4iSzV/Mm4YrHdWNar207q1bvlxHLtP2VW41y/qofz0yVxnhrBefeJPZy3kW6g3Lw+aHrZk7JuxPq8hkcdLBPzsfqfrFZ/ITElZqhTdsXw113nIq2JMNjHVeJdindvHDCTHGdcVLgmS+JaKsqqjMmyEG8X4p90eFF8so+h6Lwe3vF65BaHL4Q3HULZtLrWR5igukQfLfHGCxNiG/4ayUKte55BcJwsFLv4kxFcgf5+Br0bCTpZaGaazjr54O/lopkXEl41RPiOxRjrG5yic2xNOscKOh6uCwUug1fLoGMFvLUD851b3ZqhiwUx/JTgRbnLNcTQuudZAINewJIwqFG3RnAF+ptxxsRwRNDgOwKeFmbPcoGDrfCnHJrW1uxReW8Njj9v8XXy7ipano9y+nzDgbgrRuQ/mjqDcpp/pGd8qc/TpkSr/nrqxV9/2/NO/QNPzbydOrX6v1jA11S9D6toFZ5yzp5RKFtPZWNQZjyoaFXFOzAfTuk/xD8l4DlaVTbyo3L4lcVl0So0n6Y7i6XLHi4VWeoQz+NB71SxrTD4b8Jq9HSK8qh+COLdkjBoJ944e/B/NSWtDJp3RdvwZ8+UqG9wLdqqsbK2aiIMtrmKt6/kVvUL5xDGunxCPnv4nn7Z2xaHOy6UTf48jJWr/40Ov+N+bmJHksesCVybGsCloo6vgt9YZrj4HY8L1p+jsk8JOmq39lYqw34zW6hO9R9P7UKdZPtd1g4tE/xx1CD7PZ3/zpY2YUbTxGgX1uWIk8G/eBXUm4m3MeUkF8LHIoZLZ/L/8/dtnuSK9d1RM6GvLV7fZY/duOG+ezL03dE5TtV3PPernQUVVeQc8rFP6GJZCP4JJhVZT8l1VHOnNHnua/pklzpFr2xMzZwuo0ZP3VNX4/DkoPtU5V0yHVO2ju0Z2jre1cV5LfYZ1+z3cfA7Zs+wTRwZV/wtlt1UdM6vSed8QcfzE1NkXdFRPBfZshfN9N7j+MfmgWvy3xzt/4eZXr2X5r/VbhfyyH+nrC+MXur3Fgz+FTMH/1e7XarN1zg8I40QBvWG5y6Df/XMwf/bzPXgneCuSXdJqg02/BPES1UbXHS6AU/XPiX/nYf63nDlRZeefNFV11z33nWcRS92xrJDWPFdJ/S3HstG6N0kwZ052/+3Se1IiD+oFWhlQ0g756HOPqhV+XpBl886qK8GjAg6vLodceojjtj5m5FIvezvfybqNHmHockVTYtn7p6aqpmGf4J4qaqZ6vyV8o5Udhwvyztu7GAZ0vG8U8R1S0O4socjA0NcQ1xDXENci4HLO6PHq7Ds4buaaAd55VR2Uxnre5vX59Skc46gMynqVZ2TpxyeVbSF+61sBFKd+ytaoX14RtNMXaEZ/F/P9Op9dKafZ7VCC0GvhnEcDuCYHay71HiAshL+xfJslXYmfYkD+3Vstoe3yA/JftvZRT5Tjm1XspA6Rp+e6edH5f6aEPxw7q8/m+nVuy3/rc7FpZwnUvRYD8cj8MuIP4Ofmzn4P+7SKf42ROjFztBeHqG3baZH77UgDwfaOdurj2f7DuCBsjJ+tJI7tDMsdyoSpOyZZy9UREtFWXlnVp2FVOdNO1R/POgx4HPCBr9v5uD/OOapcs7javB3AU5vXPHs2gE8UFZ3XLGveFzVrjfC87gqOcDxsj5RkbpPEq5PClze+e8iXTZ8rFuPzBz8X42rOv+NfPK4GvznAKc3rnhu8wAeKKs7rthXPK6p5yg9OcD5wfpERdY/TWVeDj5lv1EOUsYcxydmv78yc/B/HHMVwV+WwJ/qtwzuqfnvPAK39torr16Xh+ACPV7ILPt7Y4SNp4j6gep26N1TqEyZT+/wjtEeDzpkxebT4P/NzMH/1cEWZX6zxzvyXfP4eXIQ1/A3dWS8yKxxqMhTM28pcwhENXssutsRbHH9QLg64l32qCPIKrtIinVTXaXOaiG84eN96/8wc/B/NXOomdDLUqY8d5wd+bY3toEzTGK9DRE6OKOhGPGMZvBPzPTa6s1oDa185IyGfcQzmooseDeb1X62ipZOETz2vZrR+LZVkRqaeVUrK/QqeWWl5MXzzLz+UfKlzjWosxXeKtjg2lgFY3tYFryxzZ5YdhmEx/FmrxXPFnDkCXWJb7OpVU+qLGC0gyMh6xPxGrzKTIFTOK/KF7KurDr4v/oundqR8+RR9YW6xax28PhGLtbDcwUHcM/2yjDL2oH2QVkJeTy6yahM9lTVVbXLw2e6cS7woji4929nIRbrDBbP3ypzKfLK35Uy+Ges6tV74ap+nErHvTFQ549Q79lequ+mebhudWh3Bfx2hzbyhXWZNvOJ3/s5QGu2V7ZwzjD/fxTKypxXU7qC9pl1xbPF2ZPSV2qcpgge+6bseTD+jmTqeTC8zczyqfzF1LkBz13amczFitqzT3xc3i6VnaPobO2NEZyvdOYd1QZv3imKkLNuoe1jP1tFJZXtY7uo7LWyI2wX1ff7ED72/b6ZvP9qZjGW561i303F7B44n/EZYIN/M9juk1dpnGMlcZ4m5KZFWzfatq0rmpP4nCqOTey8IeJSZ1FZz8aDXi8ZPt5teyOMAUfa0N6yTUV7yzZ1o6Dr3TXI5ObanA/217Lf0wD3VpI9tV5Gm8OyZ/C/AfL89vx3k3aDszap726y/oTgy5naFTQ4Jc9mB2qe+U4+087fy6t4ht7NVqpiBjXt5sKZ9q6gp8YBz7Src+yIy+aCxbZrXiymqF/5fhC2kfUZbQTbgRSfTNGL+WTXku435ZPZHSOl46z/qOOs/ypzqVoDxL5tr2wYz9kIfyPYsFupb7qh96TEWOYFfBdgeE2vvkPv4fJifTsE/LxDuwtlWJdpx3TSy2bYxnoK/QLWxS6UjQj4lL7qAgzHu3ZA2TyVpeour8Nwfme9Rtk2mVfyWRRzYd1VX2xCf0BllHlH6KeptnbwHc+zWN/gFJ1ja9I5VtDxcL1D4PJsopf6RK2pa97/Xkh9ovZ5VKqVGqlPrHueAzAdYHUJsYJNZlyB/macI0GnPlEisSzCp9EtEgmVYItxYdI1O0SZlfPVIoN/bNXB/214b6G2TYek5zPeFXHDXfEq/2c6hC8E7WrGrqchXyqtQEqakz/+m5s+9vZL/uJxT6W88KAK918g4GumOfmUmsY4lckolHHoHaciL81JRTPwqZT+Q/xTAp7TnJS90ohlayriOiYMmko+TNy27vOy/YurDv6PYbzF5sVcpi8JXrwpQH0k1EsIdygPhr+zJp13CjptHwx/J9GJHQb+o1W99yjfsfDvtflvPnj5oZN69b6e41THIJBHNf/g3JU9rK98MJRhNkT4+zOQT75Sq9p8rcMzhtFCGLQLHOJdOIqS81DTpsoQL6f8aiGlT/JprEOV0qfclVo+ooy9gljxXSf0tx7LRugdH7o6Y7b/b1vcjIT4g1rBmqF6wnB6aeLV7FsmURXiVQcTOHGeN9sjDrUIMRyqXvb31aJOk8kKFut6rmlmxSuuyZ+u5E9VVPQ6FzTTOyCSPd6VWg5SYBmvdupcqd3cIK6NDeHKnuHVwiGuIa7D9+qqSgjGh0mzhz9R3/bKS9E5vyad8wWdSVGv6tw35fCsDg9yv5VNaoj1OdlMbCX03JM0zdSVkMFfAyuh55/Uz7NaCWEfqHsELV41k4cksV/HZnt4UQ8O8BMGx82u83rXdJQspI7RcTRGRVf6+Hqxwb8DxuiV+e+Uq6FFV1evIXhrY+rVVYN/Tc5T0dXVWyP0Uj8nb/Argd4iXF09Rskd2hmWOxVxUfbMsxcqcqQ2s/gqnHf9sey1VnUVzrvWavBnCnnguYhlI8af6reGr8Ktj7DxZFE/UN0OvXtyBJfhyd7h8jXlKpy67com4o2iy70hy57hVbgj7iqcRWU6gi2uHwhXR7zLnqKrcDyreF2sukpZkZRL1BcJkfYsrPcBbeUJ4PB6V+H4WBzWuzVCR13uzh6e0Qz+3YkzWkOelJzRsI94RkuNnBh80ZFoVjUvaYiX6ripq3DsqTV99YjlK/XqkedV/zxePcLpiNMsKy8qVRZw9cQrq08V4I3t0aINwCk8diXhI8IGGE4VgfbkUcmvinqrKwls79QespJHg6spj5NKHrH9LI9eW7Onqq5OhUE546OkOBewG1kkN5484h6f7XmqXZI1RLPsJ1XWCP4VnWNr0jlW0PFwrRG4DF4dBfaOi6nraTWPXy/xZE8dr65xXMy65xcBpgOsLgmDIrw1givQ34yz6LgYDt0tET6NbpFIKNVRdJbVpLNM0OHjIF/ITW/NLeebUzbNKt4wuLlD+ELQK6rY7QrkS912SDlm9s3HXvvFp970jeUdqm+88LsU1X2bgK+pnrNqeuKbqaNQtpXKcIoxHtQxs4q3U2ZT+g/xTwl4PmZW9kYOlp1VEZcdM/Nu2S+WLts0/TvgRvExs7Z5UXTOr0nnfEGnya8UTTk8FwW4/yCybEoNcBv881f36v0hBbhVP3eCttPZ/94XDoxe6hcODP4bIFN8HGuDaPM1Ds+bgAbTzX4fH+HhcZqjKh6+kMexeAmK/LCeqEM96osBSk82OHTeVZPOuwSdJg/ETDk8N5nLXm1GTee/1W3Pi+A3lhkdfsd0sP6cQ+eWmnRuEXRUaAiXTTV9ppGafsTCt6uLsvkYfu8rTSlygLSa+sqS4t07ZIA+DbYxhmtbSVw1faeFMSnKtoX+XowXxSeHleq0ebJBXHwwTOnfRQKXwad+/Urd/rS6NnZdKKuybFZjp2491lg2W/e8meDs/MuSMCji2yK4Av39ZnpXtGxuO2HKYpnrIndw8mRNM+YO8gdrDf6qU3r1pmhnCvk6LfTTK3vTAet7NyrYbcGIKEdLVTr3DpUhf95NILXTNCLoqCmz4oeoOjXdywXzXHT2hmWqqouGtJr6KFbRp6A8V43P3Cpcm0riqnnrbmFMvI99If5JhxfFZ0oimNPgXUpEXvW32iHDhBQ4pVWdmlQfqcSVNaYm655fIThbiS4Jg6K0KYIr0N+/Qu+Kpqa2zZWic2ZNOmcm0lms9myoSWeDoOPhOlPgGqpS33OoVSmWDtroFomE+mjMofQwMNBY5AWeTl4gpgFN8QIN/uaTe/XOhN98Vglx3Rb6y7Afbyf+8VyOjWnNPAPJx94M/wTxUpLegseSeuK03J1DXr5iryBWfMfahGUj9I4PHi6jelXuHKpd908KnMrP/1SkHvZFEO+WCPhbCNctop7xPuLURxxYjyWmQ+9R2z4jaPOZ6gtyrcpC3FdSiFvRwv4oOjfMMMzDwok/4OGEyIm/0Ui7WJs50wfKlm2dMf1fByuz7mRNPwj63D60nuMRfrE9CH8F9AEf5FWWP0TeYR9g3djfCLs09LcF/1ay+BmC/3RB23n8Df4qZ/wnBQ/GV/Zw/zMPDLNwSongrxU8CKt58pVXXR85wzsKv5WV41HikZgUeGKP9UYmsSa93DusHUzH/lYSkLX8afnvBdfsveuujZ1f5hlhIkJzSdDPZNC8hXDojqRPVqPnHknH9lU9kh7T0iI6NY+kxyZtZSy4fqC6HfEuezJx3pxfpTiUe5K31KSjgoiMK+YWvy//zV+6/wQYqNdG9qKXCJzZY8Fvg/eOxRsehC86Osl9qQJ+Hm1v735LSV6L9oc4cKuyV6byumaRed0gePX2HmvuoyabTsPf1N5l6ldXyi1rYt+G6BBWfNcJ/a3HMraQvFR4/Wz/31WWNUW7uLysiW1rxSQriHdLBPxWwhXLLT8SoadGVOXONRyqXvb3zaJO3d337OHJeFuDuLYLXDV3VJ+eqpnd/PcE8VJVM7tEj9vHbZ8XvEyJMg45zAs684KOwrW5QVwbG8KVPZwGYohriGuIa4jrSMOlLuxx3m2cPzn1TNspVBSdc2rSOUfQUalIOpH/jQ6/YzqKZ2sPzt3cb+qU13aHDtbnU4x4cnk6/52tVr93sqYZ+/Yfn/o2+IvgmM/3T463Efv5QLtmB3lu43uQXQAYm+3hjelPF3i2S57Kl+BLhDjWhqNoDH5MY1D1+4tnwhj8HY0B1sfTgDG9UfRYRmKfeN5I/Bn834twuOJvS4Qe9gf280ci9MIpPXreRXyjXVPunt72txeK5JSP9aCccsRG3VxR30TpUP3xoMcgdoNnGYwBJ34oknMe14W5IHFcG7InTy+bqkpF1ryEFl0Br76bORUGxzwWiURcONYp46pSt/K4PtMZV3VIAPnkcTX4ZyWOKx6lO4AHyuqOq3c5XY2rdzldzd84rtYnU2FwnuR0T95xv+xJGVccA7bRBv98Z1xVlNuzwwb/wsPADmNfpYyr2glIHVe2wziunOIL5zrW5cWy0a8SY84+P9uFGH+q3xpO8bU1wsbTRP1AdTv07mkRXIYne4dhVe5ya+540CFQ7nKDXyG6XKmpOqulLorWPCmevClg+CfCoEhUCT16rucBxvL/y55iLjsttiCq2WO7BR3BFtcPhKsj3mGZEtXUlCQ4Q59OKwUUIV4pKMunPH+Dn8//jnkXhm+U4M91ZqF5wUMX3rG13iHg5wGG73tjG3ZQGdbbEqGDsyNafp4dDf7NibOj0W5jdsQ+4tlxJ5SNCHju7zsE/E6A4ajSHVDGKo19vIPoFJkOln8lp2r13RV4vfRMnjwq+VJfLlwu6nmREoNrI1KC7WFZ8HQpe7hvPNnBvpkKxXKCejlPdDy7lD2eLGB04XtkC1H+ODpXNuE31jc4ReeWmnRuEXQYV+o5FYO/Xtgow6l2gb3zEUX3rzm9nncPWH1tmP83OvwulkMFx6rJnWPPo/Z2lavSQTuzmeh0G6TTBRiOos83SAd1fpLo7GiQDtonzj2xs0E6aOvwGgvPiSrL7y7Bhy0BdsP7EnPBaEo7EP8E8VKS3sISYDfR4/bxEmCP4GVKlP06/MYypLNH0FG4bm0Ql43t8jA41iuJjvKl7nDorEykM1OTzoygMynq1dUR1TdGZ3eDdFBnZojOngbpoBxME529DdLZCzDHE505wUPmD9x/Su999m8flHGUK3tsB3iU4P/1ub16D+U4TQbRViCPWB9zKe0S7WB6j+U0zP7thzol7JHMpWS4ivru89R3u6Aspe8M/k7ouy9S32G7WLfvhLLdVHYXlO2hsruhDHFgWYA24DuWOaxvcJOiHs9X98D7EuM1lqIbiH8iDLa5ynx1D9HDtmeP9Yu1795q9EaN3n2CnhqHJwfdp0jfcJmOKTu7n8rQNt5NZWjP7qIy1O/j4DfijLWJT8AifyzfyN9WKlMnZ72cOGqN3qUybPN86D3Y5jHCkz120maUYP8j7Np/M/+t7A3b8V0Ct5XtE2UZ/qvP6G8L2hTsRyzLnhHxzptD90dw4YU/XLuxPTT4/022HW1MCV263PrlLnjJdqiiXbg81Q7FbCLypWxUSi7X9S/44VP2X/K/Hy9ruz2btlrA17RpF6tYltFWuVzvprIxKDMeVC7XinPKxSn9h/inRNlN8LvMWEyJMr7jUxUX28K6uLZXxGU5ZtEnYb9DxfJwvvBuRzBf+wtw8ee/sT7bsDsLcPGJyP2ijd7apaaNS/aHDP9EGLTbVfyhon7h9bsa+ylRxvJ6l6Bzl6CjcG1vENf+BnG1Ec9U/s0ZxHPZ3IVnCJ5V3PQMag/6gNP578wP+YVTNT+4XsL18NrZg/+PEvwmWC8989T+9iNtzy/kmEvZ3NsrE+msrUlnraDTdhycYy77G6SDerSW6NzZIB20p9NE564G6aBes6++TfCQyexLSA/uhrIRUffD+e9Rgn8N6MHLHT1AHrE+xlxU7IjpvSqnUdPfkjEX9Ae9vjuB+g7XXsqm8RrD4H8J+u611Hcqz6zq1/1UpuIqy8NgX3EMTPnh+M6L83G/YT3r35r+e7KPYfgnQi35WPAx7iV62Pbs4fXJfdXoLcRc7hf01DhgzEXFWRAXx1y8b0OgbeS1hoqzKRvEMZdtBW1KuXXMf1ucA2P+HOdYyIENerYm1zO1v/rm2f4ylPE7gO6bSFdVDLRDZSH4MTsVy2DfvYm5ScVm2Ucr61difY7F3Sno8JzO9vXCUzU/aF/RH2AfzeD/7pxevUtozNQaSY0n+2hlx3NlIp21NemsFXTa9mnYR2vLp2Ef7e4G6eB8OU107mmQDs5D7KPtFjxkMvsB0oN7oWxE1GUfzeA3gh7c4OgB8oj10UfbL9rB9GbJR6s4J0ofzXAV9d2HqO/2Q5kXQ+E48A3Qd/+shA3BOfkuKsP+uJvK7ocyxIFlAdqA71jmsL7BTYp61r82Xg/A+zZ8NMM/EQbbXMVHe4DoYduzh320B6vRW/DRHhL01Digj4Z9ivQNF/toaGd5Xwxt4/1UhvbsPipD/WYf7c6CNrGPpmSfcY3CO+VnjRL8tly/Ml3bQn6a2uM58JnV0/rhWthnST6fZPgnwuA4VZFrFdtWfhjPV1hXjf2H4DeWIR1v7Ye49jSIi9eyKGPsh5XdI1yZSGemJp0ZQaftGBb7YW35RzNEpy3/aJro3NsgHZwT2Q9T8brMxvw2+RL3QZnyzdmXMPhngS/xL8mXQFvB8z6fnWB49sMM/svkh1WcZ6Ufxv5ErO9+L2Et5/Wdwf/07F69rzp9x7qd6mvdQ2U4XyMOLAvQBnzHMof1DW5S1OP5qqKfkuyHGf6JMNjmKvPVg0QP25497Ic9VI3egh/2sKCnxgH9MOV7IS72w9DOcmwDbeMDVIb2jH001G/2w+4qaJPnh90VwZXqhxn8d8luVPSbpN3gsyhDf62/rpKfm+A3liGdVB+rbtx/6K/1/290+N3QX2uGThV/rXNa7z3OQWX9tS74HKM5zjb9tYmcxqH015ZR31X1126GvltOfadiG6pf2V9DP4r9NewrngfLxs1UfOXnJW6m5qsjKW6m4lLKNrJPhvaM42aev9ZE3Cw1xsU0Y37dW2b7yw3+/z2th/P5FDdT57EzuHuH8bWfmfiad3+B/TV1T2K3Q2dlIp2ZmnRmBJ1JUa8T+d/o8DtvH579tbbu5c0QnZ+1fc6Yz3EG2Te1z+n5HAb/XPA5znL8tZR9Ts9fM/jV5K+1uc8Z67s1DflrT4K+e5PTd6zbODfyHb/hPufBZ7jPGffX0M5yfA1tY1P7nHsK2sT+GvK3J4Ir1Q8z+PeR3ajox0i7YbjU+TaW/z3V6Cb7a4Z/gnipKv9q7NTdAfZVsa5a490Ev7EM6aTeq9jbIK6hv9ajw+8OR3+trTwK00TnrgbpeHcHYj7HJ8jnUHcHPJ/D4Pe+oVfvFidGlHJ34E7RDqa3nuxuxbPhte4O3B5Zy6feHTD4j0PfbaK+Q9qs29hPXk6GvVSGfcXnfcquSbH+z9vdAS9fw5FwdwDtLN8dQNvIdwfQnpW5O7C7oE3srynZVzEuvEfAMS7vjmxFn2l5qgyyz1T3jqzymdR8vez//nte/jtPP3v6umtXX3fxe6+45Kx111+z6tcuXX3R1ddecdF7V1166dXrrrkGmUZCR8N7LMeHYez3dvEecewtaAwLAw4WO2ZFl4f5gjbWZwN4VwEuvqCtJjf+eywM8mkXXJYk4EFFi/G1lvhSmy+ekVeHz9VkEgu4xHB9lHBhfd5cxGAR88n95eGJGVDk62PElzKYhuuBAlw3EC6s/wDherAA128RLrUI57/HwiCf3F8enuzfQwV8/XPiK3b4Jvv3cAGuawmXOrxjuD5bgOsawoX1sS7+PRYG+eT+8vBk/x4p4OtG4uuzUPYIlWG984lO2UUa1l+sRdr5ROeRBuk8AjDTUC/7+1EoQ9s6Kd4ZDZv8H4P3bQRMDP8E8VKS3sLk/xjR4/ZxwORzgpcpUcaBsM8JOp8TdBSuvQ3iepTaE1uE/ZAWYXugLGURZvDXwiLsR7QIwz56hNqo/Jg9gl6H2jUu4BHfKMH/bc6T+rzGI6K+wo3zqRfoWBoG9asNHTH8E2FQfqroyKNEj9vHOvKY4GVKlHHQQuniY4KOwnV3g7j2UHtiOjJ2ej/NqjpyAejI0hzn4aQjR+c81dER9KFSdKTixlOyjvDGU10dUb6spyOPCl6mRBkfrFe6+Kigo3Dd3yCuVB15VkM6chroyLEt6oj1d6qOGPxzG9AR9JtTdKROMAzxGT/4DvE3pSMqWaqnI/cLXqZEGa6ZsAzpeJvjiOuhBnGl6sjxDenIS0FHXnUY6shrS+qI4r2NtZeKX50Kv2N9pGR3StTfS2W7BZ0iGTn1dM1PLBkVfwp4IaESyMgZjowcDhur59Wkc56gs9gbq21teJ5HdO5rkA7OK9NE5/4G6aCtTE3KdgHpwQNQpvSAP8ds8F88q1fvQkcPYjFL3FjdI9rB9NblNGoePJIbq4arqO8ub2iemYe+e08JG4I+Pdt47I/7qAznZI77qvgqvmOZw/oGNynqWf/aeGHcso2NVcM/EQbbXMXXSr34ae17pBq9hY1VtZZQ44Abq9inSN9weRurfFgJbeNDVIb27EEqQ/1OOQiHbUo5COcdsFkqeG/Djzf8E2FQR6vIVpG/yH78fYIXNTYfh99YhnTUZWmFa3eDuGyPYXjIbPDd4eALzRCdnxdfaGsJXyh7eD43+JNgPu8ugi+06zDwhfY05As9D/pu/9AX8p4jxhf6bDV6C76Q2sMu4wupPe2fBV9oRPCHcKh7Kp4UxLuOQ49pLBF1PxH6+cayS4lG2RjQpYLfFuO6I6n6daTEdXkPvU4sNsXnOVSXPto4wHgpvGvoEO2INw5ewu+Ke3lLjJ53tgvpZfZ0PAyOYewMmjq7heMV0/mq5ynvK8DlnafkfcD7C3DxecrYwWUs+2+5/5LZ4T8/vR/m3hzmCYD5bv5bXc5Hf+qHBKeSn9RM6JGse4Z/gnipqntqHNSFw0w2nxR8GcExip0zvUe0JUVmkacUmS07pupQeQb3Nw7cXQJO0cr+xnPPhoN98f8B+0sXntffRqTLZ5PLfnDnTsGLorOyJp2ViXRmatKZEXQmRb1O5H+jw++Yjuobo9PWx9VniM6eBumg3kwTnbZiHamJ0SfP6L1nXfPmC770/pUze/WmcpzqjH7sUmfqBTSDf1pOo2bClKTEerG++wXqO3UBzes7g98HffdMp+9Yt9H288dPsT/4chrODXy2ruwFNJUM4uflApqX4OlIuICm5jplG/kCGtozvoCG+s2xge0FbfIuoFnd7HLVP85/9y5XnbXu+jdf9N4rLr3o2iuu/LU1695/3bprrh0FzGrmYAvPlhhTQ8WeDv29hMq2UTneclBPSqqBiikOkj1fw99UqgF1o8tLNaA+qatSVfz/8BvLkE7qp1D3N4iLP18xTOUZp+Ol8mzrUzszRKetFADTRKetFFSpnt7Z5K1sh7IUb8XgzwRvZTV5Kzhr8El7w42e3nbRjlGCfxN5ehWjbtLTSz15+ZaEvvN2gQz+xdB351PfIW3Wbewnti8q7Y9asfPnc1U0UO3OK49gEU4tJHt6i3FqAX0H9vQqepYLnp7yLNU4oKeHfapu4nqpPDnVgEpj4aXQUTYoxdPDNqV4eiZbc4KOle2CMv6c7j7R5kzvrnb0rpv/HiXaHyMbhLpQYsxXTBIdw4G4K0b5V6TqS2yHA/lSOw6jCbwc/90vPX3kskv3sc03XvjdEsAfs0lnCfiatuU1k0ZjtlcfbVr2jELZbiobgzLjIYsmvpD4q2iLXpPSf0pfEf602R5cmbFQO8eoI2VwHRP65Qp1x/QP9Xs+/52yDqqog8nrIMPf1DpI2URvHdQVvEyJsg/Bb7YtI+LdEgfXXIO4zDarceZ10JygM+fQWSl4VnRmatKZEXQmRb1O5H+jw++YjuqbxY54dxuk0wWYaaIz3yCdeYDhddBWwUM2/+8lXx53oUaobvawL2/w//b1vXp3Oj4F8oj1cR20TbSD6d23iOugWN89QH2HflVK3xn8/dB3Dzt9x7qNcxLPI9gfXSqLnSTCshDSTutg/TKnddAHb2MdZPibOq2jYkZqjrf2VcywsbAOUnFCNQ64Dop9OpN3lZSd5XUQ2kY+fd6FMva55qEs5XPt2CZeByn+hr5Qui90E/zGMqTTFXQUrjsaxOX5KENfqJ/O0BcKleigHUr1hf5zQ77QGpjPf7AIvtB/Owx8ob9pyBd6JfTd/6C+Q9qs2ypmpvykLpVhX/G6vmxMGOv/vMWE1XxV09db8IVURs0yMWHlF3m+0FYqU7F+Zc84JjwPZewLbS1ok+cLYV38e0zAbgm99iLsJOjZca+P09oR+su2QNlOKkvVT8SB/Ru7jf4+aoPBPzXnO4s1XnKexrkk+HtSKvZp7VhqdKGshPz+TsbXmef16KC8ZM/YbD/P81Dm+VQGv0PAo8yxb7gDytifU/KI/oXJo+qvbv6ujf5CHlL6S+1NpfYX6z321y7C1RW4sA+9/jIe2+gv5CGlvxC+bH9189+qv/YRrqI1zlnEazd/Px60TTB8owT/UrAJnC3Hs/FbBG60jR3Cge2YEO2YpDKse+Ck6ckHfy9WnAfHDedE5Z8h3lGCfx3MG+dS3xRlvmb5UjEOjFtspfakfJIacW1zaHuf6FO0kS8+u8JnZmKfYjxAa7ZXZn1T0w6MKTuA8Sq2A2qc1Pknr6/UOKm9cD6zlhpz2k9lXSjzYk6Y4YnlU8WfYjab9QHXM7zWUesET/a8TBBK9lSMVek/2w3Uf7YbKKNdKsOxnSfeq55QvyAfizZPqLN8jwYt37GT59eAbbswYtvGSuK8BOaj14KOZo/ab69pC0aVLUB9Z1vg2eDsKWs3WW9xbHivQe2bY5+yT2B9NC7gER/fcPq1RJ/AO/XtxcC9dZ/pQyY3t+Z8cEwg+z0NcNeR7KFNU2tFlj2DXw/y/AFa4zVhN+apzLvZouYcJWfq5Dx/ztjLpF7xPHhyLIXPg9fNpJ66z1PTbi7EUu4R9NQ4YCyl6FalzQWLbdewn1LsmtprSjnbhzaC7YA6i8o2QtGbh3roi99Kuq9sZKrPgvHr/0yxVNQv1n/UcdZ/lPculWEfYvtQbmLZKvjT4wa/GWzYPdQ3SpY9P/ZeAY/nRflmGMr6vQm49jq01S32ex3ayBdnZuKb4EonlS5a37Sx3kC/gHVRjZO6P+L1lRonlZ3lXipL1V2+udWFMtbreSjDG6L3ROZtbIeK8Sp/AOf862juPlJiBY+C7n5tGCsYoM18DmMF/WWLGSv4WkuxggeGsYLSsYLHj4BYwV+DbftWQ7GCbw9jBQtlhypW8P3DJFZwdH43rihW8KOGYgVPhrt4Px7GCrxnGCsgesNYwaGJFZiN8GxklVjB3iM0VvAMsGEvpL4ZxgriOjmMFZTT3SZiBSyfTcUKfkRzt1onqbUC36PfI/hW9iD2NefYWS6OFRj8K0B3T6e+UfrjxQqK9IczRyn98XB5Z4xUpqL7HNrIF2dGZ11Wd9sXO1aA+sm669nM7EnpKzVOUwSPfaPu9PO5N5yHOHsTzkNsK1C2UcdYPlPPNqm8GnjW6C0txwo4m7pasyj9Z7uh/G0vm5qSdbYbNp4YK0B4jhUY/JvysTD/s2ImVBkr4Mz9mE9CyTevrQz+V8G2vTVi28ZK4nx7judQxgpQ39kWeDY4e8raTdZbHBvO5ZKaWY31bDxoH4LPGhr8ZTAGHCtAe8R+hlr7KnvEdkzlOcrk5rcSYwXvi/gcZWMFnwB5vir/3aTduJvK0A5wrEDNOUrOVKwA51CuZ3bA7ErFDIbJsQLOLn9vNXqls8vXtJsLsQL1JV81DhgrKMowfjjGCor6ldfu2EbWZ7QRbAfQRrD9uMuhp9Z3aCM8G6kytKu8OOiznO3EClj/UcdZ/1He2W/APmS/4X7gRfk8OGcj/GfAhu2mvlGy7PmxKtM+Zsnn9br3FV6Fy4sVqK/XPOjQVl+vYV5CiOuk0kXrmzbWG+gXsC6qcVJftvD6So3TFMFj35TV3fupDOd31muUbZN5JZ9NxQreR3N329mVY3O3yrmIeNn3vQ9090vUN8o+o70s63fymkmt1z1c3v6YJ7+KNvKFdZk282n1lO5a37Shu02uD1RfqXGaCoN6zTqYmumZ9RP1yMv0jPMuy2fRuRdv3sV9Zc627p27yB7uTy/OqmTvLtE+pf9ebI3thhfTVl+/ZD3DWAHCc6zA4P8dxQoqfmFHxgr4q3IYz1DyzWsrg/8e2LZvRGzbWEmcf5oYK7BxbMOnRn1nW+DZ4OwpazdZb3FsUs6CYZ9yrMD6aDzomCWeeUH47zqxArRHHNdMzTzPZ6dQZzBWMHbWwd+8F5P9nga4v4rsn6Hsoc1h2VvwCeFLj/+F/I0m7AbHLVXMyJtzvK/Zqn0BJc9mB2qupZNjBfw1poqxCfdrTGq9U9NuLsQK1BpHjQPGCoq+QObFCtq0a95+SFG/8tod28j6jDaC7QDaCLYfexx6KhaGNsKzkak+C+55TlKsAPXL2xdj/Ud599bW7DeoL/2qNRd/eXcKbNgvU98oWfb82KL1Osc+1Xrdw+XFKdQXXR9yaCNfWJdpx3RS6aL1TRvrDfQLWBe9GE32pPSVGqcpgse+Kau7D1AZzu+s1yjbGANj+Sw6T8G6G4sf/pUT52/jK828tn4YeFHnCnAeQPgXge6eSH1jXwwOIU0m1BeK8avDbMNQJh5JwLXHof2ogH/EoY18YV2mzXxaPaW71jdt6C7qG+uuGieET+krNU5TBI99Y2WpX4x+mMpSvxhtMq/ks2j/3ztXsAfw7jm9H6+yhZ7sFc1ZLHtqzlL6z3YD9Z/tBsoo2w0cW7Yb/CVwhudYgcGfnY+F+Z8oI3VjBY8Sj58FHpR889rK4C8B27Y6YtvGSuJcm+MpihXYOLbhU6O+sy3wbHD2lLWbrLc4NhzTUXEH7FOOFVgfjQt4xDdK8O+EMeBYAdqjzxLvaI+8L9izn4E6g7GCmyhWgLo7DXDrSPbQprG9yB6WPYP/MMjzu/PfTdqN+6kM7QD71mrOUXKm9opwDuV6ZgfMrqAsthErMPwTYbDNVWIFSv9wfuBYQUW7uRAreEzQU+OAsQLsU6RvuLxYQZt2Dfspxa4hPK/dsY2sz2gj2A6gjWD7cZ9DD20E+uI3ke4rG5nqs+D6fGvusygdZ/1HHWf9R3lnvwH7kP2GR4EX5fPgnI3wHwcbto36Rsmy58d+TsA/BjAPUntQ1j+XgOshh/bnBfznHNrIF9Zl2jGdVLpofdPGegP9AtZFNU4In9JXapymCB77pqzuPkplOL+zXqNsm8wr+fT8/Oxh3X1Q8Ir+wJEWK9gLuvt56htln71YQdn1OtqwRxNweeu1xwT8ow5t5AvrMm3m0+odTrECNU6ejVV9pcZpKgzqNevgYsYKPt9SrODyn/FYQcqcj7EChOdYgcH/PsUKUEbqxgoeIx4xnpGyrjf4b4Nt+4OIbUuNFRj8Hx4GsQLUd7YFng3OnrJ2k/UWx+ZQxQq+mRgr4Lhm07GCnyTGCr7TUKwgvKFX74lFiBWgHeBYgZpzlJypWAHOoVzP7EDNtXRyrMDwT4TBNleJFSj982IFFe3mQqxArXHUOGCsQK1FENfhGCso6ldeu6uYZtn1BtuPKrGCn7QUK7igoVgByjv7DdiH7Dc8BrwonwfnbIR/Etiwf/SGfpxKlj0/ton1uofLixV8QcB/3qGNfGFdph3TycWOFaBfwLroxWiyJ6Wv1DhNETz2TVndfYzKcH5nvUbZxhgYy2dTsQL2B9TdBu87EeqMlbc+KTo7yusT5Qups0a7I3TQJuCY3Jj/5rNGz8v7ucinNto15X152+doitaDfHcGbTefecE+xvtIPDfgHZdTaW7AWBSfyVDnQ9U6mWUv9o0SPk9m8K+AMT79PI0TefDuf5WVZ2xDXXlG3biG2mrwr11ceT76UMszyyzKM8eElDx3wqANqxPPOf4wlP+zfo7kf81hLv9qLeHJf1GMhOUf/bdDIf/PKiH/jzo0lfxb22Lyj/FEhL/YkX/Vv578F+0RevL/OSrDersjdFD+cdxZ/g3+ikT5N9ptyD/2Ecu/t27KnrJrHd4TQP/dk3/er21K/sdKyL/neyv5t7bG5N/wcbz8ekf+lQ569xjL7nVhGx6jMqy3O0In5s+z/Bv8bKL8G+025L/J9WtRnIH9edQNT/55n6Mp+f/haQd/qzvuHBsqe4/dy11h7VB3NtV9AL6z+WmIDe2itbfykbwciU2seT1cnn4W5cZg2io3BvMSBJ9Wr8X7X2Nt32tVfaXGaYrgsW+UbvEd99R7JXxXReWuUPKp7rin6i7ecb/9tH689xTgLZvDlXPQqByuSv+9nBAp99iVrLPd4BxIDM970Qb/YD4Wtr+BMlJC1uVeNOeqwXv4Sr55787gfx9s22cjtm2sJM7HEufZhnLVjLadq6bIbrLeqrtpHfobcan9G9az8aDXupyXxeB/V/h1yh5xPg6Vr0nZI75zhzqDe9Hfy/ngO7rZ72mA+xrJHto0thfZE8vF+H2Q53+b/27SbnA+LJXrwJtzlJxNifo4h3I9swM174An70Ub/okw2OYqe9Gp+elq2s2FvWgVJ1TjgHvR6g4t4vL2otu0a9hPKXZN5c+YCoNtZH1GG8F2AG0E24/UXP3oi3+PdL8ofw77LOobTxneT9B6A/XLy+eUco9dnZljv+FB4EX5PDhnI/yPwIaNnt2PU8my58cW3TPn/EHqnrmHy7tf790VVbTVvR3mJYS4TipdtL5pY72BfgHrYtGebEpfqXGaInjsm7K6y/vb6h670l2Mv7N8en5+9rDu3iN4RX9guaBfde7mnAqo18gHt5FtEOJln3/52b16z6a+aTo/Ba+Zyuan8HLxFdkNpj3MT9EPr8ZpKgzaQD4rovK1KN3lGIPKnWJlas5R8qlyy6TOu5hbZg3FCprOA+nlq+Wzol7+SNR/thvKN1KyznaD/UOG51iBwb80HwvzP1FG6sYKeB7HOzdKvnltZfCngm07LmLbxkrifGWOpyhW0NA8Ptr2PF5kN1lvcWx4/ajmUuxTjhVYH40HHacwfBzfnoEx8GIF7C946wAVv1P2CGMFl+R8cDw3+z0NcKeT7FWNU10G8nxm/rtJu+H51nxuVc05Ss7U2UCcQ7me2QGzKyiLbcQKDP9EGGxzlVhB6tq9pt1ciBUoP1yNA8YKsE9V/h4vVtCmXfNioEX9ymt3bCPrc2o8ke3H3Q49tBHoi1+SsN5I9VlwvXEGxQq83M9ePnkvf5xaz/G8ETvTFLsn+z6wYbPUN03n1OJz+GVzankx9qI7ul6eoWFOLT1O6s6Jl1PL012OMeD8znqNso3ny2cj8za2Q+2FKH8A5/zTae7GWAF/96JsPEDpPPtpyvdV3x1g3/efg+5ubTnOl7Je93B567WiOB/THsb5+uHVOKXE+fC7FxwrSNVP1nmU7b4cMC3FCpZRrEDZBE/2is7TsOyl3iFhu1E2HqBkne2GjSfGChCeYwUGfyfFCirmkZKxgs8SjxjPUPIduxP8O2Db7onYtrL3jO9PjBU0dH679F1QzwZnT1m7yXqr5vgO/Y241B0w1rPxENy7E7xm/oITK0B7xHFNtEccA7lH0FX2CGMF36ZYAeruNMB9iWRPxfXR5rDsGfx3QZ6/Qv5GE3aDzzipmJE35yg5U/u8OIdyPbMDNdfSybECwz8RBttcJVag9E+td2razYVYQWr+PYwVqLUI4vJiBW3aNW8/pKhfee2ucr4oG+HtYbD9uMehhzYCffFvk+4rG5nqs+B5hQ7FClC/WP/LxgPU2pr9BpVPVuUm4nyyfwU27O+pb5Qse35s0Xrdy++ZklOrzr0nL19IUU4tpZMt5psYazvnblFOLfb/vZxaqbrLOe9UPEDpLsbA/j4yb2M7VLxS+QM453/pCI0VjJ/Tq/fMc/pxDmMFg3wOYwX9ZYsZK2D5bCpW8Hun9uMdxgp6v2OxgufnY3E4xwpWgG17YcS2lY0VvDjHM4wVHLpYwQkwBocyVvD2nI+iWMGJJHtVYwXvBHk+Kf89jBXIZxgrIHrDWMGhiRW8nXS/qVjBb+c+y5EWK1gHNuwD1DfDWEFcJ4exgnK620Ss4AOReRvbUSVWcCLN3dgm7wwy3xFs8g4CnteI3UH4EOjubdQ3Td9B8M5GpdxB2O/QLopTMO3hHYR+eDVOKXcQcC7bT2XqHlCdOwgsn/tFO1K/b7sf8H6IYgVqPvdkr+gOgncHybuDwHZD5R04VHcQdlKsoKJP3+odhMfAtu2O2LaydxD2JcYKhncQBvu0qTsIDzmxArRHHOdAe9TEHYQ/pVhB7A7C50n2qt5B+CbI8xfJ32jCbvBaYXgHIZne8A5CqG/XFusOgtpDUzaiiTsIf0q6r2xkqs+CdxA+QLECb29C5R04VHcQvgM27MfUN8M7CHGdHN5BKKe7TdxB+HFk3sZ2VLmD8PmEPc/9Am+H+EV4tCFl86lxbDE1n9qdETpoE3BMPpz/5jxMP030qY12TXkfL5srR60HvThI0XqQ99TRdnNuHXUHzXhW+/RZ319I69lOXoZrvOPh93FQjvC/dO7B/81vwHaW6O+zJ6FOAByIe7Qi7g7hC0H7eejTKHrZMyHKRhN4edGNv/HiY68fe1mH6hsv/I7lZUzAXyLgra/GiffpkPScpXTKaFvZKJSxH4h6YTxkuvRC4m+sIn8p/Yf4pwT8ubM9uDJjcUzolwWUd7N9mPNmK5WhzWR7qmymFwtmu1M2B+1zz+3V+yfn9uM83HLQejnSvbimoq3WmMxLCPG5WenHz2MO2q1Qxnmhcc5hvw3nqnuoDGUb/QSWz9TvCKkctPj9mBNoDlQ+kyd7RT4Ty16qz8R2A/XfO1OaEtNhPSubg/ZUmu8rxkJazUH7drBtZ0RsW9m42lk5nmEO2kOXg/bNMAYc00V7xGs+tEdenCc1B+31OR9FOWgvINlTax+0ObEctL8J8nxh/rtJuzHMQTvMQXsAef7/z2oOWrQRbAfQRrD9uNOhF8tBez3pvrKRqT4L5qB9CcV0Ub9Y/1HHWf/LxoJ53iibg/ZmsGG3U980fd/E26Ma5qBdeI6oHLSpustx29RYMO7H3B6Zt7Ed6kxoUQ5a9ge2Cbwq33UnDNqhlJiud08GaanzaOwTYL2tETqxGATHdA1+PtGnNtptxHSxj1jelc327gOp9SP6yry+VvF1Je9G03jeK3Bmff8LNDfsArg7Qn/ZPijjs0coB5yPTMmPJwdzoo0sBw/A3PDlhHlzH7wrOwZz1B60Afck4Nrl0C6KBzBtFQ9gXoLg0+opXbG+aWNuaFJXVF+pcVLrCJ437oCyXVSWmv+Y9Q9lG79bxPK5S7RjDt7x3DAneD2w33dKP151btGTPTU3oB6z7O0T7VP6z3bD+8YayijbDRxbthsYow4CnmNRBv91ikWhjNSNRfG6F2MSSr557W7wfwW27U8itm2sJM7HE+dNG8c21myo72wLPBucPWXtJustjs0+wrVP4MI+ZZ/K+mg86P1owzdK8E84sSi0R953ULxvt+2jMtQZjEU9afXB32q/dxrgfkCyhzaN7UX2sOwZ/FGre/V+SLGoJuwG+6RoB/gsgZpzlJx5sT4lz2YHzK6gLLYRizL8E2GwzVViUUr/1Hcca9rNhViUOvugxgFjUWqNhLi8WFSbdg37KcWuebEhbCPrM9oItgNoI9h+7HHooY1AX9xshGcjU32WfYD3/txnUTrO+o86XvfbrDxvKBvGczbCHwM27LnUN01/W4Ljbioe7uHyvr9atO/uxfx5r5tj8UonlS5a37Sx3vDiwmXPW6m+UuOk4sgcN0rVXY5T4fzOeq2+zark0/Pzs4d1V90xVP7AJoF3QuA1+DnANUI4st835r9HCf5X8vag72o4twgelsE7HtOtAn4LwBg/y8OgHeNYOdZbn/9W8m5wbXzLG9vD8q5ihQjPfbNdwGNMzsZ2iuCxn6xsPZQZzUnCg/2dycQfnNTPz2bBD44ty9cWwDVCOLLfOfiCfBn8Cke+lLxsgHfch16fIz9KhvjsB9az/lXyZXA15Wu5ki9sD8uXJy/Zw33TFfAoQza2UwSP/WRlqJdGc5LwYH9nMnHDif1waL86kf+NV37H6wTEZWcF2Rdqgg6229Z0RmcjlE3nv7N2r6X5APtkRNT9YP57lOCvBB/ozfnv5aL+HNW3sreBnl12Xrw+22CcIyaoDPsDbU6snQg/G2nnu4DPS5xYifFVU++mlN6h7Uux6whf1q6z7Uad3Ei4Ngpcah3APsJ40GNg+EYJ/j0wBhwrwfljM/G+viTvaj5RdsTqZrK0Ircjy8PgHLOFaKo5TI3VlKi/OYJrieAf9ZbHfSTo+ZDhTSYwXqns8yjB/waM1RXnaZwhwsPGCM/jEfhtxIPB3yDkxbMDKP9bCafB3wg4X1kS529GcN7k+BpKT9G/LTufsj+B/dilMuSd58XtQJ9h/z+ij2Uo50w3OPzynFrEL883VrYR5qtP5L+XEr6StnrEG6u3C35Tx2qj0z7GZfXwXk2KjmB/fGa1xjlWEuftYk5XvspxgH9jxB/JHvZHsoftMtoM1MO15JMg/Q3Ev80T24Q+qrnecNWb6zt/rub69QDBc73qG4Rnm6DWwziO7GPjfPNSKtsAZexbrRd0UudSq5uN2TNO7Mc75+DNfr+b+Cjy8a7Kf7MdvrtkTMHr86KYAu+j4nhwTEHJ7GLLI7af5dFra/aUXQ+zPKr5Q8kj+1me3GSPJ48Yl5og3w55NfrKRjM/RT73MoLv5n+PR+DZ5hv8v3L8nnnBg7dO2CHg5wXPy4kHrMu0US+xT94w298eg//Xifa4oZjHMUr+sd9Y/r0+yh7u050CHvvK+mSK4LF/lfzPU5mKI3k6m6obVjcbx++s7MfbdHyObbXB/1nJ+Jxnq9uKz3m2uk1ZPVzjcyirqfG5Pyb5Ujbdi70qeZwT/Ku4Eo871lsVivmaE3xNifoYx+V6ncj/RoffebHBVdSezU57ysYosP5mas/mBtujeC6Kdf4drS2UzcG1Bc9DBn/MG3v1/ldCrLOsTGEMC2FVbCd71syGhfZnT/O+oN5PXUxfkP09nMdSYnkoezinHYCZ7dVvaD9O9hfqM/eXZ5+yJ2VdoWJn6vz3JipDeZsjOk3FRfetLOZ/k9PeIvngGMlhtHd2yOdmloUulKXsnbG9RDrKXvIYo33FceG9JIN/dm5flU+n5MCTm6K1lvGjZGM7lan4e4s25LCWm61UpuKBqXLjxfBwjrb5W9k79ClxnkR5RvjYvscc4enQ+6PgPdb7DWoz+0iM+wMEb+0cj8AbPvZFTgBdOd2JVSmc1xMPWwt42EI8GPzrBA9e/2eP5xMuDYO6WPYcKeIzfvAd4p8IWj6mQ9LT4f4zekoOsod1WemT2sPwbKDS8xRfqQ4u7zzUSqJTdl2E9eccOjM16cwIOm2vv1YSna0N0kGdmSE62xqkg3IwTXS2N0gH5yM+07JM8JDNE+94Y+89zlvoh6APy3cTDP6ONb1678pxqjUz8oj18f7RZtEOpndpTsPs3zzUKWGP5P0jw1XUd5dR36k9FK/vDP6j0HdXOH3Hut2FMt7/wP5gnx7jpogDy0IYjLNmD8sc1je4SVGP56ud8L7MWjFFNxD/RBhsc5X5SsWfu/CO73XcUY3ewr2OXYKeGge814F9qu5lmo4pO8sxA7SNO6gM7dk8laF+Hwe/kUasTebbLnf4U34o+m4q3sKyt9i+0pZq9FxfScWHyvpKfC7qcPWVkE/2lcrGXLH+ZofOTE06M4JO27Hdoa+UTqeKr7S1IV/pBTDfd2m+R1uR4ittEe1gersOA19pD/Wd2k/w+s7gl0Hf7Xf6jnW7C2VDX6l/DIe+Uu93zFdS/kabvtKWgjaxr6T4U/5O9kyHtCfFl8L2lRi7Z6fKpuFvypdSfonypax926vRm85k7ai8Hvqxvwq/1bkkHK+mxk/FZg7V+M1Vo+eOn4pZNTl+qFtlxk/p5gnwG8uwPZ5fifUXy688gejE5vg/oTle7WnhHM9nBgz+L+HMwOM0x6szL965gBb3+UfK3jfyzhRnT9nzsLaPo+YhPmOk7vp0wuCYqPNBvOe0QdDJxmpDZN+6A3g/KOqybiP8VsGHwfMdF4bh+ygG/wPYgzkhcg4udh8ltg/7Q2cftu37KNjPXSrDet4+rMHV1IlnK53oAgDrxDyUeb6iwaeerZ0ieO4npV/Zg/vyLJ+K17kavPI44ljtIFyYa1Cd6WC5XJgn8/VS0Tngbv6ujfH39uFVn3r78EV9yvEu74ywtw/f1FnfP1nkNSrHDHYCLyOCV8M7SvBPgXX289b047T1UghpOqvWZ7jm4vOkuDbblYDLs6W7BfwuhzbyhXWZNvNp9VrULXlODtfarFtqnBA+pa/UOKl8K5z7MXW9vJPKUtfLJvNKPotymXi6i3EpjlnNC7ye7DVxD0TpP9sNNccpXWK7gWPLdoPjIAzPsUaDPz4fC1t/oYyUkHUZa9xNPN4BPCj55hiiwb8ebNurIrZtrCTOVyfOszaObeRPQ31nW+DZ4OwpazdZb3FsuoSrK3Bhn7Jfb300LuARH995OgXGgHMdoD26g3hPjd91qUztIWRyc3nOB9+Dyn5PA9xZJHto09heZA/LnsG/B+T5nPx3k3aDz3aiHWA/Vc05Ss6Uf4ZzKNczO2B2BWWxjZi44Z8Ig22uErdKjVHXtJsLMfE9gp4aB4yJY58ifcPl5YWcB/4PwM5W41/ZNeynFLum4uRTYbCN3dBfhjaC7QDaCLYf2xx6aCPQF7+cdL8bBtuR6rN0Ae9WWm+gfrH+o46z/qO8s9+Afch+w27gRfk8OGcj/PvBhn2Y+kbJsufH7hXwmP9vntqDsr43AdcOh7bK77nXoa3yDjMvIcR1Uumi9U0b6w30C1gX1Th538hQfaXGaYrgsW/K6u5uKsP5nfUaZdtkXsmn5+dnD+vuvOAV/YHFOvvXVKzgk6C784d5rMCLtw9jBTk/odjGNhkrSD2H2ESsgOUz9e590Z3ryxJiBW3njFD6z3bjcIoV3HsExAq+DLbtgYZiBQ8PYwULZV3C1RW42ogV/EsnVoD2qO1YwX9KjBX8XkOxgr8Eef6qEyuoajeGsYJhrOAA8vz/n9VYAdqItmMF/6mlWME7nFgB6//hFCv4r2DDwtp+nMNYQVwnh7GCcrrbRKyA5bOpWAH7Awhnc9T5s713mE+Hdd3jw+BNTmJnrawuxwaW5u3Hs1bqXJDhytp21FrdNrQTXeB/B9E2+Bes7dU7Ov+tfB3Oa6F8nRAG7TKP52mzQfbB04GPp6yN0zIZmnTamOF4xloNhzwgHONYEgb7wHCoPHi8vuwKngPhXCJgmcZ2UU/R2EY4sc/Qtqs4hCrfKdoWxLslAn4+6PYGQXtHAd6uwKNsjWej2KfuhsH2Ys4Xti8qN3QmO6/Jz3IqfYnphJKreYf3ncT7vOC96/DeDQcfthFHkY4hTb7LwLKFsLHzgmgz3w/v2MaqHOwIY3X5fOorhM1knLFzgFdGcP4TwMnnU7uh9xjOV8I7nou9cUJ+1LnGeaqncggF8U6Nz0aC7cLv7DFbqGR2a4QO94fiwbtf693fK8rj5ekmnil8Hukm+jOcc34z8Y6wnCuF72awfPN5WMzDo/YLWL4N/vWOfKt7gcjXlRGcb3DkW/X7K+Ady3dR/jReG6n8aYp3tD38To0PyzffA0L55js+cxE6SvaZB7XvZPK9KYKTaZZdl2Lu6IdXHPztfR+M5QVpqjN5U6I+52gyHi4AWeLvVahvr3l3Wgz+Qkc+m86TznsF6ttrqh6O31JBa9p+/NR/DJ/pwpNCXAb5vPq7oZ9OOU/z0mF+Cp4W7zFOdwhfCDpGeITeYzy2iXuMfDeqA/QzPbqa1ntKx7Dur+W/Wcc+AOus6yI4Q6hnm7at6MfbVu5WpbspebO979AYD8qHRHjOH27ws6Cbl7SeU77zIxVTQh9xbDb0tasLZSMCvqwfy9/RmYeymO+EuFSsl+Um9p0C/haPwX8cxoD3rfBeHt912VSS91gOYNZF1A3WY/VdUy+vfdF3Td+d/2a9X+/MrU1/98XL48dxJJVjWOmLwbWRA/Vw+QYJ+5Eqb6myvfhd05vJ9qp8yzi2LF+Ia0TwcXn+m7+ht9uRr6J5hfuwKLc+52ZOzYPe/jduwlMO9X1nG1sVS+I83WgL+Z68+rZhJhMXk3ypeRLrvif/zfPkIyVjLZ7OzQv4LsAYP16sRcVUWZZwbuO4l3fWIPv9vvw3nzX4F4n+Qjd/V1M+V5XdD94JZSn7dd4ZOeyTKYLnccG/EReONduubv5+POgxiH3X6KuOv5B6ZjaFd2V3lb6hTv3D6w7+Vut89lm979NwXZx7xiPwsfXnN0R/sT2LxV6vIJwG/6eOPVBz6u3wjmWwKEc7x15VPFKtH7zcAM348+GkQ52jneePLpTxHdWyOdpT5R9l6Psk/zif30Y0PT+W6yKdmPzHcqT/wJH/onX5OsJp8D8sGfvy5L/IR/B8JC8vj9mbFv3zUw+1f87y7/nnZeO8qfKPMvT46/rxqvzJWPey/DfnTw55n6bKF64bqvqgSoY828vxGeW78jjG5hlepxj8UugHz99q6JsbTz3U9pz33rpQxjmOlP30cgsp+6nmS7afT4Ux8OIzHFvaVJL3VH1DnfoKzTe49uX5ZpNDk+uiXsfmG8PHc8Mvif7qEI1YPIjnG4OfduyBsl3efFO0Xud4kPqmslrLe+t1g6upn09r+7taRbEynm/QHvL3clA3Ur6rlSr/KEMP5PJfr18/cAD+AC+zPdwjAtLwjxL8K/IxwZxs9v9oAh9/N//f79119ze+yvdessfG6Kga+H/w+hu2rP6jWz/TFv4XfOTT953+rZ+c3Bb+L//q756//MlhSVv4l3Ymr/vpL73nobbwP/HaH/3PG04cuakt/OcveeIXH/7H+7a3hf/UPV99/zNXPfH0IvzL89/js71ytIPZ86T8b7u3xfCGb5Tgz8l1LNPN1eQLjQl6Gdy7HLhO5P8DOMS70dn+dxOzg/Ajs4PwRvuo2UEerWwZlKENPwCT/439hbgmoBzh35G33cZkKdSx+lOC/lKi38e3eIdzCOMaEe8MPhufN5HdxLaX3UPPnnGqj++YtslGHb24+ss73zb5Fx+8vC29O/eDV1615hvf/WZb+L9zzN+e9ZF/NfWttvBfetHH9n7lD9d/rS38X/vVc75w0WmvOLot/C/+j097xsYnzr6tLfy//d6Jl39zz5PeXYT//wCrWz8KJCsMAA==", + "debug_symbols": "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" + }, + { + "name": "public_dispatch", + "is_unconstrained": true, + "custom_attributes": [ + "public" + ], + "abi": { + "parameters": [ + { + "name": "selector", + "type": { + "kind": "field" + }, + "visibility": "private" + } + ], + "return_type": null, + "error_types": { + "206160798890201757": { + "error_kind": "string", + "string": "Storage slot 0 not allowed. Storage slots must start from 1." + }, + "2024020833944022298": { + "error_kind": "string", + "string": "Function add_to_tally_public can only be called internally" + }, + "2233873454491509486": { + "error_kind": "string", + "string": "Initializer address is not the contract deployer" + }, + "3557153117338734214": { + "error_kind": "string", + "string": "Vote has ended" + }, + "5019202896831570965": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "8095637994846897154": { + "error_kind": "string", + "string": "Only admin can end votes" + }, + "10492081608786484886": { + "error_kind": "fmtstring", + "length": 27, + "item_types": [ + { + "kind": "field" + } + ] + }, + "13699457482007836410": { + "error_kind": "string", + "string": "Not initialized" + }, + "14225679739041873922": { + "error_kind": "string", + "string": "Index out of bounds" + }, + "17618083556256589634": { + "error_kind": "string", + "string": "Initialization hash does not match" + }, + "17843811134343075018": { + "error_kind": "string", + "string": "Stack too deep" + } + } + }, + "bytecode": "JwACBAEoAAABBIBOJwAABAMnAgIEAScCAwQAHwoAAgADgE0uCIBNAAElAAAARSUAAACaKAIAAQSATicCAgQAOw4AAgABKACAQwQAAygAgEQBAAAoAIBFBAAAKACARgAAACgAgEcBAAEoAIBIBAABKACASQAAASgAgEoEAAIoAIBLAAADKwCATAAAAAAAAAAAAQAAAAAAAAAAJiUAAAqqKQIAAgA1OT3zCioBAgMnAgQEACcCBgQDACoEBgUtCAECAAgBBQEnAwIEAQAiAgIFLQ4EBQAiBQIFLQ4EBScCBQQDACoCBQQkAgADAAAA8yMAAAZwLQgBAycCBAQCAAgBBAEnAwMEAQAiAwIEHzCASIBIAAQtCAEEAAABAgEtDgMELQgBAwAAAQIBLgyARQADJwIGBActCAAHLQoECC0KAwkACAAGACUAAArTLQIAAC0KCAUBIgAFgEgABC0LBAMeAgAEAC0IAQUnAgYEAwAIAQYBJwMFBAEAIgUCBjYOAAQABgABIgAFgEgABy0LBwYBIgAFgEoACC0LCAccCgYFAAQqBQcIJAIABgAAAbUnAgUEADwGBQEtCAEFJwIGBAMACAEGAScDBQQBACIFAgY2DgAEAAYCASIABYBIAAYtCwYEASIABYBKAActCwcGHAoEBQAEKgUGByQCAAQAAAIHJwIFBAA8BgUBLQgBBCcCBQQCAAgBBQEnAwQEAQAiBAIFHzCASIBFAAUBIgAEgEgABi0LBgUcCgUGBBwKBgQALQgBBScCBgQCAAgBBgEnAwUEAQAiBQIGHzCASIBIAAYnAgYALC0IAQknAgoEAgAIAQoBJwMJBAEAIgkCCi0KCgstDgYLJwIKBAstCAALLQoJDC0KBQ0ACAAKACUAAAswLQIAAC0KDAYnAgkECi0IAAotCgYLLgiASgAMLgiARAANAAgACQAlAAALey0CAAAtCgsFLQgBBicCCQQEAAgBCQEnAwYEAQAiBgIJLQoJCi4MgEYACgAiCgIKLgyARgAKACIKAgouDIBGAAorAgAJAAAAAAAAAAADAAAAAAAAAAAtCAEKJwILBAUACAELAScDCgQBACIKAgstCgsMLgyARgAMACIMAgwuDIBGAAwAIgwCDC4MgEYADAAiDAIMLQ4JDC0IAQkAAAECAS0OBgktCAEGAAABAgEtDgoGLQgBCgAAAQIBLgyARQAKLQgBCwAAAQIBLgyARAALJwIMAA0nAg0EDi0IAA4tCgkPLQoGEC0KChEtCgsSLQoMEwAIAA0AJQAADSotAgAAJwIMBA0tCAANLQoJDi0KBg8tCgoQLQoLES0KBBIACAAMACUAAA0qLQIAACcCBAQMLQgADC0KCQ0tCgYOLQoKDy0KCxAtCgURAAgABAAlAAANKi0CAAAnAgUEDC0IAAwtCgkNLQoGDi0KCg8tCgsQAAgABQAlAAAOSC0CAAAtCg0ECioHBAUkAgAFAAAEWSUAAA68CyIACIBGAAQeAgAFAQoqCAUGEioEBgUkAgAFAAAEfSUAAA7OMAIAA4BJMACARoBLHgIAAwUnAgQABC0IAQUnAgYEAgAIAQYBJwMFBAEAIgUCBi0KBgctDgQHJwIGAAYtCAEHJwIIBAIACAEIAScDBwQBACIHAggtCggJLQ4GCScCCAQJLQgACS0KBwotCgULAAgACAAlAAALMC0CAAAtCgoGJwIHBAgtCAAILQoGCS4IgEoACi4IgEQACwAIAAcAJQAAC3stAgAALQoJBTQCAAUcCgMFAC0IAQMnAgYEBAAIAQYBJwMDBAEAIgMCBi0KBgcuDIBGAAcAIgcCBy4MgEYABwAiBwIHLgyARgAHLQgBBicCBwQFAAgBBwEnAwYEAQAiBgIHLQoHCC4MgEYACAAiCAIILgyARgAIACIIAgguDIBGAAgAIggCCC4MgEwACC0IAQcAAAECAS0OAwctCAEDAAABAgEtDgYDLQgBBgAAAQIBLgyARQAGLQgBCAAAAQIBLgyARAAIJwIJBAotCAAKLQoHCy0KAwwtCgYNLQoIDi0KBQ8ACAAJACUAAA0qLQIAACcCCgQLLQgACy0KBwwtCgMNLQoGDi0KCA8ACAAKACUAAA5ILQIAAC0KDAkwCgAFAAQnAgMABTAKAAkAAx4CAAMANAIAAwAiAgIFLQsFBCcCBgQCACoFBgM7DgAEAAMjAAAGcCkCAAMAXwZhfgoqAQMELQsCAwAiAwIDLQ4DAiQCAAQAAAaYIwAACI4tCAEDJwIEBAIACAEEAScDAwQBACIDAgQfMIBIgEgABC0IAQQAAAECAS0OAwQtCAEDAAABAgEuDIBFAAMnAgYEBy0IAActCgQILQoDCQAIAAYAJQAACtMtAgAALQoIBQEiAAWASAAELQsEAx4CAAQAHgIABQAzKgAEAAUABiQCAAYAAAciJQAADuAeAgAEAR4CAAUACioEBQYkAgAGAAAHPiUAAA7yLwiASwAEHAoEBgEcCgYFABwKBQQBCyIABIBEAAUkAgAFAAAHaCUAAA8EJwIEAAItCAEFJwIGBAMACAEGAScDBQQBACIFAgYtCgYHLQ4EBwAiBwIHLQ4DBycCBwQILQgACC0KBQkuCIBKAAouCIBEAAsACAAHACUAAA8WLQIAAC0KCQYLIgAGgEYABQsiAAWARAAHJAIABwAAB94lAAAQxS8KAAYABQEiAAWASQAGLQgBBScCBwQDAAgBBwEnAwUEAQAiBQIHLQoHCC0OBAgAIggCCC0OAwgnAgQEBy0IAActCgUILgiASgAJLgiARAAKAAgABAAlAAAPFi0CAAAtCggDCyIAA4BGAAQLIgAEgEQABSQCAAUAAAhdJQAAEMUwCgAGAAMtCwIDACIDAgMtDgMCACICAgUtCwUEJwIGBAIAKgUGAzsOAAQAAyMAAAiOKQIAAwDyGfv/CioBAwQkAgAEAAAIqSMAAAjeJwIDBAQtCAAEAAgAAwAlAAAQ1y0CAAAAIgICBS0LBQQnAgYEAgAqBQYDOw4ABAADIwAACN4nAgICVScCAwJuJwIEAmsnAgUCbycCBgJ3JwIHAiAnAggCcycCCQJlJwIKAmwnAgsCYycCDAJ0JwINAnInAg4CeycCDwJ9LQgBECcCEQQcAAgBEQEnAxAEAQAiEAIRLQoREi0OAhIAIhICEi0OAxIAIhICEi0OBBIAIhICEi0OAxIAIhICEi0OBRIAIhICEi0OBhIAIhICEi0OAxIAIhICEi0OBxIAIhICEi0OCBIAIhICEi0OCRIAIhICEi0OChIAIhICEi0OCRIAIhICEi0OCxIAIhICEi0ODBIAIhICEi0OBRIAIhICEi0ODRIAIhICEi0OBxIAIhICEi0ODhIAIhICEi0OCBIAIhICEi0OCRIAIhICEi0OChIAIhICEi0OCRIAIhICEi0OCxIAIhICEi0ODBIAIhICEi0OBRIAIhICEi0ODRIAIhICEi0ODxILIIBEgEcAAiQCAAIAAAqqJwIDBB4tCAEEJwIFBB4ACAEFAS0KBAUqAwAFBZGbXKI+IJ6WACIFAgUAIhACBicCBwQbLgIABoADLgIABYAELgIAB4AFJQAAER8nAgYEGwAqBQYFLgyASQAFACIFAgUtDgEFACIFAgU8DgMEKACABAR4AA0AAACABIADJACAAwAACtIqAQABBfeh86+lrdTKPAQCASYlAAAKqi0LAgMtCwEECyIAA4BFAAUkAgAFAAAK9SUAABFlASIABIBIAAUtCwUDLQgBBScCBgQCAAgBBgEnAwUEAQAiBQIGLQoGBy0OAwctDgQBLgyASAACLQoFASYlAAAKqgEiAAGASAAELQsEAwEiAAKASAAELQsEAS0IAQInAgQEAwAIAQQBJwMCBAEAIgICBC0KBAUtDgMFACIFAgUtDgEFLQoCASYlAAAKqhwKAgUABSIABYBMAAYtCAEFJwIHBAQACAEHAScDBQQBACIFAgctCgcILgyARgAIACIIAgguDIBGAAgAIggCCC4MgEYACC0IAQcnAggEBQAIAQgBJwMHBAEAIgcCCC0KCAkuDIBGAAkAIgkCCS4MgEYACQAiCQIJLgyARgAJACIJAgktDgYJLQgBBgAAAQIBLQ4FBi0IAQUAAAECAS0OBwUtCAEHAAABAgEuDIBFAActCAEIAAABAgEuDIBEAAguCIBFAAQjAAAMSQ0iAASASgAJJAIACQAADMkjAAAMXiQCAAMAAAxrIwAADJ0nAgEECS0IAAktCgYKLQoFCy0KBwwtCggNLgiASQAOAAgAAQAlAAANKi0CAAAjAAAMnScCAgQJLQgACS0KBgotCgULLQoHDC0KCA0ACAACACUAAA5ILQIAAC0KCgEmDCoEAgkkAgAJAAAM2yMAAA0ZACIBAgoAKgoECy0LCwknAgoECy0IAAstCgYMLQoFDS0KBw4tCggPLQoJEAAIAAoAJQAADSotAgAAIwAADRkBIgAEgEgACS0KCQQjAAAMSSUAAAqqLQsEBgsiAAaARAAHJAIABwAADUwnAggEADwGCAEtCwMGCyIABoBDAAckAgAHAAAN2SMAAA1lLQsBBy0LAggNIgAGgEMACSQCAAkAAA2CJQAAEWUuAgAHgAMoAIAEBAAEJQAAEXcuCIAFAAkAIgkCCgAqCgYLLQ4FCwEiAAaASAAFDioGBQckAgAHAAANwiUAABIFLQ4JAS0OCAItDgUDLgyARAAEIwAADkcnAgYEBy0IAActCgEILQoCCS0KAwotCgQLAAgABgAlAAASFy0CAAAtCwEGLQsCBy0LBAguAgAGgAMoAIAEBAAEJQAAEXcuCIAFAAkBIgAJgEgACi0OBQotDgkBLQ4HAi4MgEgAAy0OCAQjAAAORyYlAAAKqi0LBAULIgAFgEQABiQCAAYAAA5qJwIHBAA8BgcBJwIFBAYtCAAGLQoBBy0KAggtCgMJLQoECgAIAAUAJQAAEhctAgAALQsBBS0LAgYtCwMHLQ4FAS0OBgItDgcDLgyARwAEASIABoBIAAItCwIBJioBAAEF9IABplnTJ0I8BAIBJioBAAEFHwBQEkAkIu48BAIBJioBAAEFvh4//z6k9vo8BAIBJioBAAEFHBbEOYk5LRo8BAIBJioBAAEFMV2L6eKmDoY8BAIBJiUAAAqqHAoCBQAFIgAFgEwABi0IAQUnAgcEBAAIAQcBJwMFBAEAIgUCBy0KBwguDIBGAAgAIggCCC4MgEYACAAiCAIILgyARgAILQgBBycCCAQFAAgBCAEnAwcEAQAiBwIILQoICS4MgEYACQAiCQIJLgyARgAJACIJAgkuDIBGAAkAIgkCCS0OBgktCAEGAAABAgEtDgUGLQgBBQAAAQIBLQ4HBS0IAQcAAAECAS4MgEUABy0IAQgAAAECAS4MgEQACC4IgEUABCMAAA/kDSIABIBKAAkkAgAJAAAQZCMAAA/5JAIAAwAAEAYjAAAQOCcCAQQJLQgACS0KBgotCgULLQoHDC0KCA0uCIBJAA4ACAABACUAAA0qLQIAACMAABA4JwICBAktCAAJLQoGCi0KBQstCgcMLQoIDQAIAAIAJQAADkgtAgAALQoKASYMKgQCCSQCAAkAABB2IwAAELQAIgECCgAqCgQLLQsLCScCCgQLLQgACy0KBgwtCgUNLQoHDi0KCA8tCgkQAAgACgAlAAANKi0CAAAjAAAQtAEiAASASAAJLQoJBCMAAA/kKgEAAQUC3G4ngHYSnTwEAgEmJQAACqoeAgABAB4CAAIAMyoAAQACAAMkAgADAAAQ+yUAAA7gLwiASQABHgIAAgEKKgECAyQCAAMAABEYJQAAEyEwAIBJgEsmAQCAA4AFgAcuAIADgAguAIAEgAkLAIAIgAeACiQAgAoAABFkLgGACIAGLgSABoAJAQCACAACgAgBAIAJAAKACSMAABEzJioBAAEFxWvEWg4QAAI8BAIBJi4BgAOABgsAgAYAAoAHJACABwAAEZIjAAARnS4AgAOABSMAABIELgAAAYAFAQAAAYAEAAEBAIADgASACS4AgAOACi4AgAWACwsAgAqACYAMJACADAAAEfAuAYAKgAguBIAIgAsBAIAKAAKACgEAgAsAAoALIwAAEb8oAYAFBAABAwCABgACgAYjAAASBCYqAQABBUWnynEZQeQVPAQCASYlAAAKqi4IgEUABSMAABInDSIABYBDAAYkAgAGAAASkiMAABI8LQsCBS0LBQYAIgYCBi0OBgUtCAEGJwIHBAUACAEHAScDBgQBACIFAgcnAggEBAAiBgIJPw8ABwAJLQsBBS0LAwctCwQILQ4FAS0OBgItDgcDLQ4IBCYtCwMGDCoFBgckAgAHAAASqCMAABMQLQsCBwAiBwIJACoJBQotCwoILQsBCQAiCQILACoLBQwtCwwKACoICgstCwQILgIAB4ADKACABAQABSUAABF3LgiABQAKACIKAgwAKgwFDS0OCw0tDgkBLQ4KAi0OBgMtDggEIwAAExABIgAFgEgABi0KBgUjAAASJyoBAAEFcFl73SEBRAI8BAIBJg==", + "debug_symbols": "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" + }, + { + "name": "sync_private_state", + "is_unconstrained": true, + "custom_attributes": [ + "utility" + ], + "abi": { + "parameters": [], + "return_type": null, + "error_types": { + "576755928210959028": { + "error_kind": "string", + "string": "0 has a square root; you cannot claim it is not square" + }, + "1004672304334401604": { + "error_kind": "fmtstring", + "length": 48, + "item_types": [ + { + "kind": "field" + }, + { + "kind": "field" + } + ] + }, + "2920182694213909827": { + "error_kind": "string", + "string": "attempt to subtract with overflow" + }, + "3206131020419630384": { + "error_kind": "fmtstring", + "length": 75, + "item_types": [] + }, + "3305101268118424981": { + "error_kind": "string", + "string": "Attempted to delete past the length of a CapsuleArray" + }, + "3738765135689704617": { + "error_kind": "fmtstring", + "length": 58, + "item_types": [ + { + "kind": "field" + } + ] + }, + "5019202896831570965": { + "error_kind": "string", + "string": "attempt to add with overflow" + }, + "5727012404371710682": { + "error_kind": "string", + "string": "push out of bounds" + }, + "6485997221020871071": { + "error_kind": "string", + "string": "call to assert_max_bit_size" + }, + "7233212735005103307": { + "error_kind": "string", + "string": "attempt to multiply with overflow" + }, + "8270195893599566439": { + "error_kind": "string", + "string": "Invalid public keys hint for address" + }, + "10676044680617262041": { + "error_kind": "fmtstring", + "length": 98, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + }, + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + }, + { + "kind": "field" + } + ] + }, + "11732781666457836689": { + "error_kind": "fmtstring", + "length": 77, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "13649294680379557736": { + "error_kind": "string", + "string": "extend_from_bounded_vec out of bounds" + }, + "14101993474458164081": { + "error_kind": "fmtstring", + "length": 61, + "item_types": [ + { + "kind": "field" + }, + { + "kind": "field" + } + ] + }, + "14225679739041873922": { + "error_kind": "string", + "string": "Index out of bounds" + }, + "14657895983200220173": { + "error_kind": "string", + "string": "Attempted to read past the length of a CapsuleArray" + }, + "15200354114977654233": { + "error_kind": "fmtstring", + "length": 144, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "15760694058516861966": { + "error_kind": "fmtstring", + "length": 128, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "16218014537381711836": { + "error_kind": "string", + "string": "Value does not fit in field" + }, + "16446004518090376065": { + "error_kind": "string", + "string": "Input length must be a multiple of 32" + }, + "16954218183513903507": { + "error_kind": "string", + "string": "Attempted to read past end of BoundedVec" + }, + "17226037485472400844": { + "error_kind": "fmtstring", + "length": 132, + "item_types": [ + { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + ] + }, + "17610130137239148460": { + "error_kind": "fmtstring", + "length": 98, + "item_types": [] + }, + "17843811134343075018": { + "error_kind": "string", + "string": "Stack too deep" + } + } + }, + "bytecode": "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", + "debug_symbols": "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us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrPDuTztevnK1Jj0bTbFpNu8mavOk03ab2uO1x2+O2x22P2x63PW573Pa47XHbI9oj2iPaI9oj2iPaI9oj2iPaI8ojG5cejabZtJp2kzV502m6Te0x2mO0x2iP0R6jPUZ7jPYY7THaY7THbI/ZHrM9ZnvM9pjtMdtjtsdsj9keqz1We6z2WO2x2mO1x2qP1R6rPVZ77PbY7bHbY7fHbo/dHrs9dnvs9tjtYe1h7WHtYe1h7WHtYe1h7WHtYe3h7eHt4e3h7eHt4e3h7eHt4e3Rdb67znfX+e46313n2QJ1PMmavOk03aYoyjoHjabZ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bbptumWWLEuMxsySh4M4iYu4iUZ04iHSzejmdHO6Od2cbk43p5vTzenmdHO6Hboduh26Hboduh26Hboduh26Hbpdul26Xbpdul26Xbpdul26XbpdugXdgm5Bt6Bb0C3oFnQLugXdot3Q9/pwECdxETfRiE48xEuk26DboNug26DboNug26DboNug26DbpNuk26TbpNuk26TbpNuk26TbpNui26Lbotui26Lbotui26Lbotui26bbptum26bbptum26bbphuz5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMkuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWRLMEvS9rpN4iJcYjcgS4CBO4iJuohHptui26Lbotum26bbptum26bbptum26bbptulmdDO6Gd2MbkY3o5vRzehmdDO6Od2cbk43p5vTzenmdHO6Od2cboduh26Hboduh26Hboduh26Hbodul26Xbpdul26Xbpdul26ZJd9fupvoe30YjZkl+YfL0Pf6cBIXcRON6MRDvMR4uND3+nAQJ3ERN9GITjzES6TboNug26DboNug26DboNug26DboNuk26TbpNuk26TbpNuk26TbpNuk26Lbotui26Lbotui26Lbotui26Lbptum26bbptum26bbptum26bbppvRzehmdDO6Gd2MbkY3o5vRzejmdHO6Od2cbk43p5vTzenmdHO6Hboduh26Hboduh26Hboduh26Hbpdul26Xbpdul26Xbpdul26XbpdugXdgm5Bt6Bb0C3oFnQLugXdmCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZgr7X7y/5LvS9PhzEdLuJi7iJRnTiIV5iNCJLgINIt0M3ZMlMNKITD/ESoxFZAhzESVxEul26Xbpdul26XboF3YJuQbegW9At6BZ0C7oF3aLd0Pf6cBAncRE30YhOPMRLpNug26DboNug26DboNug26DboNug26TbpNuk26TbpNuk26RbZkn+XWT0vT6MxsyS93eOB3ES0y0SN9GITjzES4xGZAlwECeRbptum26bbptum26bbkY3o5vRzehmdDO6Gd2MbkY3o5vTzenmdHO6Od2cbk43p5vTzel26Hboduh26Hboduh26Hboduh26Hbpdul26Xbpdul26Xbpdul26XbpFnQLugXdgm5Bt6Bb0C3oFnSLdkPf68NBnMRF3EQjOvEQL5Fug26DboNug26DboNug26DboNug26TbpNuk26Tbrj3uhON6MRDvMRoxL1X4CBO4iLSbdFt0W3RbdFt0W3TbdNt023TbdNt023TbdNt023TzehmdDO6Gd2MbkY3o5vRzehmdHO6Od2cbk43p5vTzenmdHO6Od0O3Q7dDt0O3Q7dDt0O3Q7dDt0O3S7dLt0u3S7dLt0u3S7dLt0u3S7dgm5Bt6Bb0C3oFnQLugXdgm7Rbuh7fTiIk7iIm2hEJx7iJdJt0G3QbdBt0G3QLbPER6ITD/Fz85UYjZklDwdxEhdxE43oxEOk26Tbotui26Lbotui26Lbotui26Lbotum26bbptum26bbptum26bbptumm9HN6GZ0M7oZ3YxuRjejm9HN6OZ0c7o53ZxuTjenm9PN6eZ0c7oduh26Hboduh26Hboduh26Hbodul26Xbpdul26Xbpdul26Xbpdul26Bd2CbkG3oFvQLegWdAu6Bd2i3dD3+nAQJ3ERN9GITjzES6TboNug26DboNug26DboNugG7PEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmiTNLnFnizBJnljizxJklh1lymCWHWXKYJYdZcpglh1lymCWHWXKYJYdZcpglh1lymCWHWXKYJYdZcpglh1lymCXoe/WTOIiTuIibaEQnHuIlRuOi26Lbotui26JbZsmxRCceYrrNxGhElgAHcRIXcRON6MRDpNumm9HN6GZ0M7oZ3YxuRjejm9HN6OZ0c7o53ZxuTjenm9PN6eZ0c7oduh26Hboduh26Hboduh26Hbodul26Xbpdul26Xbpdul26Xbpdul26Bd2CbkG3oFvQLegWdAu6Bd2i3dD3+nAQJ3ERN9GITjzES6TboNug26DboNug26DboNug26DboNuk26TbpNuk26TbpNuk26TbpNuk26Lbotui26Lbotui26Lbohuz5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrMEfa83MbPk4SB+bnclLuImfm7fO9wX+l4fHuLndiMxGjNLHg7iJC7iJhrRiYdIt0O3S7dLt8ySsMRF3MQ/t7+nq4lOPMT7Ya7DlyUPvywpHB+exElcxE00ohMP8RKjMPteCwdxEhdxE43oxEO8RLoNug26DboNug26DboNug26DboNuk26TbpNuk26TbpNuk26TbpNuk26Lbotui26Lbotui26Lbotui26Lbptum26bbptum26bbptum26bbptuhndjG5GN6Ob0c3oZnQzuhndjG5ON6eb083p5nRzujndnG5ON6fboduh26Hboduh26Hboduh26Hbodul26Xbpdul26Xbpdul26XbpdulW9CNWRLMkmCWBLMkmCXBLAlmSTBLorNk/zpL9q+zZP86S/avs2T/Okv2r7Nk/zpL9q+zZP86S/bvR7dBt0G3QbdBt0G3QbdBt0G3QbdBt0m3SbdJt0m3SbdJ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" + } + ], + "outputs": { + "globals": { + "storage": [ + { + "fields": [ + { + "name": "contract_name", + "value": { + "kind": "string", + "value": "PrivateVoting" + } + }, + { + "name": "fields", + "value": { + "fields": [ + { + "name": "admin", + "value": { + "fields": [ + { + "name": "slot", + "value": { + "kind": "integer", + "sign": false, + "value": "0000000000000000000000000000000000000000000000000000000000000001" + } + } + ], + "kind": "struct" + } + }, + { + "name": "tally", + "value": { + "fields": [ + { + "name": "slot", + "value": { + "kind": "integer", + "sign": false, + "value": "0000000000000000000000000000000000000000000000000000000000000002" + } + } + ], + "kind": "struct" + } + }, + { + "name": "vote_ended", + "value": { + "fields": [ + { + "name": "slot", + "value": { + "kind": "integer", + "sign": false, + "value": "0000000000000000000000000000000000000000000000000000000000000003" + } + } + ], + "kind": "struct" + } + }, + { + "name": "active_at_block", + "value": { + "fields": [ + { + "name": "slot", + "value": { + "kind": "integer", + "sign": false, + "value": "0000000000000000000000000000000000000000000000000000000000000004" + } + } + ], + "kind": "struct" + } + } + ], + "kind": "struct" + } + } + ], + "kind": "struct" + } + ] + }, + "structs": { + "functions": [ + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [ + { + "name": "candidate", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "PrivateVoting::add_to_tally_public_parameters" + } + } + ], + "kind": "struct", + "path": "PrivateVoting::add_to_tally_public_abi" + }, + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [ + { + "name": "candidate", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "PrivateVoting::cast_vote_parameters" + } + } + ], + "kind": "struct", + "path": "PrivateVoting::cast_vote_abi" + }, + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [ + { + "name": "admin", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + } + ], + "kind": "struct", + "path": "PrivateVoting::constructor_parameters" + } + } + ], + "kind": "struct", + "path": "PrivateVoting::constructor_abi" + }, + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [], + "kind": "struct", + "path": "PrivateVoting::end_vote_parameters" + } + } + ], + "kind": "struct", + "path": "PrivateVoting::end_vote_abi" + }, + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [ + { + "name": "candidate", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "PrivateVoting::get_vote_parameters" + } + }, + { + "name": "return_type", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "PrivateVoting::get_vote_abi" + }, + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [ + { + "name": "message_ciphertext", + "type": { + "fields": [ + { + "name": "storage", + "type": { + "kind": "array", + "length": 17, + "type": { + "kind": "field" + } + } + }, + { + "name": "len", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ], + "kind": "struct", + "path": "std::collections::bounded_vec::BoundedVec" + } + }, + { + "name": "message_context", + "type": { + "fields": [ + { + "name": "tx_hash", + "type": { + "kind": "field" + } + }, + { + "name": "unique_note_hashes_in_tx", + "type": { + "fields": [ + { + "name": "storage", + "type": { + "kind": "array", + "length": 64, + "type": { + "kind": "field" + } + } + }, + { + "name": "len", + "type": { + "kind": "integer", + "sign": "unsigned", + "width": 32 + } + } + ], + "kind": "struct", + "path": "std::collections::bounded_vec::BoundedVec" + } + }, + { + "name": "first_nullifier_in_tx", + "type": { + "kind": "field" + } + }, + { + "name": "recipient", + "type": { + "fields": [ + { + "name": "inner", + "type": { + "kind": "field" + } + } + ], + "kind": "struct", + "path": "aztec::protocol_types::address::aztec_address::AztecAddress" + } + } + ], + "kind": "struct", + "path": "aztec::messages::processing::message_context::MessageContext" + } + } + ], + "kind": "struct", + "path": "PrivateVoting::process_message_parameters" + } + } + ], + "kind": "struct", + "path": "PrivateVoting::process_message_abi" + }, + { + "fields": [ + { + "name": "parameters", + "type": { + "fields": [], + "kind": "struct", + "path": "PrivateVoting::sync_private_state_parameters" + } + } + ], + "kind": "struct", + "path": "PrivateVoting::sync_private_state_abi" + } + ] + } + }, + "file_map": { + "102": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/macros/functions/initialization_utils.nr", + "source": "use dep::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::GENERATOR_INDEX__CONSTRUCTOR, hash::poseidon2_hash_with_separator, traits::ToField,\n};\n\nuse crate::{\n context::{PrivateContext, PublicContext},\n oracle::get_contract_instance::{\n get_contract_instance, get_contract_instance_deployer_avm,\n get_contract_instance_initialization_hash_avm,\n },\n};\n\npub fn mark_as_initialized_public(context: &mut PublicContext) {\n let init_nullifier =\n compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_nullifier(init_nullifier);\n}\n\npub fn mark_as_initialized_private(context: &mut PrivateContext) {\n let init_nullifier =\n compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_nullifier(init_nullifier);\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_unsiloed_contract_initialization_nullifier(context.this_address());\n context.push_nullifier_read_request(init_nullifier);\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 deployer = get_contract_instance_deployer_avm(address).unwrap();\n let initialization_hash = get_contract_instance_initialization_hash_avm(address).unwrap();\n let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash());\n assert(initialization_hash == expected_init, \"Initialization hash does not match\");\n assert(\n (deployer.is_zero()) | (deployer == context.msg_sender()),\n \"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()),\n \"Initializer address is not the contract deployer\",\n );\n}\n\n/// This function is not only used in macros but it's also used by external people to check that an instance has been\n/// initialized with the correct constructor arguments. Don't hide this unless you implement factory functionality.\npub fn compute_initialization_hash(\n init_selector: FunctionSelector,\n init_args_hash: Field,\n) -> Field {\n poseidon2_hash_with_separator(\n [init_selector.to_field(), init_args_hash],\n GENERATOR_INDEX__CONSTRUCTOR,\n )\n}\n" + }, + "105": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/macros/functions/utils.nr", + "source": "use crate::macros::{\n functions::{\n auth_registry::AUTHORIZE_ONCE_REGISTRY, call_interface_stubs::stub_fn, stub_registry,\n },\n notes::NOTES,\n utils::{\n add_to_hasher, fn_has_authorize_once, fn_has_noinitcheck, get_fn_visibility,\n is_fn_contract_library_method, is_fn_initializer, is_fn_internal, is_fn_private,\n is_fn_public, is_fn_test, is_fn_utility, is_fn_view, modify_fn_body, module_has_initializer,\n module_has_storage,\n },\n};\nuse std::meta::{ctstring::AsCtString, type_of};\n\npub(crate) comptime fn transform_private(f: FunctionDefinition) {\n let fn_stub = stub_fn(f);\n stub_registry::register(f.module(), fn_stub);\n\n let module_has_initializer = module_has_initializer(f.module());\n let module_has_storage = module_has_storage(f.module());\n\n // Private functions undergo a lot of transformations from their Aztec.nr form into a circuit that can be fed to the\n // Private Kernel Circuit.\n // First we change the function signature so that it also receives `PrivateContextInputs`, which contain information\n // about the execution context (e.g. the caller).\n let original_params = f.parameters();\n f.set_parameters(&[(\n quote { inputs },\n quote { crate::context::inputs::private_context_inputs::PrivateContextInputs }.as_type(),\n )]\n .append(original_params));\n\n let mut body = f.body().as_block().unwrap();\n\n // The original params are hashed and passed to the `context` object, so that the kernel can verify we've received\n // the correct values.\n // TODO: Optimize args_hasher for small number of arguments\n let args_hasher_name = quote { args_hasher };\n let args_hasher = original_params.fold(\n quote {\n let mut $args_hasher_name = dep::aztec::hash::ArgsHasher::new();\n },\n |args_hasher, param: (Quoted, Type)| {\n let (name, typ) = param;\n let appended_arg = add_to_hasher(args_hasher_name, name, typ);\n quote {\n $args_hasher\n $appended_arg\n }\n },\n );\n\n let context_creation = quote {\n let mut context = dep::aztec::context::private_context::PrivateContext::new(inputs, dep::aztec::protocol_types::traits::Hash::hash($args_hasher_name));\n };\n\n // Modifications introduced by the different marker attributes.\n let internal_check = if is_fn_internal(f) {\n create_internal_check(f)\n } else {\n quote {}\n };\n\n let view_check = if is_fn_view(f) {\n create_view_check(f)\n } else {\n quote {}\n };\n\n let (assert_initializer, mark_as_initialized) = if is_fn_initializer(f) {\n (create_assert_correct_initializer_args(f), create_mark_as_initialized(f))\n } else {\n (quote {}, quote {})\n };\n\n let storage_init = if module_has_storage {\n quote {\n // Some functions don't access storage, but it'd be quite difficult to only inject this variable if it is\n // referenced. We instead ignore 'unused variable' warnings for it.\n #[allow(unused_variables)]\n let storage = Storage::init(&mut context);\n }\n } else {\n quote {}\n };\n\n // Initialization checks are not included in contracts that don't have initializers.\n let init_check = if module_has_initializer & !is_fn_initializer(f) & !fn_has_noinitcheck(f) {\n create_init_check(f)\n } else {\n quote {}\n };\n\n // All private functions perform message discovery, since they may need to access notes. This is slightly\n // inefficient and could be improved by only doing it once we actually attempt to read any. Note that the message\n // discovery call syncs private events as well. We do not sync those here if there are no notes because we don't\n // have an API that would access events from private functions.\n let message_discovery_call = if NOTES.len() > 0 {\n create_message_discovery_call()\n } else {\n quote {}\n };\n\n // Inject the authwit check if the function is marked with #[authorize_once].\n let authorize_once_check = if fn_has_authorize_once(f) {\n create_authorize_once_check(f)\n } else {\n quote {}\n };\n\n // Finally, we need to change the return type to be `PrivateCircuitPublicInputs`, which is what the Private Kernel\n // circuit expects.\n let return_value_var_name = quote { macro__returned__values };\n\n let return_value_type = f.return_type();\n let return_value = if body.len() == 0 {\n quote {}\n } else if return_value_type != type_of(()) {\n // The original return value is passed to a second args hasher which the context receives.\n let (body_without_return, last_body_expr) = body.pop_back();\n let return_value = last_body_expr.quoted();\n let return_value_assignment =\n quote { let $return_value_var_name: $return_value_type = $return_value; };\n let return_hasher_name = quote { return_hasher };\n let return_value_into_hasher =\n add_to_hasher(return_hasher_name, return_value_var_name, return_value_type);\n\n body = body_without_return;\n\n quote {\n let mut $return_hasher_name = dep::aztec::hash::ArgsHasher::new();\n $return_value_assignment\n $return_value_into_hasher\n context.set_return_hash($return_hasher_name);\n }\n } else {\n let (body_without_return, last_body_expr) = body.pop_back();\n if !last_body_expr.has_semicolon()\n & last_body_expr.as_for().is_none()\n & last_body_expr.as_assert().is_none()\n & last_body_expr.as_for_range().is_none()\n & last_body_expr.as_assert_eq().is_none()\n & last_body_expr.as_let().is_none() {\n let unused_return_value_name = f\"_{return_value_var_name}\".quoted_contents();\n body = body_without_return.push_back(\n quote { let $unused_return_value_name = $last_body_expr; }.as_expr().unwrap(),\n );\n }\n quote {}\n };\n\n let context_finish = quote { context.finish() };\n\n // A quote to be injected at the beginning of the function body.\n let to_prepend = quote {\n dep::aztec::oracle::version::assert_compatible_oracle_version();\n $args_hasher\n $context_creation\n $assert_initializer\n $init_check\n $internal_check\n $view_check\n $storage_init\n $message_discovery_call\n $authorize_once_check\n };\n\n let to_append = quote {\n $return_value\n $mark_as_initialized\n $context_finish\n };\n let modified_body = modify_fn_body(body, to_prepend, to_append);\n f.set_body(modified_body);\n f.set_return_type(\n quote { dep::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs }\n .as_type(),\n );\n f.set_return_data();\n}\n\npub(crate) comptime fn transform_public(f: FunctionDefinition) {\n let fn_stub = stub_fn(f);\n stub_registry::register(f.module(), fn_stub);\n\n let module_has_initializer = module_has_initializer(f.module());\n let module_has_storage = module_has_storage(f.module());\n\n // Public functions undergo a lot of transformations from their Aztec.nr form.\n let original_params = f.parameters();\n\n let args_len_quote = if original_params.len() == 0 {\n // If the function has no parameters, we set the args_len to 0.\n quote { 0 }\n } else {\n // The following will give us ::N + ::N + ...\n original_params\n .map(|(_, param_type): (Quoted, Type)| {\n quote {\n <$param_type as $crate::protocol_types::traits::Serialize>::N\n }\n })\n .join(quote {+})\n };\n\n // Unlike in the private case, in public the `context` does not need to receive the hash of the original params.\n let context_creation = quote {\n let mut context = dep::aztec::context::public_context::PublicContext::new(|| {\n // We start from 1 because we skip the selector for the dispatch function.\n let serialized_args : [Field; $args_len_quote] = dep::aztec::context::public_context::calldata_copy(1, $args_len_quote);\n dep::aztec::hash::hash_args_array(serialized_args)\n });\n };\n\n // Modifications introduced by the different marker attributes.\n let internal_check = if is_fn_internal(f) {\n create_internal_check(f)\n } else {\n quote {}\n };\n\n let view_check = if is_fn_view(f) {\n create_view_check(f)\n } else {\n quote {}\n };\n\n let (assert_initializer, mark_as_initialized) = if is_fn_initializer(f) {\n (create_assert_correct_initializer_args(f), create_mark_as_initialized(f))\n } else {\n (quote {}, quote {})\n };\n\n let storage_init = if module_has_storage {\n // Some functions don't access storage, but it'd be quite difficult to only inject this variable if it is\n // referenced. We instead ignore 'unused variable' warnings for it.\n quote {\n #[allow(unused_variables)]\n let storage = Storage::init(&mut context);\n }\n } else {\n quote {}\n };\n\n // Initialization checks are not included in contracts that don't have initializers.\n let init_check = if module_has_initializer & !fn_has_noinitcheck(f) & !is_fn_initializer(f) {\n create_init_check(f)\n } else {\n quote {}\n };\n\n // Inject the authwit check if the function is marked with #[authorize_once].\n let authorize_once_check = if fn_has_authorize_once(f) {\n create_authorize_once_check(f)\n } else {\n quote {}\n };\n\n let to_prepend = quote {\n $context_creation\n $assert_initializer\n $init_check\n $internal_check\n $view_check\n $storage_init\n $authorize_once_check\n };\n\n let to_append = quote {\n $mark_as_initialized\n };\n\n let body = f.body().as_block().unwrap();\n let modified_body = modify_fn_body(body, to_prepend, to_append);\n f.set_body(modified_body);\n\n // All public functions are automatically made unconstrained, even if they were not marked as such. This is because\n // instead of compiling into a circuit, they will compile to bytecode that will be later transpiled into AVM\n // bytecode.\n f.set_unconstrained(true);\n f.set_return_public(true);\n}\n\npub(crate) comptime fn transform_utility(f: FunctionDefinition) {\n let fn_stub = stub_fn(f);\n stub_registry::register(f.module(), fn_stub);\n\n // Create utility context\n let context_creation =\n quote { let mut context = dep::aztec::context::utility_context::UtilityContext::new(); };\n let module_has_storage = module_has_storage(f.module());\n\n // Initialize Storage if module has storage\n let storage_init = if module_has_storage {\n quote {\n // Some functions don't access storage, but it'd be quite difficult to only inject this variable if it is\n // referenced. We instead ignore 'unused variable' warnings for it.\n #[allow(unused_variables)]\n let storage = Storage::init(context);\n }\n } else {\n quote {}\n };\n\n // All utility functions perform message discovery, since they may need to access private notes that would be\n // found during this process or they may be used to sync private events from TypeScript\n // (`sync_private_state` function gets invoked by PXE::getPrivateEvents function).\n let message_discovery_call = create_message_discovery_call();\n\n // A quote to be injected at the beginning of the function body.\n let to_prepend = quote {\n dep::aztec::oracle::version::assert_compatible_oracle_version();\n $context_creation\n $storage_init\n $message_discovery_call\n };\n let body = f.body().as_block().unwrap();\n let modified_body = modify_fn_body(body, to_prepend, quote {});\n f.set_body(modified_body);\n\n f.set_return_public(true);\n}\n\ncomptime fn create_internal_check(f: FunctionDefinition) -> Quoted {\n let name = f.name();\n let assertion_message = f\"Function {name} can only be called internally\";\n quote { assert(context.msg_sender() == context.this_address(), $assertion_message); }\n}\n\ncomptime fn create_view_check(f: FunctionDefinition) -> Quoted {\n let name = f.name();\n let assertion_message = f\"Function {name} can only be called statically\";\n if is_fn_private(f) {\n // Here `context` is of type context::PrivateContext\n quote { assert(context.inputs.call_context.is_static_call, $assertion_message); }\n } else {\n // Here `context` is of type context::PublicContext\n quote { assert(context.is_static_call(), $assertion_message); }\n }\n}\n\ncomptime fn create_assert_correct_initializer_args(f: FunctionDefinition) -> Quoted {\n let fn_visibility = get_fn_visibility(f);\n f\"dep::aztec::macros::functions::initialization_utils::assert_initialization_matches_address_preimage_{fn_visibility}(context);\"\n .quoted_contents()\n}\n\ncomptime fn create_mark_as_initialized(f: FunctionDefinition) -> Quoted {\n let fn_visibility = get_fn_visibility(f);\n f\"dep::aztec::macros::functions::initialization_utils::mark_as_initialized_{fn_visibility}(&mut context);\"\n .quoted_contents()\n}\n\ncomptime fn create_init_check(f: FunctionDefinition) -> Quoted {\n let fn_visibility = get_fn_visibility(f);\n f\"dep::aztec::macros::functions::initialization_utils::assert_is_initialized_{fn_visibility}(&mut context);\"\n .quoted_contents()\n}\n\n/// Injects a call to `aztec::messages::discovery::discover_new_messages`, causing for new notes to be added to PXE and made\n/// available for the current execution.\npub(crate) comptime fn create_message_discovery_call() -> Quoted {\n quote {\n /// Safety: message discovery returns nothing and is performed solely for its side-effects. It is therefore\n /// always safe to call.\n unsafe {\n dep::aztec::messages::discovery::discover_new_messages(\n context.this_address(),\n _compute_note_hash_and_nullifier,\n );\n };\n }\n}\n\n/// Injects an authwit verification check of the form:\n/// ```\n/// if (!from.eq(context.msg_sender())) {\n/// assert_current_call_valid_authwit::(&mut context, from);\n/// } else {\n/// assert(authwit_nonce, \"Invalid authwit nonce. When 'from' and 'msg_sender' are the same, authwit_nonce must be zero\");\n/// }\n/// ```\n/// where `from` and `authwit_nonce` are the names of the parameters that are expected to be present in the function definition.\n/// This check is injected by the `#[authorize_once(\"from_arg_name\", \"nonce_arg_name\")]`, which allows the user to define\n/// which parameters to use.\npub(crate) comptime fn create_authorize_once_check(f: FunctionDefinition) -> Quoted {\n let maybe_authorize_once_args = AUTHORIZE_ONCE_REGISTRY.get(f);\n let authorize_once_args = if maybe_authorize_once_args.is_some() {\n maybe_authorize_once_args.unwrap()\n } else {\n // We need to for authorize_once to have already executed so that we can retrieve its params - this depends on\n // the order in which the attributes are applied.\n panic(\n f\"Functions marked with #[authorize_once] must have the #[private] or #[public] attribute placed last\",\n )\n };\n\n let (from_arg_name, nonce_arg_name) = authorize_once_args;\n let name: Quoted = f.name();\n\n let from_arg_candidates =\n f.parameters().filter(|(name, _)| name == f\"{from_arg_name}\".quoted_contents());\n let (from_arg_name_quoted, from_arg_type) = if from_arg_candidates.len() == 1 {\n from_arg_candidates[0]\n } else {\n panic(\n f\"Function {name} does not have a {from_arg_name} parameter. Please specify which one to use in #[authorize_once(\\\"...\\\", \\\"authwit_nonce\\\")]\",\n )\n };\n if from_arg_type\n != quote { dep::protocol_types::address::aztec_address::AztecAddress }.as_type() {\n panic(\n f\"Argument {from_arg_name_quoted} in function {name} must be of type AztecAddress, but is of type {from_arg_type}\",\n )\n }\n\n let nonce_arg_candidates =\n f.parameters().filter(|(name, _)| name == f\"{nonce_arg_name}\".quoted_contents());\n let (nonce_arg_name_quoted, nonce_arg_type) = if nonce_arg_candidates.len() == 1 {\n nonce_arg_candidates[0]\n } else {\n panic(\n f\"Function {name} does not have a {nonce_arg_name}. Please specify which one to use in #[authorize_once(\\\"from\\\", \\\"...\\\")]\",\n )\n };\n if nonce_arg_type != quote { Field }.as_type() {\n panic(\n f\"Argument {nonce_arg_name_quoted} in function {name} must be of type Field, but is of type {nonce_arg_type}\",\n );\n }\n\n let nonce_check_quote = f\"{nonce_arg_name_quoted} == 0\".quoted_contents();\n\n let fn_call = if is_fn_private(f) {\n // At this point, the original args of the fn have already been altered by the macro\n // to include PrivateContextInputs, so we need to adjust the args_len accordingly.\n let args_len = f.parameters().len() - 1;\n quote { dep::aztec::authwit::auth::assert_current_call_valid_authwit::<$args_len> }\n } else {\n quote { dep::aztec::authwit::auth::assert_current_call_valid_authwit_public }\n };\n let invalid_nonce_message = f\"Invalid authwit nonce. When '{from_arg_name}' and 'msg_sender' are the same, '{nonce_arg_name}' must be zero\"\n .as_ctstring()\n .as_quoted_str();\n quote { \n if (!$from_arg_name_quoted.eq(context.msg_sender())) {\n $fn_call(&mut context, $from_arg_name_quoted);\n } else {\n assert($nonce_check_quote, $invalid_nonce_message);\n }\n }\n}\n\n/// Checks if each function in the module is marked with either #[private], #[public], #[utility],\n/// #[contract_library_method], or #[test]. Non-macroified functions are not allowed in contracts.\npub(crate) comptime fn check_each_fn_macroified(m: Module) {\n for f in m.functions() {\n let name = f.name();\n if !is_fn_private(f)\n & !is_fn_public(f)\n & !is_fn_utility(f)\n & !is_fn_contract_library_method(f)\n & !is_fn_test(f) {\n panic(\n f\"Function {name} must be marked as either #[private], #[public], #[utility], #[contract_library_method], or #[test]\",\n );\n }\n }\n}\n" + }, + "107": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/macros/notes.nr", + "source": "use crate::note::note_getter_options::PropertySelector;\nuse std::{collections::bounded_vec::BoundedVec, meta::{ctstring::AsCtString, type_of}};\n\n/// Maximum number of note types within 1 contract.\ncomptime global MAX_NOTE_TYPES: u32 = 128;\n\n/// A BoundedVec containing all the note types within this contract.\npub comptime mut global NOTES: BoundedVec = BoundedVec::new();\n\ncomptime mut global NOTE_TYPE_ID_COUNTER: u32 = 0;\n\n/// The note type id is set by enumerating the note types.\ncomptime fn get_next_note_type_id() -> Field {\n // We assert that the note type id fits within 7 bits\n assert(\n NOTE_TYPE_ID_COUNTER < MAX_NOTE_TYPES,\n f\"A contract can contain at most {MAX_NOTE_TYPES} different note types\",\n );\n\n let note_type_id = NOTE_TYPE_ID_COUNTER as Field;\n NOTE_TYPE_ID_COUNTER += 1;\n note_type_id\n}\n\n/// Generates default `NoteType` implementation for a given note struct `s` and returns it as a quote.\n///\n/// impl NoteType for NoteStruct {\n/// fn get_id() -> Field {\n/// ...\n/// }\n/// }\ncomptime fn generate_note_type_impl(s: TypeDefinition, note_type_id: Field) -> Quoted {\n let name = s.name();\n let typ = s.as_type();\n let note_type_name: str<_> = f\"{name}\".as_ctstring().as_quoted_str!();\n let max_note_packed_len = crate::messages::discovery::private_notes::MAX_NOTE_PACKED_LEN;\n\n quote {\n impl aztec::note::note_interface::NoteType for $name {\n fn get_id() -> Field {\n // This static assertion ensures the note's packed length doesn't exceed the maximum allowed size.\n // While this check would ideally live in the Packable trait implementation, we place it here since\n // this function is always generated by our macros and the Packable trait implementation is not.\n // Note: We set the note type name and max packed length as local variables because injecting them\n // directly into the error message doesn't work.\n let note_type_name = $note_type_name;\n let max_note_packed_len: u32 = $max_note_packed_len; // Casting to u32 to avoid the value to be printed in hex.\n let note_packed_len = <$typ as Packable>::N;\n std::static_assert(note_packed_len <= $max_note_packed_len, f\"{note_type_name} has a packed length of {note_packed_len} fields, which exceeds the maximum allowed length of {max_note_packed_len} fields\");\n\n $note_type_id\n }\n }\n }\n}\n\n/// Generates default `NoteHash` trait implementation for a given note struct `s` and returns it as a quote.\n///\n/// # Generated Implementation\n/// ```\n/// impl NoteHash for NoteStruct {\n/// fn compute_note_hash(self, storage_slot: Field) -> Field { ... }\n///\n/// fn compute_nullifier(self, context: &mut PrivateContext, note_hash_for_nullify: Field) -> Field { ... }\n///\n/// unconstrained fn compute_nullifier_unconstrained(note_hash_for_nullify: Field) -> Field { ... }\n/// }\n/// ```\ncomptime fn generate_note_hash_trait_impl(s: TypeDefinition) -> Quoted {\n let name = s.name();\n\n quote {\n impl aztec::note::note_interface::NoteHash for $name {\n fn compute_note_hash(self, storage_slot: Field) -> Field {\n let inputs = aztec::protocol_types::traits::Packable::pack(self).concat( [storage_slot]);\n aztec::protocol_types::hash::poseidon2_hash_with_separator(inputs, aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_HASH)\n }\n\n fn compute_nullifier(\n self,\n context: &mut aztec::context::PrivateContext,\n note_hash_for_nullify: Field,\n ) -> Field {\n let owner_npk_m = aztec::keys::getters::get_public_keys(self.owner).npk_m;\n // We invoke hash as a static trait function rather than calling owner_npk_m.hash() directly\n // in the quote to avoid \"trait not in scope\" compiler warnings.\n let owner_npk_m_hash = aztec::protocol_types::traits::Hash::hash(owner_npk_m);\n let secret = context.request_nsk_app(owner_npk_m_hash);\n aztec::protocol_types::hash::poseidon2_hash_with_separator(\n [note_hash_for_nullify, secret],\n aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n )\n }\n\n unconstrained fn compute_nullifier_unconstrained(\n self,\n note_hash_for_nullify: Field,\n ) -> Field {\n let owner_npk_m = aztec::keys::getters::get_public_keys(self.owner).npk_m;\n // We invoke hash as a static trait function rather than calling owner_npk_m.hash() directly\n // in the quote to avoid \"trait not in scope\" compiler warnings.\n let owner_npk_m_hash = aztec::protocol_types::traits::Hash::hash(owner_npk_m);\n let secret = aztec::keys::getters::get_nsk_app(owner_npk_m_hash);\n aztec::protocol_types::hash::poseidon2_hash_with_separator(\n [note_hash_for_nullify, secret],\n aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n )\n }\n }\n }\n}\n\n/// Generates note properties struct for a given note struct `s`.\n///\n/// Example:\n/// ```\n/// struct TokenNoteProperties {\n/// amount: aztec::note::note_getter_options::PropertySelector,\n/// npk_m_hash: aztec::note::note_getter_options::PropertySelector\n/// randomness: aztec::note::note_getter_options::PropertySelector\n/// }\n///\n/// impl aztec::note::note_interface::NoteProperties for TokenNote {\n/// fn properties() -> TokenNoteProperties {\n/// Self {\n/// amount: aztec::note::note_getter_options::PropertySelector { index: 0, offset: 0, length: 32 },\n/// npk_m_hash: aztec::note::note_getter_options::PropertySelector { index: 1, offset: 0, length: 32 },\n/// randomness: aztec::note::note_getter_options::PropertySelector { index: 2, offset: 0, length: 32 }\n/// }\n/// }\n/// }\n/// ```\ncomptime fn generate_note_properties(s: TypeDefinition) -> Quoted {\n let name = s.name();\n\n let struct_name = f\"{name}Properties\".quoted_contents();\n\n let property_selector_type = type_of(PropertySelector { index: 0, offset: 0, length: 0 });\n\n let note_fields = s.fields_as_written();\n\n let properties_types = note_fields\n .map(|(name, _, _)| quote { pub $name: $property_selector_type })\n .join(quote {,});\n\n // TODO #8694: Properly handle non-field types https://github.com/AztecProtocol/aztec-packages/issues/8694\n let mut properties_list = &[];\n for i in 0..note_fields.len() {\n let (name, _, _) = note_fields[i];\n properties_list = properties_list.push_back(\n quote { $name: aztec::note::note_getter_options::PropertySelector { index: $i, offset: 0, length: 32 } },\n );\n }\n\n let properties = properties_list.join(quote {,});\n\n quote {\n pub struct $struct_name {\n $properties_types\n }\n\n impl aztec::note::note_interface::NoteProperties<$struct_name> for $name {\n fn properties() -> $struct_name {\n $struct_name {\n $properties\n }\n }\n }\n }\n}\n\n/// Generates the core note functionality for a struct:\n///\n/// - NoteTypeProperties: Defines the structure and properties of note fields\n/// - NoteType trait implementation: Provides the note type ID\n/// - NoteHash trait implementation: Handles note hash and nullifier computation\n///\n/// # Requirements\n///\n/// The note struct must:\n/// - Have an `owner` field\n/// - Implement the `Packable` trait\n/// - Not exceed `MAX_NOTE_PACKED_LEN` when packed\n///\n/// # Registration\n///\n/// Registers the note in the global `NOTES` BoundedVec to enable note processing functionality.\n///\n/// # Generated Code\n///\n/// For detailed documentation on the generated implementations, see:\n/// - `generate_note_properties()`\n/// - `generate_note_type_impl()`\n/// - `generate_note_hash_trait_impl()`\npub comptime fn note(s: TypeDefinition) -> Quoted {\n assert_has_owner(s);\n assert_has_packable(s);\n\n // We register the note in the global `NOTES` BoundedVec because we need that information inside the #[aztec] macro\n // to generate note processing functionality.\n NOTES.push(s.as_type());\n\n let note_properties = generate_note_properties(s);\n let note_type_id = get_next_note_type_id();\n let note_type_impl = generate_note_type_impl(s, note_type_id);\n let note_hash_impl = generate_note_hash_trait_impl(s);\n\n quote {\n $note_properties\n $note_type_impl\n $note_hash_impl\n }\n}\n\n/// Generates code for a custom note implementation that requires specialized note hash or nullifier computation.\n///\n/// # Generated Code\n/// - NoteTypeProperties: Defines the structure and properties of note fields\n/// - NoteType trait implementation: Provides the note type ID\n///\n/// # Requirements\n///\n/// The note struct must:\n/// - Implement the `Packable` trait\n/// - Not exceed `MAX_NOTE_PACKED_LEN` when packed\n///\n/// Unlike the `#[note]` macro, there is no requirement for an `owner` field.\n///\n/// # Registration\n///\n/// Registers the note in the global `NOTES` BoundedVec to enable note processing functionality.\n///\n/// # Use Cases\n/// Use this macro when implementing a note that needs custom:\n/// - Note hash computation logic\n/// - Nullifier computation logic\n///\n/// The macro omits generating default NoteHash trait implementation, allowing you to provide your own.\n///\n/// # Example\n/// ```\n/// #[custom_note]\n/// struct CustomNote {\n/// value: Field,\n/// metadata: Field\n/// }\n///\n/// impl NoteHash for CustomNote {\n/// // Custom note hash computation...\n/// fn compute_note_hash(...) -> Field { ... }\n///\n/// // Custom nullifier computation...\n/// fn compute_nullifier(...) -> Field { ... }\n/// fn compute_nullifier_unconstrained(...) -> Field { ... }\n/// }\n/// ```\npub comptime fn custom_note(s: TypeDefinition) -> Quoted {\n assert_has_packable(s);\n\n // We register the note in the global `NOTES` BoundedVec because we need that information inside the #[aztec] macro\n // to generate note processing functionality.\n NOTES.push(s.as_type());\n\n let note_type_id = get_next_note_type_id();\n let note_properties = generate_note_properties(s);\n let note_type_impl = generate_note_type_impl(s, note_type_id);\n\n quote {\n $note_properties\n $note_type_impl\n }\n}\n\n/// Asserts that the given note implements the `Packable` trait.\n///\n/// We require that notes have the `Packable` trait implemented because it is used when emitting a note in a log or as\n/// an offchain message.\ncomptime fn assert_has_packable(note: TypeDefinition) {\n let packable_constraint =\n quote { crate::protocol_types::traits::Packable }.as_trait_constraint();\n let note_name = note.name();\n\n assert(\n note.as_type().implements(packable_constraint),\n f\"{note_name} does not implement Packable trait. Either implement it manually or place #[derive(Packable)] on the note struct before #[note] macro invocation.\",\n );\n}\n\n/// Asserts that the note has an 'owner' field.\n///\n/// We require notes implemented with #[note] macro macro to have an 'owner' field because our\n/// auto-generated nullifier functions expect it. This requirement is most likely only temporary.\ncomptime fn assert_has_owner(note: TypeDefinition) {\n let fields = note.fields_as_written();\n let mut has_owner = false;\n for i in 0..fields.len() {\n let (field_name, _, _) = fields[i];\n if field_name == quote { owner } {\n has_owner = true;\n break;\n }\n }\n let note_name = note.name();\n\n assert(\n has_owner,\n f\"{note_name} does not have an 'owner' field. If your notes have no owner, use #[custom_note] insteadof #[note] and implement the NoteHashing trait manually.\",\n );\n}\n" + }, + "108": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/macros/storage.nr", + "source": "use poseidon::poseidon2::Poseidon2Hasher;\nuse std::{collections::umap::UHashMap, hash::BuildHasherDefault};\n\nuse super::utils::AsStrQuote;\nuse super::utils::get_storage_size;\n\n/// Stores a map from a module to the name of the struct that describes its storage layout.\n/// This is then used when generating a `storage_layout()` getter on the contract struct.\npub comptime mut global STORAGE_LAYOUT_NAME: UHashMap> =\n UHashMap::default();\n\n/// Marks a struct as the one describing the storage layout of a contract.\n///\n/// The contract's storage is accessed via the `storage` variable, which will will automatically be made available in\n/// all functions as an instance of the struct this macro was applied to.\n///\n/// Only a single struct in the entire contract should have this macro (or `storage_no_init`) applied to it, and the\n/// struct has to be called 'Storage'.\npub comptime fn storage(s: TypeDefinition) -> Quoted {\n let struct_name = s.name();\n if struct_name != quote { Storage } {\n panic(\n f\"The #[storage] macro can only be applied to a struct with name 'Storage', got '{struct_name}' instead.\",\n )\n }\n\n assert(\n !s.has_named_attribute(\"storage_no_init\"),\n f\"Only one of #[storage] and #[storage_no_init] can be applied to the Storage struct.\",\n );\n\n // This macro performs three things:\n // - it marks the contract as having storage, so that `macros::utils::module_has_storage` will return true and\n // functions will have the storage variable injected and initialized via the `init` function.\n // - it implements said `init` function by allocating appropriate storage slots to each state variable.\n // - it exposes the storage layout by creating a `StorageLayout` struct that is exposed via the `abi(storage)`\n // macro.\n let mut slot: u32 = 1;\n let mut storage_vars_constructors = &[];\n let mut storage_layout_fields = &[];\n let mut storage_layout_constructors = &[];\n\n // TODO(#8658): uncomment the code below to inject the Context type parameter.\n //let mut new_storage_fields = &[];\n //let context_generic = s.add_generic(\"Context\");\n for field in s.fields_as_written() {\n // FIXME: This doesn't handle field types with generics\n let (name, typ, _) = field;\n let (storage_field_constructor, storage_size) =\n generate_storage_field_constructor(typ, quote { $slot });\n storage_vars_constructors =\n storage_vars_constructors.push_back(quote { $name: $storage_field_constructor });\n // We have `Storable` in a separate `.nr` file instead of defining it in the last quote of this function\n // because that way a dev gets a more reasonable error if he defines a struct with the same name in\n // a contract.\n storage_layout_fields = storage_layout_fields.push_back(\n quote { pub $name: dep::aztec::state_vars::storage::Storable },\n );\n storage_layout_constructors = storage_layout_constructors.push_back(\n quote { $name: dep::aztec::state_vars::storage::Storable { slot: $slot } },\n );\n //let with_context_generic = add_context_generic(typ, context_generic);\n //println(with_context_generic);\n //new_storage_fields = new_storage_fields.push_back((name, with_context_generic ));\n slot += storage_size;\n }\n\n //s.set_fields(new_storage_fields);\n let storage_vars_constructors = storage_vars_constructors.join(quote {,});\n let storage_impl = quote {\n impl Storage {\n fn init(context: Context) -> Self {\n Self {\n $storage_vars_constructors\n }\n }\n }\n };\n\n let storage_layout_fields = storage_layout_fields.join(quote {,});\n let storage_layout_constructors = storage_layout_constructors.join(quote {,});\n\n let module = s.module();\n let module_name = module.name();\n let storage_layout_name = f\"STORAGE_LAYOUT_{module_name}\".quoted_contents();\n let (module_name_str, module_name_len) = module_name.as_str_quote();\n STORAGE_LAYOUT_NAME.insert(module, storage_layout_name);\n\n quote {\n $storage_impl\n\n pub struct StorageLayoutFields {\n $storage_layout_fields\n }\n\n pub struct StorageLayout {\n pub contract_name: str,\n pub fields: StorageLayoutFields\n }\n\n #[abi(storage)]\n pub global $storage_layout_name: StorageLayout<$module_name_len> = StorageLayout {\n contract_name: $module_name_str,\n fields: StorageLayoutFields { $storage_layout_constructors }\n };\n }\n}\n\n/// Same as `storage`, except the user is in charge of providing an implementation of the `init` constructor function\n/// with signature `fn init(context: Context) -> Self`, which allows for manual control of storage slot\n/// allocation. Similarly, no `StorageLayout` struct will be created.\n///\n/// The contract's storage is accessed via the `storage` variable, which will will automatically be made available in\n/// all functions as an instance of the struct this macro was applied to.\n///\n/// Only a single struct in the entire contract can have this macro (or storage_no_init) applied to it, and the struct\n/// has to be called 'Storage'.\npub comptime fn storage_no_init(s: TypeDefinition) {\n // All `storage` does is provide the `init` implementation, so we don't need to do anything here. Applying this\n // macro however will cause for `macros::utils::module_has_storage` to return true, resulting in the injection of\n // the `storage` variable.\n\n // We do need to make sure that the type is called Storage, since we'll do `Storage::init` later on.\n\n if s.name() != quote { Storage } {\n let name = s.name();\n panic(\n f\"The #[storage_no_init] macro can only be applied to a struct with name 'Storage', got '{name}' instead.\",\n )\n }\n\n assert(\n !s.has_named_attribute(\"storage\"),\n f\"Only one of #[storage] and #[storage_no_init] can be applied to the Storage struct.\",\n );\n}\n\n/// Returns the expression required to initialize a state variable with a given slot, along with its serialization size,\n/// i.e. how many contiguous storage slots the variable requires.\ncomptime fn generate_storage_field_constructor(typ: Type, slot: Quoted) -> (Quoted, u32) {\n assert(\n typ.as_data_type().is_some(),\n \"Storage containers must be generic structs of the form `Container<_, Context>`, or Map\",\n );\n let (container_struct, generics) = typ.as_data_type().unwrap();\n let struct_name = container_struct.name();\n\n let constructor = if is_storage_map(typ) {\n // Map state variables recursively initialize their contents - this includes nested maps.\n let (value_constructor, _) =\n generate_storage_field_constructor(generics[1], quote { slot });\n\n quote { $struct_name::new(context, $slot, | context, slot | { $value_constructor }) }\n } else {\n // We assume below that all state variables implement `fn new(context: Context, slot: Field) -> Self`.\n quote { $struct_name::new(context, $slot)}\n };\n\n (constructor, get_storage_size(typ))\n}\n\n/// Returns true if `typ` is `state_vars::map::Map`.\ncomptime fn is_storage_map(typ: Type) -> bool {\n if typ.as_data_type().is_some() {\n let (def, generics) = typ.as_data_type().unwrap();\n let maybe_map = if (def.name() == quote { Map }) & (generics.len() == 3) {\n let maybe_key = generics[0];\n let maybe_value = generics[1];\n let maybe_context = generics[2];\n quote { crate::state_vars::map::Map<$maybe_key, $maybe_value, $maybe_context> }.as_type()\n } else {\n quote {()}.as_type()\n };\n typ == maybe_map\n } else {\n false\n }\n}\n\ncomptime fn add_context_generic(typ: Type, context_generic: Type) -> Type {\n let (def, mut generics) = typ.as_data_type().expect(\n f\"Storage containers must be generic structs of the form `Container<..., Context>`\",\n );\n let name = def.name();\n\n if is_storage_map(typ) {\n generics[generics.len() - 2] = add_context_generic(generics[1], context_generic);\n generics[generics.len() - 1] = context_generic;\n } else {\n generics[generics.len() - 1] = context_generic;\n }\n\n let generics = generics.map(|typ: Type| quote {$typ}).join(quote {,});\n quote { $name<$generics> }.as_type()\n}\n" + }, + "110": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/discovery/mod.nr", + "source": "use protocol_types::{address::AztecAddress, debug_log::{debug_log, debug_log_format}};\n\npub mod nonce_discovery;\npub mod partial_notes;\npub mod private_events;\npub mod private_notes;\npub mod process_message;\n\nuse crate::{\n messages::{\n discovery::{private_notes::MAX_NOTE_PACKED_LEN, process_message::do_process_message},\n processing::{\n get_private_logs, pending_tagged_log::PendingTaggedLog,\n validate_enqueued_notes_and_events,\n },\n },\n utils::array,\n};\n\npub struct NoteHashAndNullifier {\n /// The result of NoteHash::compute_note_hash\n pub note_hash: Field,\n /// The result of NoteHash::compute_nullifier_unconstrained (since all of message discovery is unconstrained)\n pub inner_nullifier: Field,\n}\n\n/// A function which takes a note's packed content, address of the emitting contract, note nonce, storage slot and note\n/// type ID and attempts to compute its note hash (not hashed by note nonce nor siloed by address) and inner nullifier\n/// (not siloed by address).\n///\n/// This function must be user-provided as its implementation requires knowledge of how note type IDs are allocated in a\n/// contract. The `#[aztec]` macro automatically creates such a contract library method called\n/// `_compute_note_hash_and_nullifier`, which looks something like this:\n///\n/// ```\n/// |packed_note, contract_address, note_nonce, storage_slot, note_type_id| {\n/// if note_type_id == MyNoteType::get_id() {\n/// assert(packed_note.len() == MY_NOTE_TYPE_SERIALIZATION_LENGTH);\n///\n/// let note = MyNoteType::unpack(aztec::utils::array::subarray(packed_note.storage(), 0));\n///\n/// let note_hash = note.compute_note_hash(storage_slot);\n/// let note_hash_for_nullify = aztec::note::utils::compute_note_hash_for_nullify(\n/// RetrievedNote{ note, contract_address, metadata: SettledNoteMetadata::new(note_nonce).into() },\n/// storage_slot\n/// );\n///\n/// let inner_nullifier = note.compute_nullifier_unconstrained(note_hash_for_nullify);\n///\n/// Option::some(\n/// aztec::messages::discovery::NoteHashAndNullifier {\n/// note_hash, inner_nullifier\n/// }\n/// )\n/// } else if note_type_id == MyOtherNoteType::get_id() {\n/// ... // Similar to above but calling MyOtherNoteType::unpack_content\n/// } else {\n/// Option::none() // Unknown note type ID\n/// };\n/// }\n/// ```\ntype ComputeNoteHashAndNullifier = unconstrained fn[Env](/* packed_note */BoundedVec, /* storage_slot */ Field, /* note_type_id */ Field, /* contract_address */ AztecAddress, /* note nonce */ Field) -> Option;\n\n/// Performs the message discovery process, in which private are downloaded and inspected to find new private notes,\n/// partial notes and events, etc., and pending partial notes are processed to search for their completion logs.\n/// This is the mechanism via which a contract updates its knowledge of its private state.\n///\n/// Receives the address of the contract on which discovery is performed along with its\n/// `compute_note_hash_and_nullifier` function.\npub unconstrained fn discover_new_messages(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n) {\n debug_log(\"Performing message discovery\");\n\n // First we process all private logs, which can contain different kinds of messages e.g. private notes, partial\n // notes, private events, etc.\n let mut logs = get_private_logs(contract_address);\n logs.for_each(|i, pending_tagged_log: PendingTaggedLog| {\n debug_log_format(\n \"Processing log with tag {0}\",\n [pending_tagged_log.log.get(0)],\n );\n\n // We remove the tag from the pending tagged log and process the message ciphertext contained in it.\n let message_ciphertext = array::subbvec(pending_tagged_log.log, 1);\n\n do_process_message(\n contract_address,\n compute_note_hash_and_nullifier,\n message_ciphertext,\n pending_tagged_log.context,\n );\n logs.remove(i);\n });\n\n // Then we process all pending partial notes, regardless of whether they were found in the current or previous\n // executions.\n partial_notes::fetch_and_process_partial_note_completion_logs(\n contract_address,\n compute_note_hash_and_nullifier,\n );\n\n // Finally we validate all notes and events that were found as part of the previous processes, resulting in them\n // being added to PXE's database and retrievable via oracles (get_notes) and our TS API (PXE::getPrivateEvents).\n validate_enqueued_notes_and_events(contract_address);\n}\n" + }, + "111": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/discovery/nonce_discovery.nr", + "source": "use crate::messages::discovery::{ComputeNoteHashAndNullifier, private_notes::MAX_NOTE_PACKED_LEN};\n\nuse dep::protocol_types::{\n address::AztecAddress,\n constants::MAX_NOTE_HASHES_PER_TX,\n debug_log::debug_log_format,\n hash::{compute_note_hash_nonce, compute_siloed_note_hash, compute_unique_note_hash},\n traits::ToField,\n};\n\n/// A struct with the discovered information of a complete note, required for delivery to PXE. Note that this is *not*\n/// the complete note information, since it does not include content, storage slot, etc.\npub struct DiscoveredNoteInfo {\n pub note_nonce: Field,\n pub note_hash: Field,\n pub inner_nullifier: Field,\n}\n\n/// Searches for note nonces that will result in a note that was emitted in a transaction. While rare, it is possible\n/// for multiple notes to have the exact same packed content and storage slot but different nonces, resulting in\n/// different unique note hashes. Because of this this function returns a *vector* of discovered notes, though in most\n/// cases it will contain a single element.\n///\n/// Due to how nonces are computed, this function requires knowledge of the transaction in which the note was created,\n/// more specifically the list of all unique note hashes in it plus the value of its first nullifier.\npub unconstrained fn attempt_note_nonce_discovery(\n unique_note_hashes_in_tx: BoundedVec,\n first_nullifier_in_tx: Field,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n packed_note: BoundedVec,\n) -> BoundedVec {\n let discovered_notes = &mut BoundedVec::new();\n\n debug_log_format(\n \"Attempting nonce discovery on {0} potential notes on contract {1} for storage slot {2}\",\n [unique_note_hashes_in_tx.len() as Field, contract_address.to_field(), storage_slot],\n );\n\n // We need to find nonces (typically just one) that result in a note hash that, once siloed into a unique note hash,\n // is one of the note hashes created by the transaction.\n unique_note_hashes_in_tx.for_eachi(|i, expected_unique_note_hash| {\n // Nonces are computed by hashing the first nullifier in the transaction with the index of the note in the\n // new note hashes array. We therefore know for each note in every transaction what its nonce is.\n let candidate_nonce = compute_note_hash_nonce(first_nullifier_in_tx, i);\n\n // Given note nonce, note content and metadata, we can compute the note hash and silo it to check if it matches\n // the note hash at the array index we're currently processing.\n // TODO(#11157): handle failed note_hash_and_nullifier computation\n let hashes = compute_note_hash_and_nullifier(\n packed_note,\n storage_slot,\n note_type_id,\n contract_address,\n candidate_nonce,\n )\n .expect(f\"Failed to compute a note hash for note type {note_type_id}\");\n\n let siloed_note_hash = compute_siloed_note_hash(contract_address, hashes.note_hash);\n let unique_note_hash = compute_unique_note_hash(candidate_nonce, siloed_note_hash);\n\n if unique_note_hash == expected_unique_note_hash {\n // Note that while we did check that the note hash is the preimage of the expected unique note hash, we\n // perform no validations on the nullifier - we fundamentally cannot, since only the application knows\n // how to compute nullifiers. We simply trust it to have provided the correct one: if it hasn't, then\n // PXE may fail to realize that a given note has been nullified already, and calls to the application\n // could result in invalid transactions (with duplicate nullifiers). This is not a concern because an\n // application already has more direct means of making a call to it fail the transaction.\n discovered_notes.push(\n DiscoveredNoteInfo {\n note_nonce: candidate_nonce,\n note_hash: hashes.note_hash,\n inner_nullifier: hashes.inner_nullifier,\n },\n );\n\n // We don't exit the loop - it is possible (though rare) for the exact same note content to be present\n // multiple times in the same transaction with different nonces. This typically doesn't happen due to\n // notes containing random values in order to hide their contents.\n }\n });\n\n debug_log_format(\n \"Found valid nonces for a total of {0} notes\",\n [discovered_notes.len() as Field],\n );\n\n *discovered_notes\n}\n\nmod test {\n use crate::{\n messages::discovery::{NoteHashAndNullifier, private_notes::MAX_NOTE_PACKED_LEN},\n note::{\n note_interface::{NoteHash, NoteType},\n note_metadata::SettledNoteMetadata,\n retrieved_note::RetrievedNote,\n utils::compute_note_hash_for_nullify,\n },\n oracle::random::random,\n test::mocks::mock_note::MockNote,\n utils::array,\n };\n\n use dep::protocol_types::{\n address::AztecAddress,\n hash::{compute_note_hash_nonce, compute_siloed_note_hash, compute_unique_note_hash},\n traits::{FromField, Packable},\n };\n\n use super::attempt_note_nonce_discovery;\n\n // This implementation could be simpler, but this serves as a nice example of the expected flow in a real\n // implementation, and as a sanity check that the interface is sufficient.\n unconstrained fn compute_note_hash_and_nullifier(\n packed_note: BoundedVec,\n storage_slot: Field,\n note_type_id: Field,\n contract_address: AztecAddress,\n note_nonce: Field,\n ) -> Option {\n if note_type_id == MockNote::get_id() {\n let note = MockNote::unpack(array::subarray(packed_note.storage(), 0));\n let note_hash = note.compute_note_hash(storage_slot);\n\n let note_hash_for_nullify = compute_note_hash_for_nullify(\n RetrievedNote {\n note,\n contract_address,\n metadata: SettledNoteMetadata::new(note_nonce).into(),\n },\n storage_slot,\n );\n\n let inner_nullifier = note.compute_nullifier_unconstrained(note_hash_for_nullify);\n\n Option::some(NoteHashAndNullifier { note_hash, inner_nullifier })\n } else {\n Option::none()\n }\n }\n\n global VALUE: Field = 7;\n global FIRST_NULLIFIER_IN_TX: Field = 47;\n global CONTRACT_ADDRESS: AztecAddress = AztecAddress::from_field(13);\n global STORAGE_SLOT: Field = 99;\n\n #[test]\n unconstrained fn no_note_hashes() {\n let unique_note_hashes_in_tx = BoundedVec::new();\n let packed_note = BoundedVec::new();\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n MockNote::get_id(),\n packed_note,\n );\n\n assert_eq(discovered_notes.len(), 0);\n }\n\n #[test(should_fail_with = \"Failed to compute a note hash\")]\n unconstrained fn failed_hash_computation() {\n let unique_note_hashes_in_tx = BoundedVec::from_array([random()]);\n let packed_note = BoundedVec::new();\n let note_type_id = 0; // This note type id is unknown to compute_note_hash_and_nullifier\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n note_type_id,\n packed_note,\n );\n\n assert_eq(discovered_notes.len(), 0);\n }\n\n struct NoteAndData {\n note: MockNote,\n note_nonce: Field,\n note_hash: Field,\n unique_note_hash: Field,\n inner_nullifier: Field,\n }\n\n unconstrained fn construct_note(value: Field, note_index_in_tx: u32) -> NoteAndData {\n let note_nonce = compute_note_hash_nonce(FIRST_NULLIFIER_IN_TX, note_index_in_tx);\n\n let retrieved_note = MockNote::new(value)\n .contract_address(CONTRACT_ADDRESS)\n .note_metadata(SettledNoteMetadata::new(note_nonce).into())\n .build_retrieved_note();\n let note = retrieved_note.note;\n\n let note_hash = note.compute_note_hash(STORAGE_SLOT);\n let unique_note_hash = compute_unique_note_hash(\n note_nonce,\n compute_siloed_note_hash(CONTRACT_ADDRESS, note_hash),\n );\n let inner_nullifier = note.compute_nullifier_unconstrained(compute_note_hash_for_nullify(\n retrieved_note,\n STORAGE_SLOT,\n ));\n\n NoteAndData { note, note_nonce, note_hash, unique_note_hash, inner_nullifier }\n }\n\n #[test]\n unconstrained fn single_note() {\n let note_index_in_tx = 2;\n let note_and_data = construct_note(VALUE, note_index_in_tx);\n\n let mut unique_note_hashes_in_tx = BoundedVec::from_array([\n random(), random(), random(), random(), random(), random(), random(),\n ]);\n unique_note_hashes_in_tx.set(note_index_in_tx, note_and_data.unique_note_hash);\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n MockNote::get_id(),\n BoundedVec::from_array(note_and_data.note.pack()),\n );\n\n assert_eq(discovered_notes.len(), 1);\n let discovered_note = discovered_notes.get(0);\n\n assert_eq(discovered_note.note_nonce, note_and_data.note_nonce);\n assert_eq(discovered_note.note_hash, note_and_data.note_hash);\n assert_eq(discovered_note.inner_nullifier, note_and_data.inner_nullifier);\n }\n\n #[test]\n unconstrained fn multiple_notes_same_preimage() {\n let first_note_index_in_tx = 3;\n let first_note_and_data = construct_note(VALUE, first_note_index_in_tx);\n\n let second_note_index_in_tx = 5;\n let second_note_and_data = construct_note(VALUE, second_note_index_in_tx);\n\n // Both notes have the same preimage (and therefore packed representation), so both should be found in the same\n // call.\n assert_eq(first_note_and_data.note, second_note_and_data.note);\n let packed_note = first_note_and_data.note.pack();\n\n let mut unique_note_hashes_in_tx = BoundedVec::from_array([\n random(), random(), random(), random(), random(), random(), random(),\n ]);\n unique_note_hashes_in_tx.set(first_note_index_in_tx, first_note_and_data.unique_note_hash);\n unique_note_hashes_in_tx.set(second_note_index_in_tx, second_note_and_data.unique_note_hash);\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n MockNote::get_id(),\n BoundedVec::from_array(packed_note),\n );\n\n assert_eq(discovered_notes.len(), 2);\n\n assert(discovered_notes.any(|discovered_note| {\n (discovered_note.note_nonce == first_note_and_data.note_nonce)\n & (discovered_note.note_hash == first_note_and_data.note_hash)\n & (discovered_note.inner_nullifier == first_note_and_data.inner_nullifier)\n }));\n\n assert(discovered_notes.any(|discovered_note| {\n (discovered_note.note_nonce == second_note_and_data.note_nonce)\n & (discovered_note.note_hash == second_note_and_data.note_hash)\n & (discovered_note.inner_nullifier == second_note_and_data.inner_nullifier)\n }));\n }\n}\n" + }, + "112": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr", + "source": "use crate::{\n capsules::CapsuleArray,\n messages::{\n discovery::{ComputeNoteHashAndNullifier, nonce_discovery::attempt_note_nonce_discovery},\n encoding::MAX_MESSAGE_CONTENT_LEN,\n processing::{\n enqueue_note_for_validation, get_pending_partial_notes_completion_logs,\n log_retrieval_response::LogRetrievalResponse,\n },\n },\n utils::array,\n};\n\nuse protocol_types::{\n address::AztecAddress,\n debug_log::debug_log_format,\n hash::sha256_to_field,\n traits::{Deserialize, Serialize},\n};\n\nglobal PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN: u32 = 2;\n\n/// Partial notes have a maximum packed length of their private fields bound by extra content in their private message\n/// (e.g. the storage slot, note completion log tag, etc.).\npub global MAX_PARTIAL_NOTE_PRIVATE_PACKED_LEN: u32 =\n MAX_MESSAGE_CONTENT_LEN - PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN;\n\n/// The slot in the PXE capsules where we store a `CapsuleArray` of `DeliveredPendingPartialNote`.\npub global DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT\".as_bytes(),\n);\n\n/// A partial note that was delivered but is still pending completion. Contains the information necessary to find the\n/// log that will complete it and lead to a note being discovered and delivered.\n#[derive(Serialize, Deserialize)]\npub(crate) struct DeliveredPendingPartialNote {\n pub(crate) note_completion_log_tag: Field,\n pub(crate) storage_slot: Field,\n pub(crate) note_type_id: Field,\n pub(crate) packed_private_note_content: BoundedVec,\n pub(crate) recipient: AztecAddress,\n}\n\npub unconstrained fn process_partial_note_private_msg(\n contract_address: AztecAddress,\n recipient: AztecAddress,\n msg_metadata: u64,\n msg_content: BoundedVec,\n) {\n let (note_type_id, storage_slot, note_completion_log_tag, packed_private_note_content) =\n decode_partial_note_private_msg(msg_metadata, msg_content);\n\n // We store the information of the partial note we found in a persistent capsule in PXE, so that we can later search\n // for the public log that will complete it.\n let pending = DeliveredPendingPartialNote {\n note_completion_log_tag,\n storage_slot,\n note_type_id,\n packed_private_note_content,\n recipient,\n };\n\n CapsuleArray::at(\n contract_address,\n DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT,\n )\n .push(pending);\n}\n\n/// Searches for logs that would result in the completion of pending partial notes, ultimately resulting in the notes\n/// being delivered to PXE if completed.\npub unconstrained fn fetch_and_process_partial_note_completion_logs(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n) {\n let pending_partial_notes = CapsuleArray::at(\n contract_address,\n DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT,\n );\n\n debug_log_format(\n \"{} pending partial notes\",\n [pending_partial_notes.len() as Field],\n );\n\n // Each of the pending partial notes might get completed by a log containing its public values. For performance\n // reasons, we fetch all of these logs concurrently and then process them one by one, minimizing the amount of time\n // waiting for the node roundtrip.\n let maybe_completion_logs =\n get_pending_partial_notes_completion_logs(contract_address, pending_partial_notes);\n\n // Each entry in the maybe completion logs array corresponds to the entry in the pending partial notes array at the\n // same index. This means we can use the same index as we iterate through the responses to get both the partial note\n // and the log that might complete it.\n assert_eq(maybe_completion_logs.len(), pending_partial_notes.len());\n\n maybe_completion_logs.for_each(|i, maybe_log: Option| {\n // We clear the completion logs as we read them so that the array is empty by the time we next query it.\n // TODO(#14943): use volatile arrays to avoid having to manually clear this.\n maybe_completion_logs.remove(i);\n\n let pending_partial_note = pending_partial_notes.get(i);\n\n if maybe_log.is_none() {\n debug_log_format(\n \"Found no completion logs for partial note with tag {}\",\n [pending_partial_note.note_completion_log_tag],\n );\n\n // Note that we're not removing the pending partial note from the capsule array, so we will continue\n // searching for this tagged log when performing message discovery in the future until we either find it or\n // the entry is somehow removed from the array.\n } else {\n debug_log_format(\n \"Completion log found for partial note with tag {}\",\n [pending_partial_note.note_completion_log_tag],\n );\n let log = maybe_log.unwrap();\n\n // Public fields are assumed to all be placed at the end of the packed representation, so we combine the\n // private and public packed fields (i.e. the contents of the private message and public log plaintext to get\n // the complete packed content.\n let complete_packed_note = array::append(\n pending_partial_note.packed_private_note_content,\n log.log_payload,\n );\n\n let discovered_notes = attempt_note_nonce_discovery(\n log.unique_note_hashes_in_tx,\n log.first_nullifier_in_tx,\n compute_note_hash_and_nullifier,\n contract_address,\n pending_partial_note.storage_slot,\n pending_partial_note.note_type_id,\n complete_packed_note,\n );\n\n // TODO(#11627): is there anything reasonable we can do if we get a log but it doesn't result in a note\n // being found?\n if discovered_notes.len() == 0 {\n panic(\n f\"A partial note's completion log did not result in any notes being found - this should never happen\",\n );\n }\n\n debug_log_format(\n \"Discovered {0} notes for partial note with tag {1}\",\n [discovered_notes.len() as Field, pending_partial_note.note_completion_log_tag],\n );\n\n discovered_notes.for_each(|discovered_note| {\n enqueue_note_for_validation(\n contract_address,\n pending_partial_note.storage_slot,\n discovered_note.note_nonce,\n complete_packed_note,\n discovered_note.note_hash,\n discovered_note.inner_nullifier,\n log.tx_hash,\n pending_partial_note.recipient,\n );\n });\n\n // Because there is only a single log for a given tag, once we've processed the tagged log then we\n // simply delete the pending work entry, regardless of whether it was actually completed or not.\n pending_partial_notes.remove(i);\n }\n });\n}\n\nfn decode_partial_note_private_msg(\n msg_metadata: u64,\n msg_content: BoundedVec,\n) -> (Field, Field, Field, BoundedVec) {\n let note_type_id = msg_metadata as Field; // TODO: make note type id not be a full field\n\n assert(\n msg_content.len() > PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN,\n f\"Invalid private note message: all partial note private messages must have at least {PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN} fields\",\n );\n\n // If PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN is changed, causing the assertion below to fail, then the\n // destructuring of the partial note private message encoding below must be updated as well.\n std::static_assert(\n PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN == 2,\n \"unexpected value for PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN\",\n );\n\n // We currently have two fields that are not the partial note's packed representation, which are the storage slot\n // and the note completion log tag.\n let storage_slot = msg_content.get(0);\n let note_completion_log_tag = msg_content.get(1);\n\n let packed_private_note_content = array::subbvec(msg_content, 2);\n\n (note_type_id, storage_slot, note_completion_log_tag, packed_private_note_content)\n}\n" + }, + "113": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/discovery/private_events.nr", + "source": "use crate::{\n event::event_selector::EventSelector,\n messages::{encoding::MAX_MESSAGE_CONTENT_LEN, processing::enqueue_event_for_validation},\n utils::array,\n};\nuse protocol_types::{\n address::AztecAddress, constants::GENERATOR_INDEX__EVENT_COMMITMENT,\n hash::poseidon2_hash_with_separator_bounded_vec, traits::FromField,\n};\n\n/// The number of fields in a private event message content that are not the event's serialized representation\n/// (1 field for randomness).\nglobal PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN: u32 = 1;\n\n/// The maximum length of the packed representation of an event's contents. This is limited by private log size,\n/// encryption overhead and extra fields in the message (e.g. message type id, randomness, etc.).\npub global MAX_EVENT_SERIALIZED_LEN: u32 =\n MAX_MESSAGE_CONTENT_LEN - PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN;\n\npub unconstrained fn process_private_event_msg(\n contract_address: AztecAddress,\n recipient: AztecAddress,\n msg_metadata: u64,\n msg_content: BoundedVec,\n tx_hash: Field,\n) {\n // In the case of events, the msg metadata is the event selector.\n let event_type_id = EventSelector::from_field(msg_metadata as Field);\n\n assert(\n msg_content.len() > PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN,\n f\"Invalid private event message: all private event messages must have at least {PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN} fields\",\n );\n\n // If PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN is changed, causing the assertion below to fail, then the\n // destructuring of the private event message encoding below must be updated as well.\n std::static_assert(\n PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN == 1,\n \"unexpected value for PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN\",\n );\n\n let serialized_event_with_randomness = msg_content;\n\n let event_commitment = poseidon2_hash_with_separator_bounded_vec(\n serialized_event_with_randomness,\n GENERATOR_INDEX__EVENT_COMMITMENT,\n );\n\n // Randomness was injected into the event payload in `emit_event_in_private` but we have already used it\n // to compute the event commitment, so we can safely discard it now.\n let serialized_event = array::subbvec(\n serialized_event_with_randomness,\n PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN,\n );\n\n enqueue_event_for_validation(\n contract_address,\n event_type_id,\n serialized_event,\n event_commitment,\n tx_hash,\n recipient,\n );\n}\n" + }, + "114": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/discovery/private_notes.nr", + "source": "use crate::{\n messages::{\n discovery::{ComputeNoteHashAndNullifier, nonce_discovery::attempt_note_nonce_discovery},\n encoding::MAX_MESSAGE_CONTENT_LEN,\n processing::enqueue_note_for_validation,\n },\n utils::array,\n};\nuse protocol_types::{\n address::AztecAddress, constants::MAX_NOTE_HASHES_PER_TX, debug_log::debug_log_format,\n};\n\n/// The number of fields in a private note message content that are not the note's packed representation.\n// See the call to `std::static_assert` below to see what's in these fields.\nglobal PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN: u32 = 1;\n\n/// The maximum length of the packed representation of a note's contents. This is limited by private log size,\n/// encryption overhead and extra fields in the message (e.g. message type id, storage slot, etc.).\npub global MAX_NOTE_PACKED_LEN: u32 =\n MAX_MESSAGE_CONTENT_LEN - PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN;\n\npub unconstrained fn process_private_note_msg(\n contract_address: AztecAddress,\n tx_hash: Field,\n unique_note_hashes_in_tx: BoundedVec,\n first_nullifier_in_tx: Field,\n recipient: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n msg_metadata: u64,\n msg_content: BoundedVec,\n) {\n let (note_type_id, storage_slot, packed_note) =\n decode_private_note_msg(msg_metadata, msg_content);\n\n attempt_note_discovery(\n contract_address,\n tx_hash,\n unique_note_hashes_in_tx,\n first_nullifier_in_tx,\n recipient,\n compute_note_hash_and_nullifier,\n storage_slot,\n note_type_id,\n packed_note,\n );\n}\n\n/// Attempts discovery of a note given information about its contents and the transaction in which it is\n/// suspected the note was created.\npub unconstrained fn attempt_note_discovery(\n contract_address: AztecAddress,\n tx_hash: Field,\n unique_note_hashes_in_tx: BoundedVec,\n first_nullifier_in_tx: Field,\n recipient: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n storage_slot: Field,\n note_type_id: Field,\n packed_note: BoundedVec,\n) {\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n first_nullifier_in_tx,\n compute_note_hash_and_nullifier,\n contract_address,\n storage_slot,\n note_type_id,\n packed_note,\n );\n\n debug_log_format(\n \"Discovered {0} notes from a private message\",\n [discovered_notes.len() as Field],\n );\n\n discovered_notes.for_each(|discovered_note| {\n enqueue_note_for_validation(\n contract_address,\n storage_slot,\n discovered_note.note_nonce,\n packed_note,\n discovered_note.note_hash,\n discovered_note.inner_nullifier,\n tx_hash,\n recipient,\n );\n });\n}\n\nfn decode_private_note_msg(\n msg_metadata: u64,\n msg_content: BoundedVec,\n) -> (Field, Field, BoundedVec) {\n let note_type_id = msg_metadata as Field; // TODO: make note type id not be a full field\n\n assert(\n msg_content.len() > PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN,\n f\"Invalid private note message: all private note messages must have at least {PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN} fields\",\n );\n\n // If PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN is changed, causing the assertion below to fail, then the\n // destructuring of the private note message encoding below must be updated as well.\n std::static_assert(\n PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN == 1,\n \"unexpected value for PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN\",\n );\n\n // We currently have a single field that is not the note's packed representation, which is the storage slot.\n let storage_slot = msg_content.get(0);\n let packed_note = array::subbvec(msg_content, PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN);\n\n (note_type_id, storage_slot, packed_note)\n}\n" + }, + "115": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/discovery/process_message.nr", + "source": "use crate::messages::{\n discovery::{\n ComputeNoteHashAndNullifier, partial_notes::process_partial_note_private_msg,\n private_events::process_private_event_msg, private_notes::process_private_note_msg,\n },\n encoding::decode_message,\n encryption::{aes128::AES128, log_encryption::LogEncryption},\n msg_type::{\n PARTIAL_NOTE_PRIVATE_MSG_TYPE_ID, PRIVATE_EVENT_MSG_TYPE_ID, PRIVATE_NOTE_MSG_TYPE_ID,\n },\n processing::message_context::MessageContext,\n};\n\nuse protocol_types::{\n address::AztecAddress,\n constants::PRIVATE_LOG_CIPHERTEXT_LEN,\n debug_log::{debug_log, debug_log_format},\n};\n\n/// Processes a message that can contain notes, partial notes, or events.\n///\n/// Notes result in nonce discovery being performed prior to delivery, which requires knowledge of the transaction hash\n/// in which the notes would've been created (typically the same transaction in which the log was emitted), along with\n/// the list of unique note hashes in said transaction and the `compute_note_hash_and_nullifier` function. Once\n/// discovered, the notes are enqueued for validation.\n///\n/// Partial notes result in a pending partial note entry being stored in a PXE capsule, which will later be retrieved to\n/// search for the note's completion public log.\n///\n/// Events are processed by computing an event commitment from the serialized event data and its randomness field, then\n/// enqueueing the event data and commitment for validation.\npub unconstrained fn do_process_message(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n message_ciphertext: BoundedVec,\n message_context: MessageContext,\n) {\n let message = AES128::decrypt_log(message_ciphertext, message_context.recipient);\n\n // The first thing to do after decrypting the message is to determine what type of message we're processing. We\n // have 3 message types: private notes, partial notes and events.\n\n // We decode the message to obtain the message type id, metadata and content.\n let (msg_type_id, msg_metadata, msg_content) = decode_message(message);\n\n if msg_type_id == PRIVATE_NOTE_MSG_TYPE_ID {\n debug_log(\"Processing private note msg\");\n\n process_private_note_msg(\n contract_address,\n message_context.tx_hash,\n message_context.unique_note_hashes_in_tx,\n message_context.first_nullifier_in_tx,\n message_context.recipient,\n compute_note_hash_and_nullifier,\n msg_metadata,\n msg_content,\n );\n } else if msg_type_id == PARTIAL_NOTE_PRIVATE_MSG_TYPE_ID {\n debug_log(\"Processing partial note private msg\");\n\n process_partial_note_private_msg(\n contract_address,\n message_context.recipient,\n msg_metadata,\n msg_content,\n );\n } else if msg_type_id == PRIVATE_EVENT_MSG_TYPE_ID {\n debug_log(\"Processing private event msg\");\n\n process_private_event_msg(\n contract_address,\n message_context.recipient,\n msg_metadata,\n msg_content,\n message_context.tx_hash,\n );\n } else {\n debug_log_format(\"Unknown msg type id {0}\", [msg_type_id as Field]);\n }\n}\n" + }, + "116": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/encoding.nr", + "source": "// TODO(#12750): don't make these values assume we're using AES.\nuse crate::{\n messages::encryption::log_encryption::PRIVATE_LOG_PLAINTEXT_SIZE_IN_FIELDS, utils::array,\n};\n\npub global MAX_MESSAGE_LEN: u32 = PRIVATE_LOG_PLAINTEXT_SIZE_IN_FIELDS;\n\nglobal MESSAGE_EXPANDED_METADATA_LEN: u32 = 1;\n\n// The standard message layout is composed of:\n// - an initial field called the 'expanded metadata'\n// - an arbitrary number of fields following that called the 'message content'\n//\n// ```\n// message: [ msg_expanded_metadata, ...msg_content ]\n// ```\n//\n// The expanded metadata itself is interpreted as a u128, of which:\n// - the upper 64 bits are the message type id\n// - the lower 64 bits are called the 'message metadata'\n//\n// ```\n// msg_expanded_metadata: [ msg_type_id | msg_metadata ]\n// <--- 64 bits --->|<--- 64 bits --->\n// ```\n//\n// The meaning of the message metadata and message content depend on the value of the message type id. Note that there\n// is nothing special about the message metadata, it _can_ be considered part of the content. It just has a different\n// name to make it distinct from the message content given that it is not a full field.\n\n/// The maximum length of a message's content, i.e. not including the expanded message metadata.\npub global MAX_MESSAGE_CONTENT_LEN: u32 = MAX_MESSAGE_LEN - MESSAGE_EXPANDED_METADATA_LEN;\n\n/// Encodes a message following aztec-nr's standard message encoding. This message can later be decoded with\n/// `decode_message` to retrieve the original values.\n///\n/// - The `msg_type` is an identifier that groups types of messages that are all processed the same way, e.g. private\n/// notes or events. Possible values are defined in `aztec::messages::msg_type`.\n/// - The `msg_metadata` and `msg_content` are the values stored in the message, whose meaning depends on the\n/// `msg_type`. The only special thing about `msg_metadata` that separates it from `msg_content` is that it is a u64\n/// instead of a full Field (due to details of how messages are encoded), allowing applications that can fit values into\n/// this smaller variable to achieve higher data efficiency.\npub fn encode_message(\n msg_type: u64,\n msg_metadata: u64,\n msg_content: [Field; N],\n) -> [Field; (N + MESSAGE_EXPANDED_METADATA_LEN)] {\n std::static_assert(\n msg_content.len() <= MAX_MESSAGE_CONTENT_LEN,\n \"Invalid message content: it must have a length of at most MAX_MESSAGE_CONTENT_LEN\",\n );\n\n // If MESSAGE_EXPANDED_METADATA_LEN is changed, causing the assertion below to fail, then the destructuring of\n // the message encoding below must be updated as well.\n std::static_assert(\n MESSAGE_EXPANDED_METADATA_LEN == 1,\n \"unexpected value for MESSAGE_EXPANDED_METADATA_LEN\",\n );\n let mut message: [Field; (N + MESSAGE_EXPANDED_METADATA_LEN)] = std::mem::zeroed();\n\n message[0] = to_expanded_metadata(msg_type, msg_metadata);\n for i in 0..msg_content.len() {\n message[MESSAGE_EXPANDED_METADATA_LEN + i] = msg_content[i];\n }\n\n message\n}\n\n/// Decodes a standard aztec-nr message, i.e. one created via `encode_message`, returning the original encoded values.\n///\n/// Note that `encode_message` returns a fixed size array while this function takes a `BoundedVec`: this is because\n/// prior to decoding the message type is unknown, and consequentially not known at compile time. If working with\n/// fixed-size messages, consider using `BoundedVec::from_array` to convert them.\npub unconstrained fn decode_message(\n message: BoundedVec,\n) -> (u64, u64, BoundedVec) {\n assert(\n message.len() >= MESSAGE_EXPANDED_METADATA_LEN,\n f\"Invalid message: it must have at least {MESSAGE_EXPANDED_METADATA_LEN} fields\",\n );\n\n // If MESSAGE_EXPANDED_METADATA_LEN is changed, causing the assertion below to fail, then the destructuring of\n // the message encoding below must be updated as well.\n std::static_assert(\n MESSAGE_EXPANDED_METADATA_LEN == 1,\n \"unexpected value for MESSAGE_EXPANDED_METADATA_LEN\",\n );\n\n let msg_expanded_metadata = message.get(0);\n let (msg_type_id, msg_metadata) = from_expanded_metadata(msg_expanded_metadata);\n let msg_content = array::subbvec(message, MESSAGE_EXPANDED_METADATA_LEN);\n\n (msg_type_id, msg_metadata, msg_content)\n}\n\nglobal U64_SHIFT_MULTIPLIER: Field = 2.pow_32(64);\n\nfn to_expanded_metadata(msg_type: u64, msg_metadata: u64) -> Field {\n // We use multiplication instead of bit shifting operations to shift the type bits as bit shift operations are\n // expensive in circuits.\n let type_field: Field = (msg_type as Field) * U64_SHIFT_MULTIPLIER;\n let msg_metadata_field = msg_metadata as Field;\n\n type_field + msg_metadata_field\n}\n\nfn from_expanded_metadata(input: Field) -> (u64, u64) {\n input.assert_max_bit_size::<128>();\n let msg_metadata = (input as u64);\n let msg_type = ((input - (msg_metadata as Field)) / U64_SHIFT_MULTIPLIER) as u64;\n // Use division instead of bit shift since bit shifts are expensive in circuits\n (msg_type, msg_metadata)\n}\n\nmod tests {\n use crate::utils::array::subarray::subarray;\n use super::{\n decode_message, encode_message, from_expanded_metadata, MAX_MESSAGE_CONTENT_LEN,\n to_expanded_metadata,\n };\n\n global U64_MAX: u64 = (2.pow_32(64) - 1) as u64;\n global U128_MAX: Field = (2.pow_32(128) - 1);\n\n #[test]\n unconstrained fn encode_decode_empty_message(msg_type: u64, msg_metadata: u64) {\n let encoded = encode_message(msg_type, msg_metadata, []);\n let (decoded_msg_type, decoded_msg_metadata, decoded_msg_content) =\n decode_message(BoundedVec::from_array(encoded));\n\n assert_eq(decoded_msg_type, msg_type);\n assert_eq(decoded_msg_metadata, msg_metadata);\n assert_eq(decoded_msg_content.len(), 0);\n }\n\n #[test]\n unconstrained fn encode_decode_short_message(\n msg_type: u64,\n msg_metadata: u64,\n msg_content: [Field; MAX_MESSAGE_CONTENT_LEN / 2],\n ) {\n let encoded = encode_message(msg_type, msg_metadata, msg_content);\n let (decoded_msg_type, decoded_msg_metadata, decoded_msg_content) =\n decode_message(BoundedVec::from_array(encoded));\n\n assert_eq(decoded_msg_type, msg_type);\n assert_eq(decoded_msg_metadata, msg_metadata);\n assert_eq(decoded_msg_content.len(), msg_content.len());\n assert_eq(subarray(decoded_msg_content.storage(), 0), msg_content);\n }\n\n #[test]\n unconstrained fn encode_decode_full_message(\n msg_type: u64,\n msg_metadata: u64,\n msg_content: [Field; MAX_MESSAGE_CONTENT_LEN],\n ) {\n let encoded = encode_message(msg_type, msg_metadata, msg_content);\n let (decoded_msg_type, decoded_msg_metadata, decoded_msg_content) =\n decode_message(BoundedVec::from_array(encoded));\n\n assert_eq(decoded_msg_type, msg_type);\n assert_eq(decoded_msg_metadata, msg_metadata);\n assert_eq(decoded_msg_content.len(), msg_content.len());\n assert_eq(subarray(decoded_msg_content.storage(), 0), msg_content);\n }\n\n #[test]\n unconstrained fn to_expanded_metadata_packing() {\n // Test case 1: All bits set\n let packed = to_expanded_metadata(U64_MAX, U64_MAX);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 2: Only log type bits set\n let packed = to_expanded_metadata(U64_MAX, 0);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, 0);\n\n // Test case 3: Only msg_metadata bits set\n let packed = to_expanded_metadata(0, U64_MAX);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 4: No bits set\n let packed = to_expanded_metadata(0, 0);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, 0);\n }\n\n #[test]\n unconstrained fn from_expanded_metadata_packing() {\n // Test case 1: All bits set\n let input = U128_MAX as Field;\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 2: Only log type bits set\n let input = (U128_MAX - U64_MAX as Field);\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, 0);\n\n // Test case 3: Only msg_metadata bits set\n let input = U64_MAX as Field;\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 4: No bits set\n let input = 0;\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, 0);\n }\n\n #[test]\n unconstrained fn to_from_expanded_metadata(original_msg_type: u64, original_msg_metadata: u64) {\n let packed = to_expanded_metadata(original_msg_type, original_msg_metadata);\n let (unpacked_msg_type, unpacked_msg_metadata) = from_expanded_metadata(packed);\n\n assert_eq(original_msg_type, unpacked_msg_type);\n assert_eq(original_msg_metadata, unpacked_msg_metadata);\n }\n}\n" + }, + "117": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/encryption/aes128.nr", + "source": "use dep::protocol_types::{\n address::AztecAddress,\n constants::{\n GENERATOR_INDEX__SYMMETRIC_KEY, GENERATOR_INDEX__SYMMETRIC_KEY_2,\n PRIVATE_LOG_CIPHERTEXT_LEN,\n },\n hash::poseidon2_hash_with_separator,\n point::Point,\n};\n\nuse crate::{\n keys::{\n ecdh_shared_secret::derive_ecdh_shared_secret_using_aztec_address,\n ephemeral::generate_ephemeral_key_pair,\n },\n messages::{\n encryption::log_encryption::{\n EPH_PK_SIGN_BYTE_SIZE_IN_BYTES, EPH_PK_X_SIZE_IN_FIELDS,\n HEADER_CIPHERTEXT_SIZE_IN_BYTES, LogEncryption, PRIVATE_LOG_PLAINTEXT_SIZE_IN_FIELDS,\n },\n logs::arithmetic_generics_utils::{\n get_arr_of_size__log_bytes__from_PT, get_arr_of_size__log_bytes_padding__from_PT,\n },\n },\n oracle::{aes128_decrypt::aes128_decrypt_oracle, shared_secret::get_shared_secret},\n utils::{\n array,\n conversion::{\n bytes_to_fields::{bytes_from_fields, bytes_to_fields},\n fields_to_bytes::{fields_from_bytes, fields_to_bytes},\n },\n point::{get_sign_of_point, point_from_x_coord_and_sign},\n random::get_random_bytes,\n },\n};\n\nuse std::aes128::aes128_encrypt;\n\n/**\n * Computes N close-to-uniformly-random 256 bits from a given ECDH shared_secret.\n *\n * NEVER re-use the same iv and sym_key.\n * DO NOT call this function more than once with the same shared_secret.\n *\n * This function is only known to be safe if shared_secret is computed by combining a \n * random ephemeral key with an address point. See big comment within the body of the function.\n * See big comment within the body of the function.\n */\nfn extract_many_close_to_uniformly_random_256_bits_from_ecdh_shared_secret_using_poseidon2_unsafe(\n shared_secret: Point,\n) -> [[u8; 32]; N] {\n /*\n * Unsafe because of https://eprint.iacr.org/2010/264.pdf Page 13, Lemma 2 (and the * two paragraphs below it).\n *\n * If you call this function, you need to be careful and aware of how the arg\n * `shared_secret` has been derived.\n *\n * The paper says that the way you derive aes keys and IVs should be fine with poseidon2\n * (modelled as a RO), as long as you _don't_ use Poseidon2 as a PRG to generate the * two exponents x & y which multiply to the shared secret S:\n *\n * S = [x*y]*G.\n *\n * (Otherwise, you would have to \"key\" poseidon2, i.e. generate a uniformly string K\n * which can be public and compute Hash(x) as poseidon(K,x)).\n * In that lemma, k would be 2*254=508, and m would be the number of points on the * grumpkin curve (which is close to r according to the Hasse bound).\n *\n * Our shared secret S is [esk * address_sk] * G, and the question is: * Can we compute hash(S) using poseidon2 instead of sha256?\n *\n * Well, esk is random and not generated with poseidon2, so that's good.\n * What about address_sk?\n * Well, address_sk = poseidon2(stuff) + ivsk, so there was some\n * discussion about whether address_sk is independent of poseidon2.\n * Given that ivsk is random and independent of poseidon2, the address_sk is also\n * independent of poseidon2.\n *\n * Tl;dr: we believe it's safe to hash S = [esk * address_sk] * G using poseidon2,\n * in order to derive a symmetric key.\n *\n * If you're calling this function for a differently-derived `shared_secret`, be\n * careful.\n *\n */\n\n /* The output of this function needs to be 32 random bytes.\n * A single field won't give us 32 bytes of entropy.\n * So we compute two \"random\" fields, by poseidon-hashing with two different\n * generators.\n * We then extract the last 16 (big endian) bytes of each \"random\" field.\n * Note: we use to_be_bytes because it's slightly more efficient. But we have to\n * be careful not to take bytes from the \"big end\", because the \"big\" byte is\n * not uniformly random over the byte: it only has < 6 bits of randomness, because\n * it's the big end of a 254-bit field element.\n */\n\n let mut all_bytes: [[u8; 32]; N] = std::mem::zeroed();\n // We restrict N to be < 2^8, because of how we compute the domain separator\n // from k below (where k <= N must be 8 bits). In practice, it's extremely\n // unlikely that an app will want to compute >= 256 ciphertexts.\n std::static_assert(N < 256, \"N too large\");\n for k in 0..N {\n // We augment the domain separator with the loop index, so that we can\n // generate N lots of randomness.\n let k_shift = (k as u16 << 8);\n let separator_1 = k_shift + GENERATOR_INDEX__SYMMETRIC_KEY as u16;\n let separator_2 = k_shift + GENERATOR_INDEX__SYMMETRIC_KEY_2 as u16;\n\n let rand1: Field =\n poseidon2_hash_with_separator([shared_secret.x, shared_secret.y], separator_1);\n let rand2: Field =\n poseidon2_hash_with_separator([shared_secret.x, shared_secret.y], separator_2);\n\n let rand1_bytes: [u8; 32] = rand1.to_be_bytes();\n let rand2_bytes: [u8; 32] = rand2.to_be_bytes();\n\n let mut bytes: [u8; 32] = [0; 32];\n for i in 0..16 {\n // We take bytes from the \"little end\" of the be-bytes arrays:\n let j = 32 - i - 1;\n bytes[i] = rand1_bytes[j];\n bytes[16 + i] = rand2_bytes[j];\n }\n\n all_bytes[k] = bytes;\n }\n\n all_bytes\n}\n\nfn derive_aes_symmetric_key_and_iv_from_uniformly_random_256_bits(\n many_random_256_bits: [[u8; 32]; N],\n) -> [([u8; 16], [u8; 16]); N] {\n // Many (sym_key, iv) pairs:\n let mut many_pairs: [([u8; 16], [u8; 16]); N] = std::mem::zeroed();\n for k in 0..N {\n let random_256_bits = many_random_256_bits[k];\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n for i in 0..16 {\n sym_key[i] = random_256_bits[i];\n iv[i] = random_256_bits[i + 16];\n }\n many_pairs[k] = (sym_key, iv);\n }\n\n many_pairs\n}\n\npub fn derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_poseidon2_unsafe(\n shared_secret: Point,\n) -> [([u8; 16], [u8; 16]); N] {\n let many_random_256_bits: [[u8; 32]; N] = extract_many_close_to_uniformly_random_256_bits_from_ecdh_shared_secret_using_poseidon2_unsafe(\n shared_secret,\n );\n\n derive_aes_symmetric_key_and_iv_from_uniformly_random_256_bits(many_random_256_bits)\n}\n\npub struct AES128 {}\n\nimpl LogEncryption for AES128 {\n fn encrypt_log(\n plaintext: [Field; PlaintextLen],\n recipient: AztecAddress,\n ) -> [Field; PRIVATE_LOG_CIPHERTEXT_LEN] {\n // AES 128 operates on bytes, not fields, so we need to convert the fields to bytes.\n // (This process is then reversed when processing the log in `do_process_log`)\n let plaintext_bytes = fields_to_bytes(plaintext);\n\n // *****************************************************************************\n // Compute the shared secret\n // *****************************************************************************\n\n let (eph_sk, eph_pk) = generate_ephemeral_key_pair();\n\n let eph_pk_sign_byte: u8 = get_sign_of_point(eph_pk) as u8;\n\n // (not to be confused with the tagging shared secret)\n let ciphertext_shared_secret =\n derive_ecdh_shared_secret_using_aztec_address(eph_sk, recipient);\n // TODO: also use this shared secret for deriving note randomness.\n\n // *****************************************************************************\n // Convert the plaintext into whatever format the encryption function expects\n // *****************************************************************************\n\n // Already done for this strategy: AES expects bytes.\n\n // *****************************************************************************\n // Encrypt the plaintext\n // *****************************************************************************\n\n // It is safe to call the `unsafe` function here, because we know the `shared_secret`\n // was derived using an AztecAddress (the recipient). See the block comment\n // at the start of this unsafe target function for more info.\n let pairs = derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_poseidon2_unsafe::<2>(\n ciphertext_shared_secret,\n );\n let (body_sym_key, body_iv) = pairs[0];\n let (header_sym_key, header_iv) = pairs[1];\n\n let ciphertext_bytes = aes128_encrypt(plaintext_bytes, body_iv, body_sym_key);\n\n // |full_pt| = |pt_length| + |pt|\n // |pt_aes_padding| = 16 - (|full_pt| % 16)\n // or... since a % b is the same as a - b * (a // b) (integer division), so:\n // |pt_aes_padding| = 16 - (|full_pt| - 16 * (|full_pt| // 16))\n // |ct| = |full_pt| + |pt_aes_padding|\n // = |full_pt| + 16 - (|full_pt| - 16 * (|full_pt| // 16))\n // = 16 + 16 * (|full_pt| // 16)\n // = 16 * (1 + |full_pt| // 16)\n assert(ciphertext_bytes.len() == 16 * (1 + (PlaintextLen * 32) / 16));\n\n // *****************************************************************************\n // Compute the header ciphertext\n // *****************************************************************************\n\n // Header contains only the length of the ciphertext stored in 2 bytes.\n let mut header_plaintext: [u8; 2] = [0 as u8; 2];\n let ciphertext_bytes_length = ciphertext_bytes.len();\n header_plaintext[0] = (ciphertext_bytes_length >> 8) as u8;\n header_plaintext[1] = ciphertext_bytes_length as u8;\n\n // Note: the aes128_encrypt builtin fn automatically appends bytes to the\n // input, according to pkcs#7; hence why the output `header_ciphertext_bytes` is 16\n // bytes larger than the input in this case.\n let header_ciphertext_bytes = aes128_encrypt(header_plaintext, header_iv, header_sym_key);\n // I recall that converting a slice to an array incurs constraints, so I'll check the length this way instead:\n assert(header_ciphertext_bytes.len() == HEADER_CIPHERTEXT_SIZE_IN_BYTES);\n\n // *****************************************************************************\n // Prepend / append more bytes of data to the ciphertext, before converting back\n // to fields.\n // *****************************************************************************\n\n let mut log_bytes_padding_to_mult_31 =\n get_arr_of_size__log_bytes_padding__from_PT::();\n // Safety: this randomness won't be constrained to be random. It's in the\n // interest of the executor of this fn to encrypt with random bytes.\n log_bytes_padding_to_mult_31 = unsafe { get_random_bytes() };\n\n let mut log_bytes = get_arr_of_size__log_bytes__from_PT::();\n\n assert(\n log_bytes.len() % 31 == 0,\n \"Unexpected error: log_bytes.len() should be divisible by 31, by construction.\",\n );\n\n log_bytes[0] = eph_pk_sign_byte;\n let mut offset = 1;\n for i in 0..header_ciphertext_bytes.len() {\n log_bytes[offset + i] = header_ciphertext_bytes[i];\n }\n offset += header_ciphertext_bytes.len();\n\n for i in 0..ciphertext_bytes.len() {\n log_bytes[offset + i] = ciphertext_bytes[i];\n }\n offset += ciphertext_bytes.len();\n\n for i in 0..log_bytes_padding_to_mult_31.len() {\n log_bytes[offset + i] = log_bytes_padding_to_mult_31[i];\n }\n\n assert(\n offset + log_bytes_padding_to_mult_31.len() == log_bytes.len(),\n \"Something has gone wrong\",\n );\n\n // *****************************************************************************\n // Convert bytes back to fields\n // *****************************************************************************\n\n // TODO(#12749): As Mike pointed out, we need to make logs produced by different encryption schemes\n // indistinguishable from each other and for this reason the output here and in the last for-loop of this function\n // should cover a full field.\n let log_bytes_as_fields = bytes_to_fields(log_bytes);\n\n // *****************************************************************************\n // Prepend / append fields, to create the final log\n // *****************************************************************************\n\n let mut ciphertext: [Field; PRIVATE_LOG_CIPHERTEXT_LEN] = [0; PRIVATE_LOG_CIPHERTEXT_LEN];\n\n ciphertext[0] = eph_pk.x;\n\n let mut offset = 1;\n for i in 0..log_bytes_as_fields.len() {\n ciphertext[offset + i] = log_bytes_as_fields[i];\n }\n offset += log_bytes_as_fields.len();\n\n for i in offset..PRIVATE_LOG_CIPHERTEXT_LEN {\n // We need to get a random value that fits in 31 bytes to not leak information about the size of the log\n // (all the \"real\" log fields contain at most 31 bytes because of the way we convert the bytes to fields).\n // TODO(#12749): Long term, this is not a good solution.\n\n // Safety: we assume that the sender wants for the log to be private - a malicious one could simply reveal its\n // contents publicly. It is therefore fine to trust the sender to provide random padding.\n let field_bytes = unsafe { get_random_bytes::<31>() };\n ciphertext[i] = Field::from_be_bytes::<31>(field_bytes);\n }\n\n ciphertext\n }\n\n unconstrained fn decrypt_log(\n ciphertext: BoundedVec,\n recipient: AztecAddress,\n ) -> BoundedVec {\n let eph_pk_x = ciphertext.get(0);\n\n let ciphertext_without_eph_pk_x_fields = array::subbvec::(\n ciphertext,\n EPH_PK_X_SIZE_IN_FIELDS,\n );\n\n // Convert the ciphertext represented as fields to a byte representation (its original format)\n let ciphertext_without_eph_pk_x = bytes_from_fields(ciphertext_without_eph_pk_x_fields);\n\n // First byte of the ciphertext represents the ephemeral public key sign\n let eph_pk_sign_bool = ciphertext_without_eph_pk_x.get(0) != 0;\n // With the sign and the x-coordinate of the ephemeral public key, we can reconstruct the point\n let eph_pk = point_from_x_coord_and_sign(eph_pk_x, eph_pk_sign_bool);\n\n // Derive shared secret\n let ciphertext_shared_secret = get_shared_secret(recipient, eph_pk);\n\n // Derive symmetric keys:\n let pairs = derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_poseidon2_unsafe::<2>(\n ciphertext_shared_secret,\n );\n let (body_sym_key, body_iv) = pairs[0];\n let (header_sym_key, header_iv) = pairs[1];\n\n // Extract the header ciphertext\n let header_start = EPH_PK_SIGN_BYTE_SIZE_IN_BYTES; // Skip eph_pk_sign byte\n let header_ciphertext: [u8; HEADER_CIPHERTEXT_SIZE_IN_BYTES] =\n array::subarray(ciphertext_without_eph_pk_x.storage(), header_start);\n // We need to convert the array to a BoundedVec because the oracle expects a BoundedVec as it's designed to work\n // with logs with unknown length at compile time. This would not be necessary here as the header ciphertext length\n // is fixed. But we do it anyway to not have to have duplicate oracles.\n let header_ciphertext_bvec =\n BoundedVec::::from_array(header_ciphertext);\n\n // Decrypt header\n let header_plaintext =\n aes128_decrypt_oracle(header_ciphertext_bvec, header_iv, header_sym_key);\n\n // Extract ciphertext length from header (2 bytes, big-endian)\n let ciphertext_length =\n ((header_plaintext.get(0) as u32) << 8) | (header_plaintext.get(1) as u32);\n\n // Extract and decrypt main ciphertext\n let ciphertext_start = header_start + HEADER_CIPHERTEXT_SIZE_IN_BYTES;\n let ciphertext_with_padding: [u8; (PRIVATE_LOG_CIPHERTEXT_LEN - EPH_PK_X_SIZE_IN_FIELDS) * 31 - HEADER_CIPHERTEXT_SIZE_IN_BYTES - EPH_PK_SIGN_BYTE_SIZE_IN_BYTES] =\n array::subarray(ciphertext_without_eph_pk_x.storage(), ciphertext_start);\n let ciphertext: BoundedVec =\n BoundedVec::from_parts(ciphertext_with_padding, ciphertext_length);\n\n // Decrypt main ciphertext and return it\n let plaintext_bytes = aes128_decrypt_oracle(ciphertext, body_iv, body_sym_key);\n\n // Each field of the original note log was serialized to 32 bytes so we convert the bytes back to fields.\n fields_from_bytes(plaintext_bytes)\n }\n}\n\nmod test {\n use crate::{\n keys::ecdh_shared_secret::derive_ecdh_shared_secret_using_aztec_address,\n messages::encryption::log_encryption::{LogEncryption, PRIVATE_LOG_PLAINTEXT_SIZE_IN_FIELDS},\n test::helpers::test_environment::TestEnvironment,\n };\n use super::AES128;\n use protocol_types::{\n address::AztecAddress,\n indexed_tagging_secret::IndexedTaggingSecret,\n traits::{Deserialize, FromField},\n };\n use std::{embedded_curve_ops::EmbeddedCurveScalar, test::OracleMock};\n\n #[test]\n unconstrained fn encrypt_decrypt_log() {\n let env = TestEnvironment::new();\n\n // Log decryption requires oracles that are only available during private execution\n env.private_context(|_| {\n let plaintext = [1, 2, 3];\n\n let recipient = AztecAddress::from_field(\n 0x25afb798ea6d0b8c1618e50fdeafa463059415013d3b7c75d46abf5e242be70c,\n );\n\n // Mock random values for deterministic test\n let eph_sk = 0x1358d15019d4639393d62b97e1588c095957ce74a1c32d6ec7d62fe6705d9538;\n let _ = OracleMock::mock(\"utilityGetRandomField\").returns(eph_sk).times(1);\n\n let randomness = 0x0101010101010101010101010101010101010101010101010101010101010101;\n let _ = OracleMock::mock(\"utilityGetRandomField\").returns(randomness).times(1000000);\n\n let _ = OracleMock::mock(\"utilityGetIndexedTaggingSecretAsSender\").returns(\n IndexedTaggingSecret::deserialize([69420, 1337]),\n );\n let _ = OracleMock::mock(\"privateIncrementAppTaggingSecretIndexAsSender\").returns(());\n\n // Encrypt the log\n let encrypted_log = BoundedVec::from_array(AES128::encrypt_log(plaintext, recipient));\n\n // Mock shared secret for deterministic test\n let shared_secret = derive_ecdh_shared_secret_using_aztec_address(\n EmbeddedCurveScalar::from_field(eph_sk),\n recipient,\n );\n let _ = OracleMock::mock(\"utilityGetSharedSecret\").returns(shared_secret);\n\n // Decrypt the log\n let decrypted = AES128::decrypt_log(encrypted_log, recipient);\n\n // The decryption function spits out a BoundedVec because it's designed to work with logs with unknown length\n // at compile time. For this reason we need to convert the original input to a BoundedVec.\n let plaintext_bvec =\n BoundedVec::::from_array(plaintext);\n\n // Verify decryption matches original plaintext\n assert_eq(\n decrypted,\n plaintext_bvec,\n \"Decrypted bytes should match original plaintext\",\n );\n\n // The following is a workaround of \"struct is never constructed\" Noir compilation error (we only ever use\n // static methods of the struct).\n let _ = AES128 {};\n });\n }\n}\n" + }, + "12": { + "path": "std/convert.nr", + "source": "// docs:start:from-trait\npub trait From {\n fn from(input: T) -> Self;\n}\n// docs:end:from-trait\n\nimpl From for T {\n fn from(input: T) -> T {\n input\n }\n}\n\n// docs:start:into-trait\npub trait Into {\n fn into(self) -> T;\n}\n\nimpl Into for U\nwhere\n T: From,\n{\n fn into(self) -> T {\n T::from(self)\n }\n}\n// docs:end:into-trait\n\n// docs:start:from-impls\n// Unsigned integers\n\nimpl From for u16 {\n fn from(value: u8) -> u16 {\n value as u16\n }\n}\n\nimpl From for u32 {\n fn from(value: u8) -> u32 {\n value as u32\n }\n}\n\nimpl From for u32 {\n fn from(value: u16) -> u32 {\n value as u32\n }\n}\n\nimpl From for u64 {\n fn from(value: u8) -> u64 {\n value as u64\n }\n}\n\nimpl From for u64 {\n fn from(value: u16) -> u64 {\n value as u64\n }\n}\n\nimpl From for u64 {\n fn from(value: u32) -> u64 {\n value as u64\n }\n}\n\nimpl From for u128 {\n fn from(value: u8) -> u128 {\n value as u128\n }\n}\n\nimpl From for u128 {\n fn from(value: u16) -> u128 {\n value as u128\n }\n}\n\nimpl From for u128 {\n fn from(value: u32) -> u128 {\n value as u128\n }\n}\nimpl From for u128 {\n fn from(value: u64) -> u128 {\n value as u128\n }\n}\n\nimpl From for Field {\n fn from(value: u8) -> Field {\n value as Field\n }\n}\n\nimpl From for Field {\n fn from(value: u16) -> Field {\n value as Field\n }\n}\n\nimpl From for Field {\n fn from(value: u32) -> Field {\n value as Field\n }\n}\nimpl From for Field {\n fn from(value: u64) -> Field {\n value as Field\n }\n}\n\nimpl From for Field {\n fn from(value: u128) -> Field {\n value as Field\n }\n}\n\n// Signed integers\n\nimpl From for i16 {\n fn from(value: i8) -> i16 {\n value as i16\n }\n}\n\nimpl From for i32 {\n fn from(value: i8) -> i32 {\n value as i32\n }\n}\n\nimpl From for i32 {\n fn from(value: i16) -> i32 {\n value as i32\n }\n}\n\nimpl From for i64 {\n fn from(value: i8) -> i64 {\n value as i64\n }\n}\n\nimpl From for i64 {\n fn from(value: i16) -> i64 {\n value as i64\n }\n}\n\nimpl From for i64 {\n fn from(value: i32) -> i64 {\n value as i64\n }\n}\n\n// Booleans\nimpl From for u8 {\n fn from(value: bool) -> u8 {\n value as u8\n }\n}\nimpl From for u16 {\n fn from(value: bool) -> u16 {\n value as u16\n }\n}\nimpl From for u32 {\n fn from(value: bool) -> u32 {\n value as u32\n }\n}\nimpl From for u64 {\n fn from(value: bool) -> u64 {\n value as u64\n }\n}\nimpl From for u128 {\n fn from(value: bool) -> u128 {\n value as u128\n }\n}\nimpl From for i8 {\n fn from(value: bool) -> i8 {\n value as i8\n }\n}\nimpl From for i16 {\n fn from(value: bool) -> i16 {\n value as i16\n }\n}\nimpl From for i32 {\n fn from(value: bool) -> i32 {\n value as i32\n }\n}\nimpl From for i64 {\n fn from(value: bool) -> i64 {\n value as i64\n }\n}\nimpl From for Field {\n fn from(value: bool) -> Field {\n value as Field\n }\n}\n// docs:end:from-impls\n\n/// A generic interface for casting between primitive types,\n/// equivalent of using the `as` keyword between values.\n///\n/// # Example\n///\n/// ```\n/// let x: Field = 1234567890;\n/// let y: u8 = x as u8;\n/// let z: u8 = x.as_();\n/// assert_eq(y, z);\n/// ```\npub trait AsPrimitive {\n /// The equivalent of doing `self as T`.\n fn as_(self) -> T;\n}\n\n#[generate_as_primitive_impls]\ncomptime fn generate_as_primitive_impls(_: FunctionDefinition) -> Quoted {\n let types = [\n quote { bool },\n quote { u8 },\n quote { u16 },\n quote { u32 },\n quote { u64 },\n quote { u128 },\n quote { i8 },\n quote { i16 },\n quote { i32 },\n quote { i64 },\n ];\n\n let mut impls = &[];\n for type1 in types {\n for type2 in types {\n let body = if type1 == type2 {\n quote { self }\n } else if type1 == quote { bool } {\n quote { self != 0 }\n } else {\n quote { self as $type1 }\n };\n\n impls = impls.push_back(\n quote {\n impl AsPrimitive<$type1> for $type2 {\n fn as_(self) -> $type1 {\n $body\n }\n }\n },\n );\n }\n }\n\n let u_types =\n [quote { bool }, quote { u8 }, quote { u16 }, quote { u32 }, quote { u64 }, quote { u128 }];\n\n for type2 in u_types {\n let body = quote { self as Field };\n\n impls = impls.push_back(\n quote {\n impl AsPrimitive for $type2 {\n fn as_(self) -> Field {\n $body\n }\n }\n },\n );\n }\n\n for type1 in u_types {\n let body = if type1 == quote { bool } {\n quote { self != 0 }\n } else {\n quote { self as $type1 }\n };\n\n impls = impls.push_back(\n quote {\n impl AsPrimitive<$type1> for Field {\n fn as_(self) -> $type1 {\n $body\n }\n }\n },\n );\n }\n\n impls.join(quote {})\n}\n" + }, + "133": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/processing/mod.nr", + "source": "pub(crate) mod event_validation_request;\npub mod message_context;\npub(crate) mod note_validation_request;\npub(crate) mod log_retrieval_request;\npub(crate) mod log_retrieval_response;\npub(crate) mod pending_tagged_log;\n\nuse crate::{\n capsules::CapsuleArray,\n event::event_selector::EventSelector,\n messages::{\n discovery::{\n partial_notes::DeliveredPendingPartialNote, private_events::MAX_EVENT_SERIALIZED_LEN,\n private_notes::MAX_NOTE_PACKED_LEN,\n },\n processing::{\n log_retrieval_request::LogRetrievalRequest,\n log_retrieval_response::LogRetrievalResponse,\n note_validation_request::NoteValidationRequest, pending_tagged_log::PendingTaggedLog,\n },\n },\n oracle,\n};\nuse event_validation_request::EventValidationRequest;\nuse protocol_types::{address::AztecAddress, hash::sha256_to_field};\n\n// Base slot for the pending tagged log array to which the fetch_tagged_logs oracle inserts found private logs.\nglobal PENDING_TAGGED_LOG_ARRAY_BASE_SLOT: Field =\n sha256_to_field(\"AZTEC_NR::PENDING_TAGGED_LOG_ARRAY_BASE_SLOT\".as_bytes());\n\nglobal NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\nglobal EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\nglobal LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\nglobal LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\n/// Searches for private logs emitted by `contract_address` that might contain messages for one of the local accounts,\n/// and stores them in a `CapsuleArray` which is then returned.\npub(crate) unconstrained fn get_private_logs(\n contract_address: AztecAddress,\n) -> CapsuleArray {\n // We will eventually perform log discovery via tagging here, but for now we simply call the `fetchTaggedLogs`\n // oracle. This makes PXE synchronize tags, download logs and store the pending tagged logs in a capsule array.\n oracle::message_processing::fetch_tagged_logs(PENDING_TAGGED_LOG_ARRAY_BASE_SLOT);\n\n CapsuleArray::at(contract_address, PENDING_TAGGED_LOG_ARRAY_BASE_SLOT)\n}\n\n/// Enqueues a note for validation by PXE, so that it becomes aware of a note's existence allowing for later retrieval\n/// via `get_notes` oracle. The note will be scoped to `contract_address`, meaning other contracts will not be able to\n/// access it unless authorized.\n///\n/// In order for the note validation and insertion to occur, `validate_enqueued_notes_and_events` must be later called.\n/// For optimal performance, accumulate as many note validation requests as possible and then validate them all at the\n/// end (which results in PXE minimizing the number of network round-trips).\n///\n/// The `packed_note` is what `getNotes` will later return. PXE indexes notes by `storage_slot`, so this value\n/// is typically used to filter notes that correspond to different state variables. `note_hash` and `nullifier` are\n/// the inner hashes, i.e. the raw hashes returned by `NoteHash::compute_note_hash` and\n/// `NoteHash::compute_nullifier`. PXE will verify that the siloed unique note hash was inserted into the tree\n/// at `tx_hash`, and will store the nullifier to later check for nullification.\n///\n/// `recipient` is the account to which the note was sent to. Other accounts will not be able to access this note (e.g.\n/// other accounts will not be able to see one another's token balance notes, even in the same PXE) unless authorized.\npub(crate) unconstrained fn enqueue_note_for_validation(\n contract_address: AztecAddress,\n storage_slot: Field,\n note_nonce: Field,\n packed_note: BoundedVec,\n note_hash: Field,\n nullifier: Field,\n tx_hash: Field,\n recipient: AztecAddress,\n) {\n // We store requests in a `CapsuleArray`, which PXE will later read from and deserialize into its version of the\n // Noir `NoteValidationRequest`\n CapsuleArray::at(contract_address, NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT).push(\n NoteValidationRequest {\n contract_address,\n storage_slot,\n note_nonce,\n packed_note,\n note_hash,\n nullifier,\n tx_hash,\n recipient,\n },\n )\n}\n\n/// Enqueues an event for validation by PXE, so that it can be efficiently validated and then inserted into the event\n/// store.\n///\n/// In order for the event validation and insertion to occur, `validate_enqueued_notes_and_events` must be later\n/// called. For optimal performance, accumulate as many event validation requests as possible and then validate them\n/// all at the end (which results in PXE minimizing the number of network round-trips).\npub(crate) unconstrained fn enqueue_event_for_validation(\n contract_address: AztecAddress,\n event_type_id: EventSelector,\n serialized_event: BoundedVec,\n event_commitment: Field,\n tx_hash: Field,\n recipient: AztecAddress,\n) {\n // We store requests in a `CapsuleArray`, which PXE will later read from and deserialize into its version of the\n // Noir `EventValidationRequest`\n CapsuleArray::at(contract_address, EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT).push(\n EventValidationRequest {\n contract_address,\n event_type_id,\n serialized_event,\n event_commitment,\n tx_hash,\n recipient,\n },\n )\n}\n\n/// Validates all note and event validation requests enqueued via `enqueue_note_for_validation` and\n/// `enqueue_event_for_validation`, inserting them into the note database and event store respectively, making them\n/// queryable via `get_notes` oracle and our TS API (PXE::getPrivateEvents).\n///\n/// This automatically clears both validation request queues, so no further work needs to be done by the caller.\npub(crate) unconstrained fn validate_enqueued_notes_and_events(contract_address: AztecAddress) {\n oracle::message_processing::validate_enqueued_notes_and_events(\n contract_address,\n NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT,\n EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT,\n );\n}\n\n/// Efficiently queries the node for logs that result in the completion of all `DeliveredPendingPartialNote`s stored in\n/// a `CapsuleArray` by performing all node communication concurrently. Returns a second `CapsuleArray` with Options for\n/// the responses that correspond to the pending partial notes at the same index.\n///\n/// For example, given an array with pending partial notes `[ p1, p2, p3 ]`, where `p1` and `p3` have corresponding\n/// completion logs but `p2` does not, the returned `CapsuleArray` will have contents\n/// `[some(p1_log), none(), some(p3_log)]`.\npub(crate) unconstrained fn get_pending_partial_notes_completion_logs(\n contract_address: AztecAddress,\n pending_partial_notes: CapsuleArray,\n) -> CapsuleArray> {\n let log_retrieval_requests =\n CapsuleArray::at(contract_address, LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT);\n\n // We create a LogRetrievalRequest for each PendingPartialNote in the CapsuleArray. Because we need the indices in\n // the request array to match the indices in the partial note array, we can't use CapsuleArray::for_each, as that\n // function has arbitrary iteration order. Instead, we manually iterate the array from the beginning and push into\n // the requests array, which we expect to be empty.\n let mut i = 0;\n let pending_partial_notes_count = pending_partial_notes.len();\n while i < pending_partial_notes_count {\n let pending_partial_note = pending_partial_notes.get(i);\n log_retrieval_requests.push(\n LogRetrievalRequest {\n contract_address,\n unsiloed_tag: pending_partial_note.note_completion_log_tag,\n },\n );\n i += 1;\n }\n\n oracle::message_processing::bulk_retrieve_logs(\n contract_address,\n LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT,\n LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT,\n );\n\n CapsuleArray::at(contract_address, LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT)\n}\n" + }, + "145": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/note/note_metadata.nr", + "source": "use protocol_types::traits::{Packable, Serialize};\n\n// There's temporarily quite a bit of boilerplate here because Noir does not yet support enums. This file will\n// eventually be simplified into something closer to:\n//\n// pub enum NoteMetadata {\n// PendingSamePhase{ note_hash_counter: u32 },\n// PendingOtherPhase{ note_hash_counter: u32, note_nonce: Field },\n// Settled{ note_nonce: Field },\n// }\n//\n// For now, we have `NoteMetadata` acting as a sort of tagged union.\n\nstruct NoteStageEnum {\n /// A note that was created in the transaction that is currently being executed, during the current execution phase,\n /// i.e. non-revertible or revertible.\n ///\n /// These notes are not yet in the note hash tree, though they will be inserted unless nullified in this transaction\n /// (becoming a transient note).\n PENDING_SAME_PHASE: u8,\n /// A note that was created in the transaction that is currently being executed, during the previous execution\n /// phase. Because there are only two phases and their order is always the same (first non-revertible and then\n /// revertible) this implies that the note was created in the non-revertible phase, and that the current phase is\n /// the revertible phase.\n ///\n /// These notes are not yet in the note hash tree, though they will be inserted **even if nullified in this\n /// transaction**. This means that they must be nullified as if they were settled (i.e. using the unique note hash)\n /// in order to avoid double spends once they become settled.\n PENDING_PREVIOUS_PHASE: u8,\n /// A note that was created in a prior transaction and is therefore already in the note hash tree.\n SETTLED: u8,\n}\n\nglobal NoteStage: NoteStageEnum =\n NoteStageEnum { PENDING_SAME_PHASE: 1, PENDING_PREVIOUS_PHASE: 2, SETTLED: 3 };\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a note in any of the three valid stages (pending same phase, pending previous phase, or settled). In\n/// order to access the underlying fields callers must first find the appropriate stage (e.g. via `is_settled()`) and\n/// then convert this into the appropriate type (e.g. via `to_settled()`).\n#[derive(Eq, Serialize, Packable)]\npub struct NoteMetadata {\n stage: u8,\n maybe_note_nonce: Field,\n}\n\nimpl NoteMetadata {\n /// Constructs a `NoteMetadata` object from optional note hash counter and nonce. Both a zero note hash counter and\n /// a zero nonce are invalid, so those are used to signal non-existent values.\n pub fn from_raw_data(nonzero_note_hash_counter: bool, maybe_note_nonce: Field) -> Self {\n if nonzero_note_hash_counter {\n if maybe_note_nonce == 0 {\n Self { stage: NoteStage.PENDING_SAME_PHASE, maybe_note_nonce }\n } else {\n Self { stage: NoteStage.PENDING_PREVIOUS_PHASE, maybe_note_nonce }\n }\n } else if maybe_note_nonce != 0 {\n Self { stage: NoteStage.SETTLED, maybe_note_nonce }\n } else {\n panic(\n f\"Note has a zero note hash counter and no nonce - existence cannot be proven\",\n )\n }\n }\n\n /// Returns true if the note is pending **and** from the same phase, i.e. if it's been created in the current\n /// transaction during the current execution phase (either non-revertible or revertible).\n pub fn is_pending_same_phase(self) -> bool {\n self.stage == NoteStage.PENDING_SAME_PHASE\n }\n\n /// Returns true if the note is pending **and** from the previous phase, i.e. if it's been created in the current\n /// transaction during an execution phase prior to the current one. Because private execution only has two phases\n /// with strict ordering, this implies that the note was created in the non-revertible phase, and that the current\n /// phase is the revertible phase.\n pub fn is_pending_previous_phase(self) -> bool {\n self.stage == NoteStage.PENDING_PREVIOUS_PHASE\n }\n\n /// Returns true if the note is settled, i.e. if it's been created in a prior transaction and is therefore already\n /// in the note hash tree.\n pub fn is_settled(self) -> bool {\n self.stage == NoteStage.SETTLED\n }\n\n /// Asserts that the metadata is that of a pending note from the same phase and converts it accordingly.\n pub fn to_pending_same_phase(self) -> PendingSamePhaseNoteMetadata {\n assert_eq(self.stage, NoteStage.PENDING_SAME_PHASE);\n PendingSamePhaseNoteMetadata::new()\n }\n\n /// Asserts that the metadata is that of a pending note from a previous phase and converts it accordingly.\n pub fn to_pending_previous_phase(self) -> PendingPreviousPhaseNoteMetadata {\n assert_eq(self.stage, NoteStage.PENDING_PREVIOUS_PHASE);\n PendingPreviousPhaseNoteMetadata::new(self.maybe_note_nonce)\n }\n\n /// Asserts that the metadata is that of a settled note and converts it accordingly.\n pub fn to_settled(self) -> SettledNoteMetadata {\n assert_eq(self.stage, NoteStage.SETTLED);\n SettledNoteMetadata::new(self.maybe_note_nonce)\n }\n}\n\nimpl From for NoteMetadata {\n fn from(_value: PendingSamePhaseNoteMetadata) -> Self {\n NoteMetadata::from_raw_data(true, std::mem::zeroed())\n }\n}\n\nimpl From for NoteMetadata {\n fn from(value: PendingPreviousPhaseNoteMetadata) -> Self {\n NoteMetadata::from_raw_data(true, value.note_nonce())\n }\n}\n\nimpl From for NoteMetadata {\n fn from(value: SettledNoteMetadata) -> Self {\n NoteMetadata::from_raw_data(false, value.note_nonce())\n }\n}\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a pending same phase note, i.e. a note that was created in the transaction that is currently being\n/// executed during the current execution phase (either non-revertible or revertible).\npub struct PendingSamePhaseNoteMetadata {\n // This struct contains no fields since there is no metadata associated with a pending same phase note: it has no\n // nonce (since it may get squashed by a nullifier emitted in the same phase), and while it does have a note hash\n // counter we cannot constrain its value (and don't need to - only that it is non-zero).\n}\n\nimpl PendingSamePhaseNoteMetadata {\n pub fn new() -> Self {\n Self {}\n }\n}\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a pending previous phase note, i.e. a note that was created in the transaction that is currently\n/// being executed, during the previous execution phase. Because there are only two phases and their order is always the\n/// same (first non-revertible and then revertible) this implies that the note was created in the non-revertible phase,\n/// and that the current phase is the revertible phase.\npub struct PendingPreviousPhaseNoteMetadata {\n note_nonce: Field,\n // This struct does not contain a note hash counter, even though one exists for this note, because we cannot\n // constrain its value (and don't need to - only that it is non-zero).\n}\n\nimpl PendingPreviousPhaseNoteMetadata {\n pub fn new(note_nonce: Field) -> Self {\n Self { note_nonce }\n }\n\n pub fn note_nonce(self) -> Field {\n self.note_nonce\n }\n}\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a settled note, i.e. a note that was created in a prior transaction and is therefore already in the\n/// note hash tree.\npub struct SettledNoteMetadata {\n note_nonce: Field,\n}\n\nimpl SettledNoteMetadata {\n pub fn new(note_nonce: Field) -> Self {\n Self { note_nonce }\n }\n\n pub fn note_nonce(self) -> Field {\n self.note_nonce\n }\n}\n" + }, + "148": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/note/utils.nr", + "source": "use crate::{\n context::PrivateContext,\n note::{note_interface::NoteHash, retrieved_note::RetrievedNote},\n};\n\nuse dep::protocol_types::hash::{\n compute_siloed_note_hash, compute_siloed_nullifier, compute_unique_note_hash,\n};\n\n/// Returns the note hash that must be used to issue a private kernel read request for a note.\npub fn compute_note_hash_for_read_request(\n retrieved_note: RetrievedNote,\n storage_slot: Field,\n) -> Field\nwhere\n Note: NoteHash,\n{\n let note_hash = retrieved_note.note.compute_note_hash(storage_slot);\n\n if retrieved_note.metadata.is_settled() {\n // Settled notes are read by siloing with contract address and nonce (resulting in the final unique note hash,\n // which is already in the note hash tree).\n let siloed_note_hash = compute_siloed_note_hash(retrieved_note.contract_address, note_hash);\n compute_unique_note_hash(\n retrieved_note.metadata.to_settled().note_nonce(),\n siloed_note_hash,\n )\n } else {\n // Pending notes (both same phase and previous phase ones) re read by their non-siloed hash (not even by\n // contract address), which is what is stored in the new note hashes array (at the position hinted by note hash\n // counter).\n note_hash\n }\n}\n\n/// Returns the note hash that must be used to compute a note's nullifier when calling `NoteHash::compute_nullifier` or\n/// `NoteHash::compute_nullifier_unconstrained`.\npub fn compute_note_hash_for_nullify(\n retrieved_note: RetrievedNote,\n storage_slot: Field,\n) -> Field\nwhere\n Note: NoteHash,\n{\n compute_note_hash_for_nullify_from_read_request(\n retrieved_note,\n compute_note_hash_for_read_request(retrieved_note, storage_slot),\n )\n}\n\n/// Same as `compute_note_hash_for_nullify`, except it takes the note hash used in a read request (i.e. what\n/// `compute_note_hash_for_read_request` would return). This is useful in scenarios where that hash has already been\n/// computed to reduce constraints by reusing this value.\npub fn compute_note_hash_for_nullify_from_read_request(\n retrieved_note: RetrievedNote,\n note_hash_for_read_request: Field,\n) -> Field {\n // There is just one instance in which the note hash for nullification does not match the note hash used for a read\n // request, which is when dealing with pending previous phase notes. These had their existence proven using their\n // non-siloed note hash along with the note hash counter (like all pending notes), but since they will be\n // unconditionally inserted in the note hash tree (since they cannot be squashed) they must be nullified using the\n // *unique* note hash.\n // If we didn't, it'd be possible to emit a second different nullifier for the same note in a follow up transaction,\n // once the note is settled, resulting in a double spend.\n\n if retrieved_note.metadata.is_pending_previous_phase() {\n let siloed_note_hash =\n compute_siloed_note_hash(retrieved_note.contract_address, note_hash_for_read_request);\n let note_nonce = retrieved_note.metadata.to_pending_previous_phase().note_nonce();\n\n compute_unique_note_hash(note_nonce, siloed_note_hash)\n } else {\n note_hash_for_read_request\n }\n}\n\n/// Computes a note's siloed nullifier, i.e. the one that will be inserted into the nullifier tree.\npub fn compute_siloed_note_nullifier(\n retrieved_note: RetrievedNote,\n storage_slot: Field,\n context: &mut PrivateContext,\n) -> Field\nwhere\n Note: NoteHash,\n{\n let note_hash_for_nullify = compute_note_hash_for_nullify(retrieved_note, storage_slot);\n let inner_nullifier = retrieved_note.note.compute_nullifier(context, note_hash_for_nullify);\n\n compute_siloed_nullifier(retrieved_note.contract_address, inner_nullifier)\n}\n" + }, + "153": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/capsules.nr", + "source": "use protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}};\n\n/// Stores arbitrary information in a per-contract non-volatile database, which can later be retrieved with `load`. If\n/// data was already stored at this slot, it is overwritten.\npub unconstrained fn store(contract_address: AztecAddress, slot: Field, value: T)\nwhere\n T: Serialize,\n{\n let serialized = value.serialize();\n store_oracle(contract_address, slot, serialized);\n}\n\n/// Returns data previously stored via `storeCapsule` in the per-contract non-volatile database. Returns Option::none() if\n/// nothing was stored at the given slot.\npub unconstrained fn load(contract_address: AztecAddress, slot: Field) -> Option\nwhere\n T: Deserialize,\n{\n let serialized_option = load_oracle(contract_address, slot, ::N);\n serialized_option.map(|arr| Deserialize::deserialize(arr))\n}\n\n/// Deletes data in the per-contract non-volatile database. Does nothing if no data was present.\npub unconstrained fn delete(contract_address: AztecAddress, slot: Field) {\n delete_oracle(contract_address, slot);\n}\n\n/// Copies a number of contiguous entries in the per-contract non-volatile database. This allows for efficient data\n/// structures by avoiding repeated calls to `loadCapsule` and `storeCapsule`.\n/// Supports overlapping source and destination regions (which will result in the overlapped source values being\n/// overwritten). All copied slots must exist in the database (i.e. have been stored and not deleted)\npub unconstrained fn copy(\n contract_address: AztecAddress,\n src_slot: Field,\n dst_slot: Field,\n num_entries: u32,\n) {\n copy_oracle(contract_address, src_slot, dst_slot, num_entries);\n}\n\n#[oracle(utilityStoreCapsule)]\nunconstrained fn store_oracle(\n contract_address: AztecAddress,\n slot: Field,\n values: [Field; N],\n) {}\n\n/// We need to pass in `array_len` (the value of N) as a parameter to tell the oracle how many fields the response must\n/// have.\n///\n/// Note that the oracle returns an Option<[Field; N]> because we cannot return an Option directly. That would\n/// require for the oracle resolver to know the shape of T (e.g. if T were a struct of 3 u32 values then the expected\n/// response shape would be 3 single items, whereas it were a struct containing `u32, [Field;10], u32` then the expected\n/// shape would be single, array, single.). Instead, we return the serialization and deserialize in Noir.\n#[oracle(utilityLoadCapsule)]\nunconstrained fn load_oracle(\n contract_address: AztecAddress,\n slot: Field,\n array_len: u32,\n) -> Option<[Field; N]> {}\n\n#[oracle(utilityDeleteCapsule)]\nunconstrained fn delete_oracle(contract_address: AztecAddress, slot: Field) {}\n\n#[oracle(utilityCopyCapsule)]\nunconstrained fn copy_oracle(\n contract_address: AztecAddress,\n src_slot: Field,\n dst_slot: Field,\n num_entries: u32,\n) {}\n\nmod test {\n // These tests are sort of redundant since we already test the oracle implementation directly in TypeScript, but\n // they are cheap regardless and help ensure both that the TXE implementation works accordingly and that the Noir\n // oracles are hooked up correctly.\n\n use crate::{\n oracle::capsules::{copy, delete, load, store},\n test::{helpers::test_environment::TestEnvironment, mocks::mock_struct::MockStruct},\n };\n use protocol_types::{address::AztecAddress, traits::{FromField, ToField}};\n\n global SLOT: Field = 1;\n\n #[test]\n unconstrained fn stores_and_loads() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value);\n\n assert_eq(load(contract_address, SLOT).unwrap(), value);\n });\n }\n\n #[test]\n unconstrained fn store_overwrites() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value);\n\n let new_value = MockStruct::new(7, 8);\n store(contract_address, SLOT, new_value);\n\n assert_eq(load(contract_address, SLOT).unwrap(), new_value);\n });\n }\n\n #[test]\n unconstrained fn loads_empty_slot() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let loaded_value: Option = load(contract_address, SLOT);\n assert_eq(loaded_value, Option::none());\n });\n }\n\n #[test]\n unconstrained fn deletes_stored_value() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value);\n delete(contract_address, SLOT);\n\n let loaded_value: Option = load(contract_address, SLOT);\n assert_eq(loaded_value, Option::none());\n });\n }\n\n #[test]\n unconstrained fn deletes_empty_slot() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n delete(contract_address, SLOT);\n let loaded_value: Option = load(contract_address, SLOT);\n assert_eq(loaded_value, Option::none());\n });\n }\n\n #[test]\n unconstrained fn copies_non_overlapping_values() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let src = 5;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0]);\n store(contract_address, src + 1, values[1]);\n store(contract_address, src + 2, values[2]);\n\n let dst = 10;\n copy(contract_address, src, dst, 3);\n\n assert_eq(load(contract_address, dst).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2).unwrap(), values[2]);\n });\n }\n\n #[test]\n unconstrained fn copies_overlapping_values_with_src_ahead() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let src = 1;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0]);\n store(contract_address, src + 1, values[1]);\n store(contract_address, src + 2, values[2]);\n\n let dst = 2;\n copy(contract_address, src, dst, 3);\n\n assert_eq(load(contract_address, dst).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2).unwrap(), values[2]);\n\n // src[1] and src[2] should have been overwritten since they are also dst[0] and dst[1]\n assert_eq(load(contract_address, src).unwrap(), values[0]); // src[0] (unchanged)\n assert_eq(load(contract_address, src + 1).unwrap(), values[0]); // dst[0]\n assert_eq(load(contract_address, src + 2).unwrap(), values[1]); // dst[1]\n });\n }\n\n #[test]\n unconstrained fn copies_overlapping_values_with_dst_ahead() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let src = 2;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0]);\n store(contract_address, src + 1, values[1]);\n store(contract_address, src + 2, values[2]);\n\n let dst = 1;\n copy(contract_address, src, dst, 3);\n\n assert_eq(load(contract_address, dst).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2).unwrap(), values[2]);\n\n // src[0] and src[1] should have been overwritten since they are also dst[1] and dst[2]\n assert_eq(load(contract_address, src).unwrap(), values[1]); // dst[1]\n assert_eq(load(contract_address, src + 1).unwrap(), values[2]); // dst[2]\n assert_eq(load(contract_address, src + 2).unwrap(), values[2]); // src[2] (unchanged)\n });\n }\n\n #[test(should_fail_with = \"copy empty slot\")]\n unconstrained fn cannot_copy_empty_values() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n copy(contract_address, SLOT, SLOT, 1);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_store_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n let value = MockStruct::new(5, 6);\n store(other_contract_address, SLOT, value);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_load_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n let _: Option = load(other_contract_address, SLOT);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_delete_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n delete(other_contract_address, SLOT);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_copy_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n copy(other_contract_address, SLOT, SLOT, 0);\n });\n }\n}\n" + }, + "154": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr", + "source": "use dep::protocol_types::address::AztecAddress;\n\n#[oracle(privateNotifyEnqueuedPublicFunctionCall)]\nunconstrained fn notify_enqueued_public_function_call_oracle(\n _contract_address: AztecAddress,\n _calldata_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n) {}\n\nunconstrained fn notify_enqueued_public_function_call_wrapper(\n contract_address: AztecAddress,\n calldata_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n) {\n notify_enqueued_public_function_call_oracle(\n contract_address,\n calldata_hash,\n side_effect_counter,\n is_static_call,\n )\n}\n\npub fn notify_enqueued_public_function_call(\n contract_address: AztecAddress,\n calldata_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n) {\n // Safety: Notifies the simulator that a public call has been enqueued, allowing it to prepare hints for the AVM to process this call.\n unsafe {\n notify_enqueued_public_function_call_wrapper(\n contract_address,\n calldata_hash,\n side_effect_counter,\n is_static_call,\n )\n }\n}\n\n#[oracle(privateNotifySetPublicTeardownFunctionCall)]\nunconstrained fn notify_set_public_teardown_function_call_oracle(\n _contract_address: AztecAddress,\n _calldata_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n) {}\n\nunconstrained fn notify_set_public_teardown_function_call_wrapper(\n contract_address: AztecAddress,\n calldata_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n) {\n notify_set_public_teardown_function_call_oracle(\n contract_address,\n calldata_hash,\n side_effect_counter,\n is_static_call,\n )\n}\n\npub fn notify_set_public_teardown_function_call(\n contract_address: AztecAddress,\n calldata_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n) {\n // Safety: Notifies the simulator that a teardown call has been set, allowing it to prepare hints for the AVM to process this call.\n unsafe {\n notify_set_public_teardown_function_call_wrapper(\n contract_address,\n calldata_hash,\n side_effect_counter,\n is_static_call,\n )\n }\n}\n\npub fn notify_set_min_revertible_side_effect_counter(counter: u32) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe { notify_set_min_revertible_side_effect_counter_oracle_wrapper(counter) };\n}\n\npub unconstrained fn notify_set_min_revertible_side_effect_counter_oracle_wrapper(counter: u32) {\n notify_set_min_revertible_side_effect_counter_oracle(counter);\n}\n\n#[oracle(privateNotifySetMinRevertibleSideEffectCounter)]\nunconstrained fn notify_set_min_revertible_side_effect_counter_oracle(_counter: u32) {}\n" + }, + "155": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/execution.nr", + "source": "use dep::protocol_types::address::AztecAddress;\n\n#[oracle(utilityGetContractAddress)]\nunconstrained fn get_contract_address_oracle() -> AztecAddress {}\n\n#[oracle(utilityGetBlockNumber)]\nunconstrained fn get_block_number_oracle() -> u32 {}\n\n#[oracle(utilityGetTimestamp)]\nunconstrained fn get_timestamp_oracle() -> u64 {}\n\n#[oracle(utilityGetChainId)]\nunconstrained fn get_chain_id_oracle() -> Field {}\n\n#[oracle(utilityGetVersion)]\nunconstrained fn get_version_oracle() -> Field {}\n\npub unconstrained fn get_contract_address() -> AztecAddress {\n get_contract_address_oracle()\n}\n\npub unconstrained fn get_block_number() -> u32 {\n get_block_number_oracle()\n}\n\npub unconstrained fn get_timestamp() -> u64 {\n get_timestamp_oracle()\n}\n\npub unconstrained fn get_chain_id() -> Field {\n get_chain_id_oracle()\n}\n\npub unconstrained fn get_version() -> Field {\n get_version_oracle()\n}\n" + }, + "156": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/execution_cache.nr", + "source": "/// Stores values represented as slice in execution cache to be later obtained by its hash.\npub fn store(values: [Field], hash: Field) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call. When loading the values, however, the caller must check that the values are indeed the preimage.\n unsafe { store_in_execution_cache_oracle_wrapper(values, hash) };\n}\n\nunconstrained fn store_in_execution_cache_oracle_wrapper(values: [Field], hash: Field) {\n store_in_execution_cache_oracle(values, hash);\n}\n\npub unconstrained fn load(hash: Field) -> [Field; N] {\n load_from_execution_cache_oracle(hash)\n}\n\n#[oracle(privateStoreInExecutionCache)]\nunconstrained fn store_in_execution_cache_oracle(_values: [Field], _hash: Field) {}\n\n#[oracle(privateLoadFromExecutionCache)]\nunconstrained fn load_from_execution_cache_oracle(_hash: Field) -> [Field; N] {}\n" + }, + "157": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr", + "source": "use protocol_types::{\n address::AztecAddress, contract_class_id::ContractClassId, contract_instance::ContractInstance,\n traits::FromField,\n};\n\n// NOTE: this is for use in private only\n#[oracle(utilityGetContractInstance)]\nunconstrained fn get_contract_instance_oracle(_address: AztecAddress) -> ContractInstance {}\n\n// NOTE: this is for use in private only\nunconstrained fn get_contract_instance_internal(address: AztecAddress) -> ContractInstance {\n get_contract_instance_oracle(address)\n}\n\n// NOTE: this is for use in private only\npub fn get_contract_instance(address: AztecAddress) -> ContractInstance {\n // Safety: The to_address function combines all values in the instance object to produce an address,\n // so by checking that we get the expected address we validate the entire struct.\n let instance = unsafe { get_contract_instance_internal(address) };\n assert_eq(instance.to_address(), address);\n\n instance\n}\n\nstruct GetContractInstanceResult {\n exists: bool,\n member: Field,\n}\n\n// These oracles each return a ContractInstance member\n// plus a boolean indicating whether the instance was found.\n#[oracle(avmOpcodeGetContractInstanceDeployer)]\nunconstrained fn get_contract_instance_deployer_oracle_avm(\n _address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {}\n#[oracle(avmOpcodeGetContractInstanceClassId)]\nunconstrained fn get_contract_instance_class_id_oracle_avm(\n _address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {}\n#[oracle(avmOpcodeGetContractInstanceInitializationHash)]\nunconstrained fn get_contract_instance_initialization_hash_oracle_avm(\n _address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {}\n\nunconstrained fn get_contract_instance_deployer_internal_avm(\n address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {\n get_contract_instance_deployer_oracle_avm(address)\n}\nunconstrained fn get_contract_instance_class_id_internal_avm(\n address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {\n get_contract_instance_class_id_oracle_avm(address)\n}\nunconstrained fn get_contract_instance_initialization_hash_internal_avm(\n address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {\n get_contract_instance_initialization_hash_oracle_avm(address)\n}\n\npub fn get_contract_instance_deployer_avm(address: AztecAddress) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let GetContractInstanceResult { exists, member } =\n unsafe { get_contract_instance_deployer_internal_avm(address)[0] };\n if exists {\n Option::some(AztecAddress::from_field(member))\n } else {\n Option::none()\n }\n}\npub fn get_contract_instance_class_id_avm(address: AztecAddress) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let GetContractInstanceResult { exists, member } =\n unsafe { get_contract_instance_class_id_internal_avm(address)[0] };\n if exists {\n Option::some(ContractClassId::from_field(member))\n } else {\n Option::none()\n }\n}\npub fn get_contract_instance_initialization_hash_avm(address: AztecAddress) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let GetContractInstanceResult { exists, member } =\n unsafe { get_contract_instance_initialization_hash_internal_avm(address)[0] };\n if exists {\n Option::some(member)\n } else {\n Option::none()\n }\n}\n" + }, + "16": { + "path": "std/embedded_curve_ops.nr", + "source": "use crate::cmp::Eq;\nuse crate::hash::Hash;\nuse crate::ops::arith::{Add, Neg, Sub};\n\n/// A point on the embedded elliptic curve\n/// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field.\n/// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false.\npub struct EmbeddedCurvePoint {\n pub x: Field,\n pub y: Field,\n pub is_infinite: bool,\n}\n\nimpl EmbeddedCurvePoint {\n /// Elliptic curve point doubling operation\n /// returns the doubled point of a point P, i.e P+P\n pub fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n /// Returns the null element of the curve; 'the point at infinity'\n pub fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n\n /// Returns the curve's generator point.\n pub fn generator() -> EmbeddedCurvePoint {\n // Generator point for the grumpkin curve (y^2 = x^3 - 17)\n EmbeddedCurvePoint {\n x: 1,\n y: 17631683881184975370165255887551781615748388533673675138860, // sqrt(-16)\n is_infinite: false,\n }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n /// Points subtraction operation, using addition and negation\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n /// Negates a point P, i.e returns -P, by negating the y coordinate.\n /// If the point is at infinity, then the result is also at infinity.\n fn neg(self) -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: self.x, y: -self.y, is_infinite: self.is_infinite }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n /// Checks whether two points are equal\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite)\n | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\nimpl Hash for EmbeddedCurvePoint {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n if self.is_infinite {\n self.is_infinite.hash(state);\n } else {\n self.x.hash(state);\n self.y.hash(state);\n }\n }\n}\n\n/// Scalar for the embedded curve represented as low and high limbs\n/// By definition, the scalar field of the embedded curve is base field of the proving system curve.\n/// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs.\npub struct EmbeddedCurveScalar {\n pub lo: Field,\n pub hi: Field,\n}\n\nimpl EmbeddedCurveScalar {\n pub fn new(lo: Field, hi: Field) -> Self {\n EmbeddedCurveScalar { lo, hi }\n }\n\n #[field(bn254)]\n pub fn from_field(scalar: Field) -> EmbeddedCurveScalar {\n let (a, b) = crate::field::bn254::decompose(scalar);\n EmbeddedCurveScalar { lo: a, hi: b }\n }\n\n //Bytes to scalar: take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value\n #[field(bn254)]\n pub(crate) fn from_bytes(bytes: [u8; 64], offset: u32) -> EmbeddedCurveScalar {\n let mut v = 1;\n let mut lo = 0 as Field;\n let mut hi = 0 as Field;\n for i in 0..16 {\n lo = lo + (bytes[offset + 31 - i] as Field) * v;\n hi = hi + (bytes[offset + 15 - i] as Field) * v;\n v = v * 256;\n }\n let sig_s = crate::embedded_curve_ops::EmbeddedCurveScalar { lo, hi };\n sig_s\n }\n}\n\nimpl Eq for EmbeddedCurveScalar {\n fn eq(self, other: Self) -> bool {\n (other.hi == self.hi) & (other.lo == self.lo)\n }\n}\n\nimpl Hash for EmbeddedCurveScalar {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n self.hi.hash(state);\n self.lo.hash(state);\n }\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// docs:start:multi_scalar_mul\npub fn multi_scalar_mul(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> EmbeddedCurvePoint\n// docs:end:multi_scalar_mul\n{\n multi_scalar_mul_array_return(points, scalars, true)[0]\n}\n\n#[foreign(multi_scalar_mul)]\npub(crate) fn multi_scalar_mul_array_return(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n predicate: bool,\n) -> [EmbeddedCurvePoint; 1] {}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint\n// docs:end:fixed_base_scalar_mul\n{\n multi_scalar_mul([EmbeddedCurvePoint::generator()], [scalar])\n}\n\n/// This function only assumes that the points are on the curve\n/// It handles corner cases around the infinity point causing some overhead compared to embedded_curve_add_not_nul and embedded_curve_add_unsafe\n// docs:start:embedded_curve_add\npub fn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n // docs:end:embedded_curve_add\n if crate::runtime::is_unconstrained() {\n // `embedded_curve_add_unsafe` requires the inputs not to be the infinity point, so we check it here.\n // This is because `embedded_curve_add_unsafe` uses the `embedded_curve_add` opcode.\n // For efficiency, the backend does not check the inputs for the infinity point, but it assumes that they are not the infinity point\n // so that it can apply the ec addition formula directly.\n if point1.is_infinite {\n point2\n } else if point2.is_infinite {\n point1\n } else {\n embedded_curve_add_unsafe(point1, point2)\n }\n } else {\n // In a constrained context, we also need to check the inputs are not the infinity point because we also use `embedded_curve_add_unsafe`\n // However we also need to identify the case where the two inputs are the same, because then\n // the addition formula does not work and we need to use the doubling formula instead.\n // In unconstrained context, we can check directly if the input values are the same when solving the opcode, so it is not an issue.\n\n // x_coordinates_match is true if both abscissae are the same\n let x_coordinates_match = point1.x == point2.x;\n // y_coordinates_match is true if both ordinates are the same\n let y_coordinates_match = point1.y == point2.y;\n // double_predicate is true if both abscissae and ordinates are the same\n let double_predicate = (x_coordinates_match & y_coordinates_match);\n // If the abscissae are the same, but not the ordinates, then one point is the opposite of the other\n let infinity_predicate = (x_coordinates_match & !y_coordinates_match);\n let point1_1 = EmbeddedCurvePoint {\n x: point1.x + (x_coordinates_match as Field),\n y: point1.y,\n is_infinite: false,\n };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n // point1_1 is guaranteed to have a different abscissa than point2:\n // - if x_coordinates_match is 0, that means point1.x != point2.x, and point1_1.x = point1.x + 0\n // - if x_coordinates_match is 1, that means point1.x = point2.x, but point1_1.x = point1.x + 1 in this case\n // Because the abscissa is different, the addition formula is guaranteed to succeed, so we can safely use `embedded_curve_add_unsafe`\n // Note that this computation may be garbage: if x_coordinates_match is 1, or if one of the input is the point at infinity.\n let mut result = embedded_curve_add_unsafe(point1_1, point2_1);\n\n // `embedded_curve_add_unsafe` is doing a doubling if the input is the same variable, because in this case it is guaranteed (at 'compile time') that the input is the same.\n let double = embedded_curve_add_unsafe(point1, point1);\n // `embedded_curve_add_unsafe` would not perform doubling, even if the inputs point1 and point2 are the same, because it cannot know this without adding some logic (and some constraints)\n // However we did this logic when we computed `double_predicate`, so we set the result to 2*point1 if point1 and point2 are the same\n result = if double_predicate { double } else { result };\n\n // Same logic as above for unconstrained context, we set the proper result when one of the inputs is the infinity point\n if point1.is_infinite {\n result = point2;\n }\n if point2.is_infinite {\n result = point1;\n }\n\n // Finally, we set the is_infinity flag of the result:\n // Opposite points should sum into the infinity point, however, if one of them is point at infinity, their coordinates are not meaningful\n // so we should not use the fact that the inputs are opposite in this case:\n let mut result_is_infinity =\n infinity_predicate & (!point1.is_infinite & !point2.is_infinite);\n // However, if both of them are at infinity, then the result is also at infinity\n result.is_infinite = result_is_infinity | (point1.is_infinite & point2.is_infinite);\n result\n }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(\n _point1: EmbeddedCurvePoint,\n _point2: EmbeddedCurvePoint,\n _predicate: bool,\n) -> [EmbeddedCurvePoint; 1] {}\n\n/// This function assumes that:\n/// The points are on the curve, and\n/// The points don't share an x-coordinate, and\n/// Neither point is the infinity point.\n/// If it is used with correct input, the function ensures the correct non-zero result is returned.\n/// Except for points on the curve, the other assumptions are checked by the function. It will cause assertion failure if they are not respected.\npub fn embedded_curve_add_not_nul(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n assert(point1.x != point2.x);\n assert(!point1.is_infinite);\n assert(!point2.is_infinite);\n // Ensure is_infinite is comptime\n let point1_1 = EmbeddedCurvePoint { x: point1.x, y: point1.y, is_infinite: false };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n embedded_curve_add_unsafe(point1_1, point2_1)\n}\n\n/// Unsafe ec addition\n/// If the inputs are the same, it will perform a doubling, but only if point1 and point2 are the same variable.\n/// If they have the same value but are different variables, the result will be incorrect because in this case\n/// it assumes (but does not check) that the points' x-coordinates are not equal.\n/// It also assumes neither point is the infinity point.\npub fn embedded_curve_add_unsafe(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n embedded_curve_add_array_return(point1, point2, true)[0]\n}\n" + }, + "162": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr", + "source": "use protocol_types::abis::validation_requests::KeyValidationRequest;\n\n#[oracle(utilityGetKeyValidationRequest)]\nunconstrained fn get_key_validation_request_oracle(\n _pk_m_hash: Field,\n _key_index: Field,\n) -> KeyValidationRequest {}\n\npub unconstrained fn get_key_validation_request(\n pk_m_hash: Field,\n key_index: Field,\n) -> KeyValidationRequest {\n get_key_validation_request_oracle(pk_m_hash, key_index)\n}\n" + }, + "163": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/keys.nr", + "source": "use dep::protocol_types::{\n address::{AztecAddress, PartialAddress},\n point::Point,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, TpkM},\n};\n\n#[oracle(utilityGetPublicKeysAndPartialAddress)]\nunconstrained fn get_public_keys_and_partial_address_oracle(_address: AztecAddress) -> [Field; 13] {}\n\npub unconstrained fn get_public_keys_and_partial_address(\n address: AztecAddress,\n) -> (PublicKeys, PartialAddress) {\n let result = get_public_keys_and_partial_address_oracle(address);\n\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: result[0], y: result[1], is_infinite: result[2] != 0 } },\n ivpk_m: IvpkM { inner: Point { x: result[3], y: result[4], is_infinite: result[5] != 0 } },\n ovpk_m: OvpkM { inner: Point { x: result[6], y: result[7], is_infinite: result[8] != 0 } },\n tpk_m: TpkM { inner: Point { x: result[9], y: result[10], is_infinite: result[11] != 0 } },\n };\n\n let partial_address = PartialAddress::from_field(result[12]);\n\n (keys, partial_address)\n}\n" + }, + "165": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/message_processing.nr", + "source": "use protocol_types::address::AztecAddress;\n\n/// Finds new private logs that may have been sent to all registered accounts in PXE in the current contract and makes\n/// them available for later processing in Noir by storing them in a capsule array.\npub unconstrained fn fetch_tagged_logs(pending_tagged_log_array_base_slot: Field) {\n fetch_tagged_logs_oracle(pending_tagged_log_array_base_slot);\n}\n\n#[oracle(utilityFetchTaggedLogs)]\nunconstrained fn fetch_tagged_logs_oracle(pending_tagged_log_array_base_slot: Field) {}\n\n// This must be a single oracle and not one for notes and one for events because the entire point is to validate\n// all notes and events in one go, minimizing node round-trips.\npub(crate) unconstrained fn validate_enqueued_notes_and_events(\n contract_address: AztecAddress,\n note_validation_requests_array_base_slot: Field,\n event_validation_requests_array_base_slot: Field,\n) {\n validate_enqueued_notes_and_events_oracle(\n contract_address,\n note_validation_requests_array_base_slot,\n event_validation_requests_array_base_slot,\n );\n}\n\n#[oracle(utilityValidateEnqueuedNotesAndEvents)]\nunconstrained fn validate_enqueued_notes_and_events_oracle(\n contract_address: AztecAddress,\n note_validation_requests_array_base_slot: Field,\n event_validation_requests_array_base_slot: Field,\n) {}\n\npub(crate) unconstrained fn bulk_retrieve_logs(\n contract_address: AztecAddress,\n log_retrieval_requests_array_base_slot: Field,\n log_retrieval_responses_array_base_slot: Field,\n) {\n bulk_retrieve_logs_oracle(\n contract_address,\n log_retrieval_requests_array_base_slot,\n log_retrieval_responses_array_base_slot,\n );\n}\n\n#[oracle(utilityBulkRetrieveLogs)]\nunconstrained fn bulk_retrieve_logs_oracle(\n contract_address: AztecAddress,\n log_retrieval_requests_array_base_slot: Field,\n log_retrieval_responses_array_base_slot: Field,\n) {}\n" + }, + "167": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/notes.nr", + "source": "use crate::note::{note_interface::NoteType, retrieved_note::RetrievedNote};\n\nuse dep::protocol_types::{\n address::AztecAddress, indexed_tagging_secret::IndexedTaggingSecret, traits::Packable,\n};\n\n/// Notifies the simulator that a note has been created, so that it can be returned in future read requests in the same\n/// transaction. This note should only be added to the non-volatile database if found in an actual block.\npub fn notify_created_note(\n storage_slot: Field,\n note_type_id: Field,\n packed_note: [Field; N],\n note_hash: Field,\n counter: u32,\n) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe {\n notify_created_note_oracle_wrapper(\n storage_slot,\n note_type_id,\n packed_note,\n note_hash,\n counter,\n )\n };\n}\n\n/// Notifies the simulator that a note has been nullified, so that it is no longer returned in future read requests in\n/// the same transaction. This note should only be removed to the non-volatile database if its nullifier is found in an\n/// actual block.\npub fn notify_nullified_note(nullifier: Field, note_hash: Field, counter: u32) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to\n // call.\n unsafe { notify_nullified_note_oracle_wrapper(nullifier, note_hash, counter) };\n}\n\n/// Notifies the simulator that a non-note nullifier has been created, so that it can be used for note nonces.\npub fn notify_created_nullifier(nullifier: Field) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to\n // call.\n unsafe { notify_created_nullifier_oracle_wrapper(nullifier) };\n}\n\nunconstrained fn notify_created_note_oracle_wrapper(\n storage_slot: Field,\n note_type_id: Field,\n packed_note: [Field; N],\n note_hash: Field,\n counter: u32,\n) {\n notify_created_note_oracle(storage_slot, note_type_id, packed_note, note_hash, counter);\n}\n\n#[oracle(privateNotifyCreatedNote)]\nunconstrained fn notify_created_note_oracle(\n _storage_slot: Field,\n _note_type_id: Field,\n _packed_note: [Field; N],\n _note_hash: Field,\n _counter: u32,\n) {}\n\nunconstrained fn notify_nullified_note_oracle_wrapper(\n nullifier: Field,\n note_hash: Field,\n counter: u32,\n) {\n notify_nullified_note_oracle(nullifier, note_hash, counter);\n}\n\n#[oracle(privateNotifyNullifiedNote)]\nunconstrained fn notify_nullified_note_oracle(_nullifier: Field, _note_hash: Field, _counter: u32) {}\n\nunconstrained fn notify_created_nullifier_oracle_wrapper(nullifier: Field) {\n notify_created_nullifier_oracle(nullifier);\n}\n\n#[oracle(privateNotifyCreatedNullifier)]\nunconstrained fn notify_created_nullifier_oracle(_nullifier: Field) {}\n\n#[oracle(utilityGetNotes)]\nunconstrained fn get_notes_oracle(\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 // This is always set to MAX_NOTES. We need to pass it to TS in order to correctly construct the BoundedVec\n _max_notes: u32,\n // This is always set to as Packable>::N. We need to pass it to TS in order to be able to\n // correctly construct the BoundedVec there.\n _packed_retrieved_note_length: u32,\n) -> BoundedVec<[Field; as Packable>::N], MaxNotes>\nwhere\n // TODO(https://github.com/noir-lang/noir/issues/9399): `Note: Packable` should work here.\n RetrievedNote: Packable,\n{}\n\npub unconstrained 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) -> [Option>; MaxNotes]\nwhere\n Note: NoteType + Packable,\n{\n let packed_retrieved_notes: BoundedVec<[Field; as Packable>::N], MaxNotes>\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 MaxNotes,\n as Packable>::N,\n );\n\n let mut notes = BoundedVec::<_, MaxNotes>::new();\n for i in 0..packed_retrieved_notes.len() {\n let retrieved_note = RetrievedNote::unpack(packed_retrieved_notes.get(i));\n notes.push(retrieved_note);\n }\n\n // At last we convert the bounded vector to an array of options. We do this because that is what the filter\n // function needs to have on the output and we've decided to have the same type on the input and output of\n // the filter and preprocessor functions.\n //\n // We have decided to have the same type on the input and output of the filter and preprocessor functions because\n // it allows us to chain multiple filters and preprocessors together.\n //\n // So why do we want the array of options on the output of the filter function?\n //\n // Filter returns an array of options rather than a BoundedVec for performance reasons. Using an array of options\n // allows setting values at known indices in the output array which is much more efficient than pushing to a\n // BoundedVec where the write position depends on previous iterations. The array can then be efficiently converted\n // to a BoundedVec using utils/array/collapse.nr::collapse function from Aztec.nr. This avoids expensive dynamic\n // memory access patterns that would be required when building up a BoundedVec incrementally. For preprocessor\n // functions we could use BoundedVec return value as there the optimization does not matter since it is applied in\n // an unconstrained context. We, however, use the same return value type to be able to use the same function as\n // both a preprocessor and a filter.\n let mut notes_array = [Option::none(); MaxNotes];\n for i in 0..notes.len() {\n if i < notes.len() {\n notes_array[i] = Option::some(notes.get_unchecked(i));\n }\n }\n\n notes_array\n}\n\n/// Returns true if the nullifier exists. Note that a `true` value can be constrained by proving existence of the\n/// nullifier, but a `false` value should not be relied upon since other transactions may emit this nullifier before the\n/// current transaction is included in a block. While this might seem of little use at first, certain design patterns\n/// benefit from this abstraction (see e.g. `PrivateMutable`).\npub unconstrained fn check_nullifier_exists(inner_nullifier: Field) -> bool {\n check_nullifier_exists_oracle(inner_nullifier)\n}\n\n#[oracle(utilityCheckNullifierExists)]\nunconstrained fn check_nullifier_exists_oracle(_inner_nullifier: Field) -> bool {}\n\n// TODO: Oracles below are generic private log oracles and are not specific to notes. Move them somewhere else.\n\n/// Returns the derived app tagging secret ready to be included in a log for a given sender and recipient pair,\n/// siloed for the current contract address.\npub unconstrained fn get_app_tag_as_sender(sender: AztecAddress, recipient: AztecAddress) -> Field {\n get_indexed_tagging_secret_as_sender_oracle(sender, recipient).compute_tag(recipient)\n}\n\n#[oracle(utilityGetIndexedTaggingSecretAsSender)]\nunconstrained fn get_indexed_tagging_secret_as_sender_oracle(\n _sender: AztecAddress,\n _recipient: AztecAddress,\n) -> IndexedTaggingSecret {}\n\n/// Notifies the simulator that a tag has been used in a note, and to therefore increment the associated index so that\n/// future notes get a different tag and can be discovered by the recipient.\n/// This change should only be persisted in a non-volatile database if the tagged log is found in an actual block -\n/// otherwise e.g. a reverting transaction can cause the sender to accidentally skip indices and later produce notes\n/// that are not found by the recipient.\npub fn increment_app_tagging_secret_index_as_sender(sender: AztecAddress, recipient: AztecAddress) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe {\n increment_app_tagging_secret_index_as_sender_wrapper(sender, recipient);\n }\n}\n\nunconstrained fn increment_app_tagging_secret_index_as_sender_wrapper(\n sender: AztecAddress,\n recipient: AztecAddress,\n) {\n increment_app_tagging_secret_index_as_sender_oracle(sender, recipient);\n}\n\n#[oracle(privateIncrementAppTaggingSecretIndexAsSender)]\nunconstrained fn increment_app_tagging_secret_index_as_sender_oracle(\n _sender: AztecAddress,\n _recipient: AztecAddress,\n) {}\n\n/// Gets the sender for tags.\n///\n/// This unconstrained value is used as the sender when computing an unconstrained shared secret\n/// for a tag in order to emit a log. Constrained tagging should not use this as there is no\n/// guarantee that the recipient knows about the sender, and hence about the shared secret.\n///\n/// The value persists through nested calls, meaning all calls down the stack will use the same\n/// 'senderForTags' value (unless it is replaced).\npub unconstrained fn get_sender_for_tags() -> Option {\n get_sender_for_tags_oracle()\n}\n\n#[oracle(privateGetSenderForTags)]\nunconstrained fn get_sender_for_tags_oracle() -> Option {}\n\n/// Sets the sender for tags.\n///\n/// This unconstrained value is used as the sender when computing an unconstrained shared secret\n/// for a tag in order to emit a log. Constrained tagging should not use this as there is no\n/// guarantee that the recipient knows about the sender, and hence about the shared secret.\n///\n/// Account contracts typically set this value before calling other contracts. The value persists\n/// through nested calls, meaning all calls down the stack will use the same 'senderForTags'\n/// value (unless it is replaced by another call to this setter).\npub unconstrained fn set_sender_for_tags(sender_for_tags: AztecAddress) {\n set_sender_for_tags_oracle(sender_for_tags);\n}\n\n#[oracle(privateSetSenderForTags)]\nunconstrained fn set_sender_for_tags_oracle(_sender_for_tags: AztecAddress) {}\n" + }, + "17": { + "path": "std/field/bn254.nr", + "source": "use crate::field::field_less_than;\nuse crate::runtime::is_unconstrained;\n\n// The low and high decomposition of the field modulus\nglobal PLO: Field = 53438638232309528389504892708671455233;\nglobal PHI: Field = 64323764613183177041862057485226039389;\n\npub(crate) global TWO_POW_128: Field = 0x100000000000000000000000000000000;\n\n// Decomposes a single field into two 16 byte fields.\nfn compute_decomposition(x: Field) -> (Field, Field) {\n // Here's we're taking advantage of truncating 128 bit limbs from the input field\n // and then subtracting them from the input such the field division is equivalent to integer division.\n let low = (x as u128) as Field;\n let high = (x - low) / TWO_POW_128;\n\n (low, high)\n}\n\npub(crate) unconstrained fn decompose_hint(x: Field) -> (Field, Field) {\n compute_decomposition(x)\n}\n\nunconstrained fn lte_hint(x: Field, y: Field) -> bool {\n if x == y {\n true\n } else {\n field_less_than(x, y)\n }\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 // Safety: borrow is enforced to be boolean due to its type.\n // if borrow is 0, it asserts that (alo > blo && ahi >= bhi)\n // if borrow is 1, it asserts that (alo <= blo && ahi > bhi)\n unsafe {\n let borrow = lte_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\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 // Safety: decomposition is properly checked below\n unsafe {\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}\n\npub fn assert_gt(a: Field, b: Field) {\n if is_unconstrained() {\n assert(\n // Safety: already unconstrained\n unsafe { field_less_than(b, a) },\n );\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 // Safety: unsafe in unconstrained\n unsafe {\n field_less_than(b, a)\n }\n } else if a == b {\n false\n } else {\n // Safety: Take a hint of the comparison and verify it\n unsafe {\n if field_less_than(a, b) {\n assert_gt(b, a);\n false\n } else {\n assert_gt(a, b);\n true\n }\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::{assert_gt, decompose, gt, lte_hint, PHI, PLO, TWO_POW_128};\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 unconstrained fn check_lte_hint() {\n assert(lte_hint(0, 1));\n assert(lte_hint(0, 0x100));\n assert(lte_hint(0x100, TWO_POW_128 - 1));\n assert(!lte_hint(0 - 1, 0));\n\n assert(lte_hint(0, 0));\n assert(lte_hint(0x100, 0x100));\n assert(lte_hint(0 - 1, 0 - 1));\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" + }, + "170": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/shared_secret.nr", + "source": "use protocol_types::{address::aztec_address::AztecAddress, point::Point};\n\n// TODO(#12656): return an app-siloed secret + document this\n#[oracle(utilityGetSharedSecret)]\nunconstrained fn get_shared_secret_oracle(address: AztecAddress, ephPk: Point) -> Point {}\n\n/// Returns an app-siloed shared secret between `address` and someone who knows the secret key behind an\n/// ephemeral public key `ephPk`. The app-siloing means that contracts cannot retrieve secrets that belong to\n/// other contracts, and therefore cannot e.g. decrypt their messages. This is an important security consideration\n/// given that both the `address` and `ephPk` are public information.\n///\n/// The shared secret `S` is computed as:\n/// `let S = (ivsk + h) * ephPk`\n/// where `ivsk + h` is the 'preaddress' i.e. the preimage of the address, also called the address secret.\n/// TODO(#12656): app-silo this secret\npub unconstrained fn get_shared_secret(address: AztecAddress, ephPk: Point) -> Point {\n get_shared_secret_oracle(address, ephPk)\n}\n" + }, + "172": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/storage.nr", + "source": "use dep::protocol_types::{address::AztecAddress, traits::{Packable, ToField}};\n\n#[oracle(utilityStorageRead)]\nunconstrained fn storage_read_oracle(\n address: Field,\n storage_slot: Field,\n block_number: u32,\n length: u32,\n) -> [Field; N] {}\n\npub unconstrained fn raw_storage_read(\n address: AztecAddress,\n storage_slot: Field,\n block_number: u32,\n) -> [Field; N] {\n storage_read_oracle(address.to_field(), storage_slot, block_number, N)\n}\n\npub unconstrained fn storage_read(\n address: AztecAddress,\n storage_slot: Field,\n block_number: u32,\n) -> T\nwhere\n T: Packable,\n{\n T::unpack(raw_storage_read(address, storage_slot, block_number))\n}\n\nmod tests {\n use crate::oracle::storage::{raw_storage_read, storage_read};\n use dep::protocol_types::{address::AztecAddress, traits::{FromField, Packable}};\n\n use crate::test::mocks::mock_struct::MockStruct;\n use std::test::OracleMock;\n\n global address: AztecAddress = AztecAddress::from_field(29);\n global slot: Field = 7;\n global block_number: u32 = 17;\n\n #[test]\n unconstrained fn test_raw_storage_read() {\n let written = MockStruct { a: 13, b: 42 };\n\n let _ = OracleMock::mock(\"utilityStorageRead\").returns(written.pack());\n\n let read: [Field; 2] = raw_storage_read(address, slot, block_number);\n assert_eq(read[0], 13);\n assert_eq(read[1], 42);\n }\n\n #[test]\n unconstrained fn test_storage_read() {\n let written = MockStruct { a: 13, b: 42 };\n\n let _ = OracleMock::mock(\"utilityStorageRead\").returns(written.pack());\n\n let read: MockStruct = storage_read(address, slot, block_number);\n assert_eq(read.a, 13);\n assert_eq(read.b, 42);\n }\n}\n" + }, + "173": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/version.nr", + "source": "/// The ORACLE_VERSION constant is used to check that the oracle interface is in sync between PXE and Aztec.nr. We need\n/// to version the oracle interface to ensure that developers get a reasonable error message if they use incompatible\n/// versions of Aztec.nr and PXE. The TypeScript counterpart is in `oracle_version.ts`.\n///\n/// @dev Whenever a contract function or Noir test is run, the `utilityAssertCompatibleOracleVersion` oracle is called and\n/// if the oracle version is incompatible an error is thrown.\npub global ORACLE_VERSION: Field = 1;\n\n/// Asserts that the version of the oracle is compatible with the version expected by the contract.\npub fn assert_compatible_oracle_version() {\n // Safety: This oracle call returns nothing: we only call it to check Aztec.nr and Oracle interface versions are\n // compatible. It is therefore always safe to call.\n unsafe {\n assert_compatible_oracle_version_wrapper();\n }\n}\n\nunconstrained fn assert_compatible_oracle_version_wrapper() {\n assert_compatible_oracle_version_oracle(ORACLE_VERSION);\n}\n\n#[oracle(utilityAssertCompatibleOracleVersion)]\nunconstrained fn assert_compatible_oracle_version_oracle(version: Field) {}\n\nmod test {\n use super::{assert_compatible_oracle_version_oracle, ORACLE_VERSION};\n\n #[test]\n unconstrained fn compatible_oracle_version() {\n assert_compatible_oracle_version_oracle(ORACLE_VERSION);\n }\n\n #[test(should_fail_with = \"Incompatible oracle version. PXE is using version '1', but got a request for '318183437'.\")]\n unconstrained fn incompatible_oracle_version() {\n let arbitrary_incorrect_version = 318183437;\n assert_compatible_oracle_version_oracle(arbitrary_incorrect_version);\n }\n}\n" + }, + "177": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/state_vars/map.nr", + "source": "use crate::state_vars::storage::HasStorageSlot;\nuse dep::protocol_types::{storage::map::derive_storage_slot_in_map, traits::ToField};\n\n/// Map\n///\n/// A key-value storage container that maps keys to state variables, similar\n/// to Solidity mappings.\n///\n/// `Map` enables you to associate keys (like addresses or other identifiers)\n/// with state variables in your Aztec smart contract. This is conceptually\n/// similar to Solidity's `mapping(K => V)` syntax, where you can store and\n/// retrieve values by their associated keys.\n///\n/// You can declare a state variable contained within a Map in your contract's\n/// #[storage] struct.\n///\n/// For example, you might use\n/// `Map, Context>` to track\n/// token balances for different users, similar to how you'd use\n/// `mapping(address => uint256)` in Solidity.\n///\n/// > Aside: the verbose `Context` in the declaration is a consequence of\n/// > leveraging Noir's regular syntax for generics to ensure that certain\n/// > state variable methods can only be called in some contexts (private,\n/// > public, utility).\n///\n/// The methods of Map are:\n/// - `at` (access state variable for a given key)\n/// (see the method's own doc comments for more info).\n///\n/// ## Generic Parameters\n/// - `K`: The key type (must implement `ToField` trait for hashing)\n/// - `V`: The value type:\n/// - any Aztec state variable:\n/// - `PublicMutable`\n/// - `PublicImmutable`\n/// - `PrivateMutable`\n/// - `PrivateImmutable`\n/// - `PrivateSet`\n/// - `DelayedPublicMutable`\n/// - `Map`\n/// - `Context`: The execution context (handles private/public function\n/// contexts)\n///\n/// ## Usage\n/// Maps are typically declared in your contract's #[storage] struct and\n/// accessed\n/// using the `at(key)` method to get the state variable for a specific key.\n/// The resulting state variable can then be read from or written to using its\n/// own methods.\n///\n/// ## Advanced\n/// Internally, `Map` uses a single base storage slot to represent the\n/// mapping\n/// itself, similar to Solidity's approach. Individual key-value pairs are\n/// stored at derived storage slots computed by hashing the base storage\n/// slot\n/// with the key using Poseidon2. This ensures:\n/// - No storage slot collisions between different keys\n/// - Uniform distribution of storage slots across the storage space\n/// - Compatibility with Aztec's storage tree structure\n/// - Gas-efficient storage access patterns similar to Solidity mappings\n///\n/// The storage slot derivation uses `derive_storage_slot_in_map(base_slot,\n/// key)` which computes `poseidon2_hash([base_slot, key.to_field()])`,\n/// ensuring cryptographically secure slot separation.\n///\n/// docs:start:map\npub struct Map {\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V,\n}\n// docs:end:map\n\n// Map reserves a single storage slot regardless of what it stores because\n// nothing is stored at said slot: it is only used to derive the storage slots\n// of nested state variables, which is expected to never result in collisions\n// or slots being close to one another due to these being hashes. This mirrors\n// the strategy adopted by Solidity mappings.\nimpl HasStorageSlot<1> for Map {\n fn get_storage_slot(self) -> Field {\n self.storage_slot\n }\n}\n\nimpl Map {\n /// Initializes a new Map state variable.\n ///\n /// This function is usually automatically called within the #[storage]\n /// macro.\n /// You typically don't need to call this directly when writing smart contracts.\n ///\n /// # Arguments\n ///\n /// * `context` - One of `PrivateContext`/`PublicContext`/`UtilityContext`.\n /// The Context determines which methods of this struct will\n /// be made available to the calling smart contract function.\n /// * `storage_slot` - A unique identifier for this Map within the contract.\n /// Usually, the #[storage] macro will determine an\n /// appropriate storage_slot automatically. A smart\n /// contract dev shouldn't have to worry about this, as\n /// it's managed behind the scenes.\n /// * `state_var_constructor` - A function that creates the value type (V)\n /// given a context and storage slot. This is\n /// typically the constructor of the state\n /// variable type being stored in the Map.\n ///\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 /// Returns the state variable associated with the given key.\n ///\n /// This is equivalent to accessing `mapping[key]` in Solidity. It returns\n /// the state variable instance for the specified key, which can then be\n /// used to read or write the value at that key.\n ///\n /// Unlike Solidity mappings which return the value directly, this returns\n /// the state variable wrapper (like PrivateMutable, PublicMutable, etc.)\n /// that you then call methods on to interact with the actual value.\n ///\n /// # Arguments\n ///\n /// * `key` - The key to look up in the map. Must implement the ToField\n /// trait (which most basic Noir & Aztec types do).\n ///\n /// # Returns\n ///\n /// * `V` - The state variable instance for this key. You can then call\n /// methods like `.read()`, `.write()`, `.get_note()`, etc. on this\n /// depending on the specific state variable type.\n ///\n /// # Example\n ///\n /// ```noir\n /// // Get a user's balance (assuming PrivateMutable)\n /// let user_balance = storage.balances.at(user_address);\n /// let current_note = user_balance.get_note();\n ///\n /// // Update the balance\n /// user_balance.replace(new_note);\n /// ```\n ///\n // docs:start:at\n pub fn at(self, key: K) -> V\n where\n K: ToField,\n {\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" + }, + "18": { + "path": "std/field/mod.nr", + "source": "pub mod bn254;\nuse crate::{runtime::is_unconstrained, static_assert};\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n /// Asserts that `self` can be represented in `bit_size` bits.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^{bit_size}`.\n // docs:start:assert_max_bit_size\n pub fn assert_max_bit_size(self) {\n // docs:end:assert_max_bit_size\n static_assert(\n BIT_SIZE < modulus_num_bits() as u32,\n \"BIT_SIZE must be less than modulus_num_bits\",\n );\n __assert_max_bit_size(self, BIT_SIZE);\n }\n\n /// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n /// This slice will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_le_bits\n pub fn to_le_bits(self: Self) -> [u1; N] {\n // docs:end:to_le_bits\n let bits = __to_le_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[N - 1 - i] != p[N - 1 - i]) {\n assert(p[N - 1 - i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_be_bits\n pub fn to_be_bits(self: Self) -> [u1; N] {\n // docs:end:to_be_bits\n let bits = __to_be_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the decomposition does not overflow the modulus\n let p = modulus_be_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[i] != p[i]) {\n assert(p[i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its little endian byte decomposition as a `[u8;N]` array\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_le_bytes\n pub fn to_le_bytes(self: Self) -> [u8; N] {\n // docs:end:to_le_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_le_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[N - 1 - i] != p[N - 1 - i]) {\n assert(bytes[N - 1 - i] < p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n /// Decomposes `self` into its big endian byte decomposition as a `[u8;N]` array of length required to represent the field modulus\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_be_bytes\n pub fn to_be_bytes(self: Self) -> [u8; N] {\n // docs:end:to_be_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_be_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_be_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[i] != p[i]) {\n assert(bytes[i] < p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n fn to_le_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_le_radix(self, radix)\n }\n\n fn to_be_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_be_radix(self, radix)\n }\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: [u1; 32] = exponent.to_le_bits();\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 `elem` {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 /// Convert a little endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_le_bytes(bytes: [u8; N]) -> Field {\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[i] as Field) * v;\n v = v * 256;\n }\n result\n }\n\n /// Convert a big endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_be_bytes(bytes: [u8; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[N - 1 - i] as Field) * v;\n v = v * 256;\n }\n result\n }\n}\n\n#[builtin(apply_range_constraint)]\nfn __assert_max_bit_size(value: Field, bit_size: u32) {}\n\n// `_radix` must be less than 256\n#[builtin(to_le_radix)]\nfn __to_le_radix(value: Field, radix: u32) -> [u8; N] {}\n\n// `_radix` must be less than 256\n#[builtin(to_be_radix)]\nfn __to_be_radix(value: Field, radix: u32) -> [u8; N] {}\n\n/// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n/// This slice will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_le_bits)]\nfn __to_le_bits(value: Field) -> [u1; N] {}\n\n/// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n/// This array will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_be_bits)]\nfn __to_be_bits(value: Field) -> [u1; N] {}\n\n#[builtin(modulus_num_bits)]\npub comptime fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub comptime fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub comptime fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub comptime fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub comptime fn modulus_le_bytes() -> [u8] {}\n\n/// An unconstrained only built in to efficiently compare fields.\n#[builtin(field_less_than)]\nunconstrained fn __field_less_than(x: Field, y: Field) -> bool {}\n\npub(crate) unconstrained fn field_less_than(x: Field, y: Field) -> bool {\n __field_less_than(x, y)\n}\n\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 if is_unconstrained() {\n // Safety: unconstrained context\n unsafe {\n field_less_than(x, y)\n }\n } else {\n let x_bytes: [u8; 32] = x.to_le_bytes();\n let y_bytes: [u8; 32] = y.to_le_bytes();\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..32 {\n if (!done) {\n let x_byte = x_bytes[32 - 1 - i] as u8;\n let y_byte = y_bytes[32 - 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\nmod tests {\n use crate::{panic::panic, runtime};\n use super::field_less_than;\n\n #[test]\n // docs:start:to_be_bits_example\n fn test_to_be_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_be_bits();\n assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]);\n }\n // docs:end:to_be_bits_example\n\n #[test]\n // docs:start:to_le_bits_example\n fn test_to_le_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_le_bits();\n assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]);\n }\n // docs:end:to_le_bits_example\n\n #[test]\n // docs:start:to_be_bytes_example\n fn test_to_be_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_be_bytes();\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_bytes_example\n\n #[test]\n // docs:start:to_le_bytes_example\n fn test_to_le_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_le_bytes();\n assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_bytes_example\n\n #[test]\n // docs:start:to_be_radix_example\n fn test_to_be_radix() {\n // 259, in base 256, big endian, is [1, 3].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_be_radix(256);\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 1, 3]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_radix_example\n\n #[test]\n // docs:start:to_le_radix_example\n fn test_to_le_radix() {\n // 259, in base 256, little endian, is [3, 1].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_le_radix(256);\n assert_eq(bytes, [3, 1, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_radix_example\n\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n // TODO: Update this test to account for the Brillig restriction that the radix must be greater than 2\n //#[test]\n //fn test_to_le_radix_brillig_1() {\n // // this test should only fail in constrained mode\n // if runtime::is_unconstrained() {\n // let field = 1;\n // let out: [u8; 8] = field.to_le_radix(1);\n // crate::println(out);\n // let expected = [0; 8];\n // assert(out == expected, \"unexpected result\");\n // }\n //}\n\n #[test(should_fail_with = \"radix must be a power of 2\")]\n fn test_to_le_radix_3() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(3);\n } else {\n panic(f\"radix must be a power of 2\");\n }\n }\n\n #[test]\n fn test_to_le_radix_brillig_3() {\n // this test should only fail in constrained mode\n if runtime::is_unconstrained() {\n let field = 1;\n let out: [u8; 8] = field.to_le_radix(3);\n let mut expected = [0; 8];\n expected[0] = 1;\n assert(out == expected, \"unexpected result\");\n }\n }\n\n #[test(should_fail_with = \"radix must be less than or equal to 256\")]\n fn test_to_le_radix_512() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(512);\n } else {\n panic(f\"radix must be less than or equal to 256\")\n }\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n unconstrained fn not_enough_limbs_brillig() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n fn not_enough_limbs() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n // TODO: Update this test to account for the Brillig restriction that the radix must be less than 512\n //#[test]\n //fn test_to_le_radix_brillig_512() {\n // // this test should only fail in constrained mode\n // if runtime::is_unconstrained() {\n // let field = 1;\n // let out: [u8; 8] = field.to_le_radix(512);\n // let mut expected = [0; 8];\n // expected[0] = 1;\n // assert(out == expected, \"unexpected result\");\n // }\n //}\n\n #[test]\n unconstrained fn test_field_less_than() {\n assert(field_less_than(0, 1));\n assert(field_less_than(0, 0x100));\n assert(field_less_than(0x100, 0 - 1));\n assert(!field_less_than(0 - 1, 0));\n }\n}\n" + }, + "185": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr", + "source": "use crate::{\n context::{PrivateContext, PublicContext, UtilityContext},\n state_vars::storage::HasStorageSlot,\n utils::with_hash::WithHash,\n};\nuse protocol_types::{\n constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, hash::poseidon2_hash_with_separator,\n traits::Packable,\n};\n\n/// # PublicImmutable\n///\n/// PublicImmutable is a public state variable type for values that are set once\n/// during initialization and remain permanently unchanged.\n///\n/// You can declare a state variable of type PublicImmutable within your contract's\n/// #[storage] struct:\n///\n/// E.g.:\n/// `your_variable: PublicImmutable`\n///\n/// PublicImmutable stores an immutable value in public state which can be _read_\n/// from public, utility and even _private_ execution contexts.\n///\n/// The methods of PublicImmutable are:\n/// - `initialize`\n/// - `read`\n/// (see the methods' own doc comments for more info).\n///\n/// # Generic Parameters:\n///\n/// * `T` - The type of value stored (must implement Packable).\n/// * `Context` - The execution context (PublicContext, PrivateContext, or UtilityContext).\n///\n/// # Advanced\n///\n/// PublicImmutable leverages `WithHash` to enable efficient private reads of\n/// public storage. The `WithHash` wrapper optimizes reads by hashing values that would\n/// be larger than a single field into a single field, then proving inclusion of only\n/// the hash in public storage.\n///\n/// This optimization is particularly valuable when T packs to multiple fields,\n/// as it maintains \"almost constant\" verification overhead regardless of the\n/// original data size.\n///\n/// ## Optimizing private reads in your contract\n/// Since reading T from public immutable storage in private contexts has \"almost\n/// constant\" constraint costs regardless of T's size, it's recommended to group\n/// multiple values into a single struct when they are to be read together. This is\n/// typically useful for configuration data set during contract initialization. E.g.:\n///\n/// ```noir\n/// use dep::aztec::protocol_types::{address::AztecAddress, traits::Packable};\n/// use std::meta::derive;\n///\n/// #[derive(Eq, Packable)]\n/// pub struct Config \\{\n/// pub address_1: AztecAddress,\n/// pub value_1: u128,\n/// pub value_2: u64,\n/// ...\n/// }\n/// ```\n///\n// docs:start:public_immutable_struct\npub struct PublicImmutable {\n context: Context,\n storage_slot: Field,\n}\n// docs:end:public_immutable_struct\n\n/// `WithHash` stores both the packed value (using O fields) and its hash (1 field), requiring O = M + 1 total\n/// fields.\nimpl HasStorageSlot for PublicImmutable\nwhere\n WithHash: Packable,\n{\n fn get_storage_slot(self) -> Field {\n self.storage_slot\n }\n}\n\nimpl PublicImmutable {\n /// Initializes a new PublicImmutable state variable.\n ///\n /// This function is usually automatically called within the #[storage] macro.\n /// You typically don't need to call this directly when writing smart contracts.\n ///\n /// # Arguments\n ///\n /// * `context` - One of `PublicContext`/`PrivateContext`/`UtilityContext`. The\n /// Context determines which methods of this struct will be made\n /// available to the calling smart contract function.\n /// * `storage_slot` - A unique identifier for this state variable within the\n /// contract. Usually, the #[storage] macro will determine an\n /// appropriate storage_slot automatically. A smart contract\n /// dev shouldn't have to worry about this, as it's managed\n /// behind the scenes.\n ///\n /// docs:start:public_immutable_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 PublicImmutable { context, storage_slot }\n }\n // docs:end:public_immutable_struct_new\n\n pub fn compute_initialization_nullifier(self) -> Field {\n poseidon2_hash_with_separator(\n [self.storage_slot],\n GENERATOR_INDEX__INITIALIZATION_NULLIFIER,\n )\n }\n}\n\nimpl PublicImmutable {\n /// Initializes a PublicImmutable state variable instance with a permanent value.\n ///\n /// This function sets the immutable value for this state variable. It can only\n /// be called once per PublicImmutable. Subsequent calls will fail because the\n /// initialization nullifier will already exist.\n ///\n /// # Arguments\n /// * `value` - The permanent value to store in this PublicImmutable.\n ///\n /// # Panics\n /// Panics if the value is already initialized.\n ///\n /// # Advanced\n ///\n /// This function performs the following operations:\n /// - Creates and emits an initialization nullifier to mark this storage slot\n /// as initialized. This prevents double-initialization.\n /// - Wraps the value in `WithHash` for efficient private reads.\n /// - Stores the wrapped value in Aztec's public data tree.\n ///\n /// docs:start:public_immutable_struct_write\n pub fn initialize(self, value: T)\n where\n T: Packable + Eq,\n {\n // We emit an initialization nullifier to indicate that the struct is initialized. This also prevents\n // the value from being initialized again as a nullifier can be included only once.\n let nullifier = self.compute_initialization_nullifier();\n self.context.push_nullifier(nullifier);\n\n self.context.storage_write(self.storage_slot, WithHash::new(value));\n }\n // docs:end:public_immutable_struct_write\n\n /// Reads the permanent value stored in this PublicImmutable state variable.\n ///\n /// # Returns\n /// * `T` - The permanent value stored in this PublicImmutable.\n ///\n /// # Panics\n /// Panics if the value is not initialized.\n ///\n /// # Advanced\n ///\n /// This function performs the following operations:\n /// - Checks that the state variable has been initialized by verifying the\n /// initialization nullifier exists\n /// - Reads the `WithHash` wrapper from public storage\n /// - Extracts and returns the original value T\n ///\n /// The function will panic if called on an uninitialized PublicImmutable.\n ///\n /// docs:start:public_immutable_struct_read\n pub fn read(self) -> T\n where\n T: Packable + Eq,\n {\n assert(self.is_initialized(), \"Trying to read from uninitialized PublicImmutable\");\n WithHash::public_storage_read(*self.context, self.storage_slot)\n }\n // docs:end:public_immutable_struct_read\n\n /// Reads the value stored in this PublicImmutable without checking if the value\n /// is initialized.\n ///\n /// This function bypasses the initialization check and directly reads from\n /// storage.\n /// If the PublicImmutable has not been initialized, this will return a\n /// zeroed value.\n /// However, if the variable is _known_ to be initialized, this is cheaper\n /// to call than `read`.\n ///\n /// # Returns\n ///\n /// * `T` - The value stored in this PublicImmutable, or empty/default values if\n /// uninitialized.\n ///\n pub fn read_unsafe(self) -> T\n where\n T: Packable + Eq,\n {\n WithHash::public_storage_read(*self.context, self.storage_slot)\n }\n\n fn is_initialized(self) -> bool {\n let nullifier = self.compute_initialization_nullifier();\n self.context.nullifier_exists(nullifier, self.context.this_address())\n }\n}\n\nimpl PublicImmutable {\n /// Reads the permanent value stored in this PublicImmutable state variable.\n ///\n /// Notice that this function is executable only within a UtilityContext, which\n /// is an unconstrained environment on the user's local device.\n ///\n /// # Returns\n ///\n /// * `T` - The permanent value stored in this PublicImmutable.\n ///\n pub unconstrained fn read(self) -> T\n where\n T: Packable + Eq,\n {\n // TODO(#15703): this fn should fail if the variable is not initialized\n WithHash::utility_public_storage_read(self.context, self.storage_slot)\n }\n}\n\nimpl PublicImmutable {\n /// Reads the permanent value stored in this PublicImmutable from the anchor\n /// block.\n ///\n /// Private functions execute asynchronously and offchain. When a user begins\n /// private execution, their view of the chain 'branches off' from the current\n /// public state, since public state continues to advance while they execute\n /// privately. Therefore, private functions read from a historical snapshot of\n /// public state rather than the current state.\n ///\n /// # Returns\n ///\n /// * `T` - The permanent value stored in this PublicImmutable at the historical\n /// block referenced by the private context.\n ///\n /// # Advanced\n ///\n /// This function performs a historical read using the block header from the private\n /// context. The `WithHash` optimization is particularly valuable here because it\n /// reduces the number of required inclusion proofs by proving membership of\n /// only the hash instead of the full packed value.\n ///\n /// The historical read mechanism:\n /// - Uses an oracle to obtain the value from the historical block\n /// - Proves inclusion of the value's hash in the public data tree\n /// - Proves that the root of this public data tree is correct, relative to the\n /// historical block header that is being referenced by this private function.\n /// - Verifies that the oracle-provided value matches the stored hash\n ///\n pub fn read(self) -> T\n where\n T: Packable + Eq,\n {\n // TODO(#15703): this fn should fail if the variable is not initialized\n WithHash::historical_public_storage_read(\n self.context.get_block_header(),\n self.context.this_address(),\n self.storage_slot,\n )\n }\n}\n" + }, + "187": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr", + "source": "use crate::context::{PublicContext, UtilityContext};\nuse crate::state_vars::storage::HasStorageSlot;\nuse dep::protocol_types::traits::Packable;\n\n/// # PublicMutable\n///\n/// PublicMutable is a public state variable type for values that can be read\n/// and written within #[public] functions of your smart contract.\n///\n/// You can declare a state variable of type PublicMutable within your contract's\n/// #[storage] struct:\n///\n/// E.g.:\n/// `your_variable: PublicMutable`\n/// or:\n/// `your_mapping: Map>`\n///\n/// The methods of PublicMutable are:\n/// - `read`\n/// - `write`\n/// (see the methods' own doc comments for more info).\n///\n/// ## Example.\n///\n/// A voting contract's proposal count can be represented as a PublicMutable.\n/// The count can be read by anyone to see how many proposals exist, and incremented\n/// when new proposals are submitted.\n///\n/// # Generic Parameters:\n///\n/// * `T` - The type of value stored (must implement Packable).\n/// * `Context` - The execution context (PublicContext or UtilityContext).\n///\n/// # Advanced\n///\n/// Unlike private state variables which use notes, PublicMutable stores values\n/// directly in Aztec's public data tree. This enables direct read and write\n/// access to the current state during public function execution.\n///\n/// docs:start:public_mutable_struct\npub struct PublicMutable {\n context: Context,\n storage_slot: Field,\n}\n// docs:end:public_mutable_struct\n\nimpl HasStorageSlot for PublicMutable\nwhere\n T: Packable,\n{\n fn get_storage_slot(self) -> Field {\n self.storage_slot\n }\n}\n\nimpl PublicMutable {\n /// Initializes a new PublicMutable state variable.\n ///\n /// This function is usually automatically called within the #[storage] macro.\n /// You typically don't need to call this directly when writing smart contracts.\n ///\n /// # Arguments\n ///\n /// * `context` - One of `PublicContext`/`UtilityContext`. The Context determines\n /// which methods of this struct will be made available to the calling\n /// smart contract function.\n /// * `storage_slot` - A unique identifier for this state variable within the\n /// contract. Usually, the #[storage] macro will determine an\n /// appropriate storage_slot automatically. A smart contract\n /// dev shouldn't have to worry about this, as it's managed\n /// behind the scenes.\n ///\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 /// Reads the current value stored in this PublicMutable state variable.\n ///\n /// # Returns\n ///\n /// * `T` - The current value stored in this PublicMutable.\n ///\n /// docs:start:public_mutable_struct_read\n pub fn read(self) -> T\n where\n T: Packable,\n {\n self.context.storage_read(self.storage_slot)\n }\n // docs:end:public_mutable_struct_read\n\n /// Writes a new value to this PublicMutable state variable.\n ///\n /// # Arguments\n ///\n /// * `value` - The new value to store in this PublicMutable.\n ///\n /// # Advanced\n ///\n /// This function updates the value stored in Aztec's public data tree.\n /// The new value becomes immediately available to subsequent reads within\n /// the same transaction.\n ///\n /// docs:start:public_mutable_struct_write\n pub fn write(self, value: T)\n where\n T: Packable,\n {\n self.context.storage_write(self.storage_slot, value);\n }\n // docs:end:public_mutable_struct_write\n}\n\nimpl PublicMutable {\n /// Reads the current value stored in this PublicMutable state variable.\n ///\n /// Notice that this function is executable only within a UtilityContext, which\n /// is an unconstrained environment on the user's local device.\n ///\n /// # Returns\n ///\n /// * `T` - The current value stored in this PublicMutable.\n ///\n pub unconstrained fn read(self) -> T\n where\n T: Packable,\n {\n self.context.storage_read(self.storage_slot)\n }\n}\n" + }, + "19": { + "path": "std/hash/mod.nr", + "source": "// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3(input: [u8; N]) -> [u8; 32] {}\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#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\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#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\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.)\npub trait 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.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n type H = H;\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)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\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)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\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)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\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\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n" + }, + "203": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/array/append.nr", + "source": "/// Appends the elements of the second `BoundedVec` to the end of the first one. The resulting `BoundedVec` can have any arbitrary maximum length, but it must be\n/// large enough to fit all of the elements of both the first and second vectors.\npub fn append(\n a: BoundedVec,\n b: BoundedVec,\n) -> BoundedVec {\n let mut dst = BoundedVec::new();\n\n dst.extend_from_bounded_vec(a);\n dst.extend_from_bounded_vec(b);\n\n dst\n}\n\nmod test {\n use super::append;\n\n #[test]\n unconstrained fn append_empty_vecs() {\n let a: BoundedVec<_, 3> = BoundedVec::new();\n let b: BoundedVec<_, 14> = BoundedVec::new();\n\n let result: BoundedVec = append(a, b);\n\n assert_eq(result.len(), 0);\n assert_eq(result.storage(), std::mem::zeroed());\n }\n\n #[test]\n unconstrained fn append_non_empty_vecs() {\n let a: BoundedVec<_, 3> = BoundedVec::from_array([1, 2, 3]);\n let b: BoundedVec<_, 14> = BoundedVec::from_array([4, 5, 6]);\n\n let result: BoundedVec = append(a, b);\n\n assert_eq(result.len(), 6);\n assert_eq(result.storage(), [1, 2, 3, 4, 5, 6, std::mem::zeroed(), std::mem::zeroed()]);\n }\n\n #[test(should_fail_with = \"out of bounds\")]\n unconstrained fn append_non_empty_vecs_insufficient_max_len() {\n let a: BoundedVec<_, 3> = BoundedVec::from_array([1, 2, 3]);\n let b: BoundedVec<_, 14> = BoundedVec::from_array([4, 5, 6]);\n\n let _: BoundedVec = append(a, b);\n }\n}\n" + }, + "206": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/array/subarray.nr", + "source": "/// Returns `DstLen` elements from a source array, starting at `offset`. `DstLen` must not be larger than the number\n/// of elements past `offset`.\n///\n/// Examples:\n/// ```\n/// let foo: [Field; 2] = subarray([1, 2, 3, 4, 5], 2);\n/// assert_eq(foo, [3, 4]);\n///\n/// let bar: [Field; 5] = subarray([1, 2, 3, 4, 5], 2); // fails - we can't return 5 elements since only 3 remain\n/// ```\npub fn subarray(src: [T; SrcLen], offset: u32) -> [T; DstLen] {\n assert(offset + DstLen <= SrcLen, \"DstLen too large for offset\");\n\n let mut dst: [T; DstLen] = std::mem::zeroed();\n for i in 0..DstLen {\n dst[i] = src[i + offset];\n }\n\n dst\n}\n\nmod test {\n use super::subarray;\n\n #[test]\n unconstrained fn subarray_into_empty() {\n // In all of these cases we're setting DstLen to be 0, so we always get back an empty array.\n assert_eq(subarray::([], 0), []);\n assert_eq(subarray([1, 2, 3, 4, 5], 0), []);\n assert_eq(subarray([1, 2, 3, 4, 5], 2), []);\n }\n\n #[test]\n unconstrained fn subarray_complete() {\n assert_eq(subarray::([], 0), []);\n assert_eq(subarray([1, 2, 3, 4, 5], 0), [1, 2, 3, 4, 5]);\n }\n\n #[test]\n unconstrained fn subarray_different_end_sizes() {\n // We implicitly select how many values to read in the size of the return array\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2, 3, 4, 5]);\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2, 3, 4]);\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2, 3]);\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2]);\n }\n\n #[test(should_fail_with = \"DstLen too large for offset\")]\n unconstrained fn subarray_offset_too_large() {\n // With an offset of 1 we can only request up to 4 elements\n let _: [_; 5] = subarray([1, 2, 3, 4, 5], 1);\n }\n\n #[test(should_fail)]\n unconstrained fn subarray_bad_return_value() {\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [3, 3, 4, 5]);\n }\n}\n" + }, + "207": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/array/subbvec.nr", + "source": "use crate::utils::array;\n\n/// Returns `DstMaxLen` elements from a source BoundedVec, starting at `offset`. `offset` must not be larger than the\n/// original length, and `DstLen` must not be larger than the total number of elements past `offset` (including the\n/// zeroed elements past `len()`).\n///\n/// Only elements at the beginning of the vector can be removed: it is not possible to also remove elements at the end\n/// of the vector by passing a value for `DstLen` that is smaller than `len() - offset`.\n///\n/// Examples:\n/// ```\n/// let foo = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n/// assert_eq(subbvec(foo, 2), BoundedVec::<_, 8>::from_array([3, 4, 5]));\n///\n/// let bar: BoundedVec<_, 1> = subbvec(foo, 2); // fails - we can't return just 1 element since 3 remain\n/// let baz: BoundedVec<_, 10> = subbvec(foo, 3); // fails - we can't return 10 elements since only 7 remain\n/// ```\npub fn subbvec(\n bvec: BoundedVec,\n offset: u32,\n) -> BoundedVec {\n // from_parts_unchecked does not verify that the elements past len are zeroed, but that is not an issue in our case\n // because we're constructing the new storage array as a subarray of the original one (which should have zeroed\n // storage past len), guaranteeing correctness. This is because `subarray` does not allow extending arrays past\n // their original length.\n BoundedVec::from_parts_unchecked(array::subarray(bvec.storage(), offset), bvec.len() - offset)\n}\n\nmod test {\n use super::subbvec;\n\n #[test]\n unconstrained fn subbvec_empty() {\n let bvec = BoundedVec::::from_array([]);\n assert_eq(subbvec(bvec, 0), bvec);\n }\n\n #[test]\n unconstrained fn subbvec_complete() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n assert_eq(subbvec(bvec, 0), bvec);\n\n let smaller_capacity = BoundedVec::<_, 5>::from_array([1, 2, 3, 4, 5]);\n assert_eq(subbvec(bvec, 0), smaller_capacity);\n }\n\n #[test]\n unconstrained fn subbvec_partial() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n assert_eq(subbvec(bvec, 2), BoundedVec::<_, 8>::from_array([3, 4, 5]));\n assert_eq(subbvec(bvec, 2), BoundedVec::<_, 3>::from_array([3, 4, 5]));\n }\n\n #[test]\n unconstrained fn subbvec_into_empty() {\n let bvec: BoundedVec<_, 10> = BoundedVec::from_array([1, 2, 3, 4, 5]);\n assert_eq(subbvec(bvec, 5), BoundedVec::<_, 5>::from_array([]));\n }\n\n #[test(should_fail)]\n unconstrained fn subbvec_offset_past_len() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n let _: BoundedVec<_, 1> = subbvec(bvec, 6);\n }\n\n #[test(should_fail)]\n unconstrained fn subbvec_insufficient_dst_len() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n // We're not providing enough space to hold all of the items inside the original BoundedVec. subbvec can cause\n // for the capacity to reduce, but not the length (other than by len - offset).\n let _: BoundedVec<_, 1> = subbvec(bvec, 2);\n }\n\n #[test(should_fail_with = \"DstLen too large for offset\")]\n unconstrained fn subbvec_dst_len_causes_enlarge() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n // subbvec does not supprt capacity increases\n let _: BoundedVec<_, 11> = subbvec(bvec, 0);\n }\n\n #[test(should_fail_with = \"DstLen too large for offset\")]\n unconstrained fn subbvec_dst_len_too_large_for_offset() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n // This effectively requests a capacity increase, since there'd be just one element plus the 5 empty slots,\n // which is less than 7.\n let _: BoundedVec<_, 7> = subbvec(bvec, 4);\n }\n}\n" + }, + "209": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/conversion/bytes_to_fields.nr", + "source": "use std::static_assert;\n\n// These functions are used to facilitate the conversion of log ciphertext between byte and field representations.\n//\n// `bytes_to_fields` uses fixed-size arrays since encryption contexts have compile-time size information.\n// `bytes_from_fields` uses BoundedVec for flexibility in unconstrained contexts where sizes are dynamic.\n//\n// Together they provide bidirectional conversion between bytes and fields when processing encrypted logs.\n\n/// Converts the input bytes into an array of fields. A Field is ~254 bits meaning that each field can store 31 whole\n/// bytes. Use `bytes_from_fields` to obtain the original bytes array.\n///\n/// The input bytes are chunked into chunks of 31 bytes. Each 31-byte chunk is viewed as big-endian, and is converted\n/// into a Field.\n/// For example, [1, 10, 3, ..., 0] (31 bytes) is encoded as [1 * 256^30 + 10 * 256^29 + 3 * 256^28 + ... + 0]\n/// Note: N must be a multiple of 31 bytes\npub fn bytes_to_fields(bytes: [u8; N]) -> [Field; N / 31] {\n // Assert that N is a multiple of 31\n static_assert(N % 31 == 0, \"N must be a multiple of 31\");\n\n let mut fields = [0; N / 31];\n\n // Since N is a multiple of 31, we can simply process all chunks fully\n for i in 0..N / 31 {\n let mut field = 0;\n for j in 0..31 {\n // Shift the existing value left by 8 bits and add the new byte\n field = field * 256 + bytes[i * 31 + j] as Field;\n }\n fields[i] = field;\n }\n\n fields\n}\n\n/// Converts an input BoundedVec of fields into a BoundedVec of bytes in big-endian order. Arbitrary Field arrays\n/// are not allowed: this is assumed to be an array obtained via `bytes_to_fields`, i.e. one that actually represents\n/// bytes. To convert a Field array into bytes, use `fields_to_bytes`.\n///\n/// Each input field must contain at most 31 bytes (this is constrained to be so).\n/// Each field is converted into 31 big-endian bytes, and the resulting 31-byte chunks are concatenated\n/// back together in the order of the original fields.\npub fn bytes_from_fields(fields: BoundedVec) -> BoundedVec {\n let mut bytes = BoundedVec::new();\n\n for i in 0..fields.len() {\n let field = fields.get(i);\n\n // We expect that the field contains at most 31 bytes of information.\n field.assert_max_bit_size::<248>();\n\n // Now we can safely convert the field to 31 bytes.\n let field_as_bytes: [u8; 31] = field.to_be_bytes();\n\n for j in 0..31 {\n bytes.push(field_as_bytes[j]);\n }\n }\n\n bytes\n}\n\nmod tests {\n use crate::utils::array::subarray;\n use super::{bytes_from_fields, bytes_to_fields};\n\n #[test]\n unconstrained fn random_bytes_to_fields_and_back(input: [u8; 93]) {\n let fields = bytes_to_fields(input);\n\n // At this point in production, the log flies through the system and we get a BoundedVec on the other end.\n // So we need to convert the field array to a BoundedVec to be able to feed it to the `bytes_from_fields`\n // function.\n let fields_as_bounded_vec = BoundedVec::<_, 6>::from_array(fields);\n\n let bytes_back = bytes_from_fields(fields_as_bounded_vec);\n\n // Compare the original input with the round-tripped result\n assert_eq(bytes_back.len(), input.len());\n assert_eq(subarray(bytes_back.storage(), 0), input);\n }\n\n #[test(should_fail_with = \"N must be a multiple of 31\")]\n unconstrained fn bytes_to_fields_input_length_not_multiple_of_31() {\n // Try to convert 32 bytes (not a multiple of 31) to fields\n let _fields = bytes_to_fields([0; 32]);\n }\n\n}\n" + }, + "210": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/conversion/fields_to_bytes.nr", + "source": "// These functions are used to facilitate the conversion of log plaintext represented as fields into bytes and back.\n//\n// `fields_to_bytes` uses fixed-size arrays since encryption contexts have compile-time size information.\n// `fields_from_bytes` uses BoundedVec for flexibility in unconstrained contexts where sizes are dynamic.\n//\n// Together they provide bidirectional conversion between fields and bytes.\n\n/// Converts an input array of fields into a single array of bytes. Use `fields_from_bytes` to obtain the original\n/// field array.\n/// Each field is converted to a 32-byte big-endian array.\n///\n/// For example, if you have a field array [123, 456], it will be converted to a 64-byte array:\n/// [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,123, // First field (32 bytes)\n/// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,200] // Second field (32 bytes)\n///\n/// Since a field is ~254 bits, you'll end up with a subtle 2-bit \"gap\" at the big end, every 32 bytes. Be careful\n/// that such a gap doesn't leak information! This could happen if you for example expected the output to be\n/// indistinguishable from random bytes.\npub fn fields_to_bytes(fields: [Field; N]) -> [u8; 32 * N] {\n let mut bytes = [0; 32 * N];\n\n for i in 0..N {\n let field_as_bytes: [u8; 32] = fields[i].to_be_bytes();\n\n for j in 0..32 {\n bytes[i * 32 + j] = field_as_bytes[j];\n }\n }\n\n bytes\n}\n\n/// Converts an input BoundedVec of bytes into a BoundedVec of fields. Arbitrary byte arrays are not allowed: this\n/// is assumed to be an array obtained via `fields_to_bytes`, i.e. one that actually represents fields. To convert\n/// a byte array into Fields, use `bytes_to_fields`.\n///\n/// The input bytes are chunked into chunks of 32 bytes. Each 32-byte chunk is viewed as big-endian, and is converted\n/// into a Field.\n/// For example, [1, 10, 3, ..., 0] (32 bytes) is encoded as [1 * 256^31 + 10 * 256^30 + 3 * 256^29 + ... + 0]\n/// Note 1: N must be a multiple of 32 bytes\n/// Note 2: The max value check code was taken from std::field::to_be_bytes function.\npub fn fields_from_bytes(bytes: BoundedVec) -> BoundedVec {\n // Assert that input length is a multiple of 32\n assert(bytes.len() % 32 == 0, \"Input length must be a multiple of 32\");\n\n let mut fields = BoundedVec::new();\n\n let p = std::field::modulus_be_bytes();\n\n // Since input length is a multiple of 32, we can simply process all chunks fully\n for i in 0..bytes.len() / 32 {\n let mut field = 0;\n\n // Process each byte in the 32-byte chunk\n let mut ok = false;\n\n for j in 0..32 {\n let next_byte = bytes.get(i * 32 + j);\n field = field * 256 + next_byte as Field;\n\n if !ok {\n if next_byte != p[j] {\n assert(next_byte < p[j], \"Value does not fit in field\");\n ok = true;\n }\n }\n }\n assert(ok, \"Value does not fit in field\");\n\n fields.push(field);\n }\n\n fields\n}\n\nmod tests {\n use crate::utils::array::subarray;\n use super::{fields_from_bytes, fields_to_bytes};\n\n #[test]\n unconstrained fn random_fields_to_bytes_and_back(input: [Field; 3]) {\n // Convert to bytes\n let bytes = fields_to_bytes(input);\n\n // At this point in production, the log flies through the system and we get a BoundedVec on the other end.\n // So we need to convert the field array to a BoundedVec to be able to feed it to the `fields_from_bytes`\n // function.\n // 113 is an arbitrary max length that is larger than the input length of 96.\n let bytes_as_bounded_vec = BoundedVec::<_, 113>::from_array(bytes);\n\n // Convert back to fields\n let fields_back = fields_from_bytes(bytes_as_bounded_vec);\n\n // Compare the original input with the round-tripped result\n assert_eq(fields_back.len(), input.len());\n assert_eq(subarray(fields_back.storage(), 0), input);\n }\n\n #[test(should_fail_with = \"Input length must be a multiple of 32\")]\n unconstrained fn to_fields_assert() {\n // 143 is an arbitrary max length that is larger than 33\n let input = BoundedVec::<_, 143>::from_array([\n 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n 25, 26, 27, 28, 29, 30, 31, 32, 33,\n ]);\n\n // This should fail since 33 is not a multiple of 32\n let _fields = fields_from_bytes(input);\n }\n\n #[test]\n unconstrained fn fields_from_bytes_max_value() {\n let max_field_as_bytes: [u8; 32] = (-1).to_be_bytes();\n let input = BoundedVec::<_, 32>::from_array(max_field_as_bytes);\n\n let fields = fields_from_bytes(input);\n\n // The result should be a largest value storable in a field (-1 since we are modulo-ing)\n assert_eq(fields.get(0), -1);\n }\n\n // In this test we verify that overflow check works by taking the max allowed value, bumping a random byte\n // and then feeding it to `fields_from_bytes` as input.\n #[test(should_fail_with = \"Value does not fit in field\")]\n unconstrained fn fields_from_bytes_overflow(random_value: u8) {\n let index_of_byte_to_bump = random_value % 32;\n\n // Obtain the byte representation of the maximum field value\n let max_field_value_as_bytes: [u8; 32] = (-1).to_be_bytes();\n\n let byte_to_bump = max_field_value_as_bytes[index_of_byte_to_bump as u32];\n\n // Skip test execution if the selected byte is already at maximum value (255).\n // This is acceptable since we are using fuzz testing to generate many test cases.\n if byte_to_bump != 255 {\n let mut input = BoundedVec::<_, 32>::from_array(max_field_value_as_bytes);\n\n // Increment the selected byte to exceed the field's maximum value\n input.set(index_of_byte_to_bump as u32, byte_to_bump + 1);\n\n // Attempt the conversion, which should fail due to the value exceeding the field's capacity\n let _fields = fields_from_bytes(input);\n }\n }\n\n}\n" + }, + "212": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/field.nr", + "source": "use std::option::Option;\n\nglobal KNOWN_NON_RESIDUE: Field = 5; // This is a non-residue in Noir's native Field.\n\nglobal C1: u32 = 28;\nglobal C3: Field = 40770029410420498293352137776570907027550720424234931066070132305055;\nglobal C5: Field = 19103219067921713944291392827692070036145651957329286315305642004821462161904;\n\n// Power function of two Field arguments of arbitrary size.\n// Adapted from std::field::pow_32.\npub fn pow(x: Field, y: Field) -> Field {\n let mut r = 1 as Field;\n let b: [u1; 254] = y.to_le_bits();\n\n for i in 0..254 {\n r *= r;\n r *= (b[254 - 1 - i] as Field) * x + (1 - b[254 - 1 - i] as Field);\n }\n\n r\n}\n\n// Boolean indicating whether Field element is a square, i.e. whether there exists a y in Field s.t. x = y*y.\nunconstrained fn is_square(x: Field) -> bool {\n let v = pow(x, -1 / 2);\n v * (v - 1) == 0\n}\n\n// Tonelli-Shanks algorithm for computing the square root of a Field element.\n// Requires C1 = max{c: 2^c divides (p-1)}, where p is the order of Field\n// as well as C3 = (C2 - 1)/2, where C2 = (p-1)/(2^c1),\n// and C5 = ZETA^C2, where ZETA is a non-square element of Field.\n// These are pre-computed above as globals.\nunconstrained fn tonelli_shanks_sqrt(x: Field) -> Field {\n let mut z = pow(x, C3);\n let mut t = z * z * x;\n z *= x;\n let mut b = t;\n let mut c = C5;\n\n for i in 0..(C1 - 1) {\n for _j in 1..(C1 - i - 1) {\n b *= b;\n }\n\n z *= if b == 1 { 1 } else { c };\n\n c *= c;\n\n t *= if b == 1 { 1 } else { c };\n\n b = t;\n }\n\n z\n}\n\n// NB: this doesn't return an option, because in the case of there _not_ being a square root, we still want to return a field element that allows us to then assert in the _constrained_ sqrt function that there is no sqrt.\npub unconstrained fn __sqrt(x: Field) -> (bool, Field) {\n let is_sq = is_square(x);\n if is_sq {\n let sqrt = tonelli_shanks_sqrt(x);\n (true, sqrt)\n } else {\n // Demonstrate that x is not a square (a.k.a. a \"quadratic non-residue\").\n // Facts:\n // The Legendre symbol (\"LS\") of x, is x^((p-1)/2) (mod p).\n // - If x is a square, LS(x) = 1\n // - If x is not a square, LS(x) = -1\n // - If x = 0, LS(x) = 0.\n //\n // Hence:\n // sq * sq = sq // 1 * 1 = 1\n // non-sq * non-sq = sq // -1 * -1 = 1\n // sq * non-sq = non-sq // -1 * 1 = -1\n //\n // See: https://en.wikipedia.org/wiki/Legendre_symbol\n let demo_x_not_square = x * KNOWN_NON_RESIDUE;\n let not_sqrt = tonelli_shanks_sqrt(demo_x_not_square);\n (false, not_sqrt)\n }\n}\n\n// Returns (false, 0) if there is no square root.\n// Returns (true, sqrt) if there is a square root.\npub fn sqrt(x: Field) -> Option {\n // Safety: if the hint returns the square root of x, then we simply square it\n // check the result equals x. If x is not square, we return a value that\n // enables us to prove that fact (see the `else` clause below).\n let (is_sq, maybe_sqrt) = unsafe { __sqrt(x) };\n\n if is_sq {\n let sqrt = maybe_sqrt;\n validate_sqrt_hint(x, sqrt);\n Option::some(sqrt)\n } else {\n let not_sqrt_hint = maybe_sqrt;\n validate_not_sqrt_hint(x, not_sqrt_hint);\n Option::none()\n }\n}\n\nfn validate_sqrt_hint(x: Field, hint: Field) {\n assert(hint * hint == x, f\"The claimed_sqrt {hint} is not the sqrt of x {x}\");\n}\n\nfn validate_not_sqrt_hint(x: Field, hint: Field) {\n // We need this assertion, because x = 0 would pass the other assertions in this\n // function, and we don't want people to be able to prove that 0 is not square!\n assert(x != 0, \"0 has a square root; you cannot claim it is not square\");\n // Demonstrate that x is not a square (a.k.a. a \"quadratic non-residue\").\n //\n // Facts:\n // The Legendre symbol (\"LS\") of x, is x^((p-1)/2) (mod p).\n // - If x is a square, LS(x) = 1\n // - If x is not a square, LS(x) = -1\n // - If x = 0, LS(x) = 0.\n //\n // Hence:\n // 1. sq * sq = sq // 1 * 1 = 1\n // 2. non-sq * non-sq = sq // -1 * -1 = 1\n // 3. sq * non-sq = non-sq // -1 * 1 = -1\n //\n // See: https://en.wikipedia.org/wiki/Legendre_symbol\n //\n // We want to demonstrate that this below multiplication falls under bullet-point (2):\n let demo_x_not_square = x * KNOWN_NON_RESIDUE;\n // I.e. we want to demonstrate that `demo_x_not_square` has Legendre symbol 1\n // (i.e. that it is a square), so we prove that it is square below.\n // Why do we want to prove that it has LS 1?\n // Well, since it was computed with a known-non-residue, its squareness implies we're\n // in case 2 (something multiplied by a known-non-residue yielding a result which\n // has a LS of 1), which implies that x must be a non-square. The unconstrained\n // function gave us the sqrt of demo_x_not_square, so all we need to do is\n // assert its squareness:\n assert(\n hint * hint == demo_x_not_square,\n f\"The hint {hint} does not demonstrate that {x} is not a square\",\n );\n}\n\n#[test]\nfn test_sqrt() {\n let x = 9;\n let maybe_sqrt = sqrt(x);\n assert(maybe_sqrt.is_some());\n let sqrt = maybe_sqrt.unwrap_unchecked();\n assert((sqrt == 3) | (sqrt == -3));\n}\n\n#[test]\nfn test_non_square() {\n let x = 5;\n let maybe_sqrt = sqrt(x);\n assert(maybe_sqrt.is_none());\n}\n\n#[test]\nunconstrained fn test_known_non_residue_is_actually_a_non_residue_in_the_field() {\n assert(!is_square(KNOWN_NON_RESIDUE));\n}\n\n#[test]\nfn test_sqrt_0() {\n let x = 0;\n let sqrt = sqrt(x).unwrap();\n assert(sqrt == 0);\n}\n\n#[test]\nfn test_sqrt_1() {\n let x = 1;\n let sqrt = sqrt(x).unwrap();\n assert((sqrt == 1) | (sqrt == -1));\n}\n\n#[test(should_fail_with = \"The claimed_sqrt 0x04 is not the sqrt of x 0x09\")]\nfn test_bad_sqrt_hint_fails() {\n validate_sqrt_hint(9, 4);\n}\n\n#[test(should_fail_with = \"The hint 0x04 does not demonstrate that 0x0a is not a square\")]\nfn test_bad_not_sqrt_hint_fails() {\n validate_not_sqrt_hint(10, 4);\n}\n\n#[test(should_fail_with = \"0 has a square root; you cannot claim it is not square\")]\nfn test_0_not_sqrt_hint_fails() {\n validate_not_sqrt_hint(0, 0);\n}\n\n#[test]\nunconstrained fn test_is_square() {\n assert(is_square(25));\n}\n\n#[test]\nunconstrained fn test_is_not_square() {\n assert(!is_square(10));\n}\n" + }, + "214": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/point.nr", + "source": "use crate::utils::field::sqrt;\nuse dep::protocol_types::point::Point;\n\n// I am storing the modulus minus 1 divided by 2 here because full modulus would throw \"String literal too large\" error\n// Full modulus is 21888242871839275222246405745257275088548364400416034343698204186575808495617\nglobal BN254_FR_MODULUS_DIV_2: Field =\n 10944121435919637611123202872628637544274182200208017171849102093287904247808;\n\n/// Converts a point to a byte array.\n///\n/// We don't serialize the point at infinity flag because this function is used in situations where we do not want\n/// to waste the extra byte (encrypted log).\npub fn point_to_bytes(p: Point) -> [u8; 32] {\n // Note that there is 1 more free bit in the 32 bytes (254 bits currently occupied by the x coordinate, 1 bit for\n // the \"sign\") so it's possible to use that last bit as an \"is_infinite\" flag if desired in the future.\n assert(!p.is_infinite, \"Cannot serialize point at infinity as bytes.\");\n\n let mut result: [u8; 32] = p.x.to_be_bytes();\n\n if get_sign_of_point(p) {\n // y is <= (modulus - 1) / 2 so we set the sign bit to 1\n // Here we leverage that field fits into 254 bits (log2(Fr.MODULUS) < 254) and given that we serialize Fr to 32\n // bytes and we use big-endian the 2 most significant bits are never populated. Hence we can use one of\n // the bits as a sign bit.\n result[0] += 128;\n }\n\n result\n}\n\n/**\n * Returns: true if p.y <= MOD_DIV_2, else false.\n */\npub fn get_sign_of_point(p: Point) -> bool {\n // We store only a \"sign\" of the y coordinate because the rest can be derived from the x coordinate. To get\n // the sign we check if the y coordinate is less or equal than the curve's order minus 1 divided by 2.\n // Ideally we'd do `y <= MOD_DIV_2`, but there's no `lte` function, so instead we do `!(y > MOD_DIV_2)`, which is\n // equivalent, and then rewrite that as `!(MOD_DIV_2 < y)`, since we also have no `gt` function.\n !BN254_FR_MODULUS_DIV_2.lt(p.y)\n}\n\npub fn point_from_x_coord(x: Field) -> Point {\n // y ^ 2 = x ^ 3 - 17\n let rhs = x * x * x - 17;\n let y = sqrt(rhs).unwrap();\n Point { x, y, is_infinite: false }\n}\n\n/// Uses the x coordinate and sign flag (+/-) to reconstruct the point.\n/// The y coordinate can be derived from the x coordinate and the \"sign\" flag by solving the grumpkin curve\n/// equation for y.\n/// @param x - The x coordinate of the point\n/// @param sign - The \"sign\" of the y coordinate - determines whether y <= (Fr.MODULUS - 1) / 2\npub fn point_from_x_coord_and_sign(x: Field, sign: bool) -> Point {\n // y ^ 2 = x ^ 3 - 17\n let rhs = x * x * x - 17;\n let y = sqrt(rhs).unwrap();\n\n // If y > MOD_DIV_2 and we want positive sign (or vice versa), negate y\n let y_is_positive = !BN254_FR_MODULUS_DIV_2.lt(y);\n let final_y = if y_is_positive == sign { y } else { -y };\n\n Point { x, y: final_y, is_infinite: false }\n}\n\nmod test {\n use crate::utils::point::{point_from_x_coord_and_sign, point_to_bytes};\n use dep::protocol_types::point::Point;\n\n #[test]\n unconstrained fn test_point_to_bytes_positive_sign() {\n let p = Point {\n x: 0x1af41f5de96446dc3776a1eb2d98bb956b7acd9979a67854bec6fa7c2973bd73,\n y: 0x07fc22c7f2c7057571f137fe46ea9c95114282bc95d37d71ec4bfb88de457d4a,\n is_infinite: false,\n };\n\n let compressed_point = point_to_bytes(p);\n\n let expected_compressed_point_positive_sign = [\n 154, 244, 31, 93, 233, 100, 70, 220, 55, 118, 161, 235, 45, 152, 187, 149, 107, 122,\n 205, 153, 121, 166, 120, 84, 190, 198, 250, 124, 41, 115, 189, 115,\n ];\n assert_eq(expected_compressed_point_positive_sign, compressed_point);\n }\n\n #[test]\n unconstrained fn test_point_to_bytes_negative_sign() {\n let p = Point {\n x: 0x247371652e55dd74c9af8dbe9fb44931ba29a9229994384bd7077796c14ee2b5,\n y: 0x26441aec112e1ae4cee374f42556932001507ad46e255ffb27369c7e3766e5c0,\n is_infinite: false,\n };\n\n let compressed_point = point_to_bytes(p);\n\n let expected_compressed_point_negative_sign = [\n 36, 115, 113, 101, 46, 85, 221, 116, 201, 175, 141, 190, 159, 180, 73, 49, 186, 41, 169,\n 34, 153, 148, 56, 75, 215, 7, 119, 150, 193, 78, 226, 181,\n ];\n\n assert_eq(expected_compressed_point_negative_sign, compressed_point);\n }\n\n #[test]\n unconstrained fn test_point_from_x_coord_and_sign() {\n // Test positive y coordinate\n let x = 0x1af41f5de96446dc3776a1eb2d98bb956b7acd9979a67854bec6fa7c2973bd73;\n let sign = true;\n let p = point_from_x_coord_and_sign(x, sign);\n\n assert_eq(p.x, x);\n assert_eq(p.y, 0x07fc22c7f2c7057571f137fe46ea9c95114282bc95d37d71ec4bfb88de457d4a);\n assert_eq(p.is_infinite, false);\n\n // Test negative y coordinate\n let x2 = 0x247371652e55dd74c9af8dbe9fb44931ba29a9229994384bd7077796c14ee2b5;\n let sign2 = false;\n let p2 = point_from_x_coord_and_sign(x2, sign2);\n\n assert_eq(p2.x, x2);\n assert_eq(p2.y, 0x26441aec112e1ae4cee374f42556932001507ad46e255ffb27369c7e3766e5c0);\n assert_eq(p2.is_infinite, false);\n }\n}\n" + }, + "219": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/with_hash.nr", + "source": "use crate::{\n context::{PublicContext, UtilityContext},\n history::public_storage::PublicStorageHistoricalRead,\n oracle,\n};\nuse dep::protocol_types::{\n abis::block_header::BlockHeader, address::AztecAddress, hash::poseidon2_hash, traits::Packable,\n};\n\n/// A struct that allows for efficient reading of value `T` from public storage in private.\n///\n/// The efficient reads are achieved by verifying large values through a single hash check\n/// and then proving inclusion only of the hash in public storage. This reduces the number\n/// of required tree inclusion proofs from `M` to 1.\n///\n/// # Type Parameters\n/// - `T`: The underlying type being wrapped, must implement `Packable`\n/// - `M`: The number of field elements required to pack values of type `T`\npub struct WithHash {\n value: T,\n packed: [Field; M],\n hash: Field,\n}\n\nimpl WithHash\nwhere\n T: Packable + Eq,\n{\n pub fn new(value: T) -> Self {\n let packed = value.pack();\n Self { value, packed, hash: poseidon2_hash(packed) }\n }\n\n pub fn get_value(self) -> T {\n self.value\n }\n\n pub fn get_hash(self) -> Field {\n self.hash\n }\n\n pub fn public_storage_read(context: PublicContext, storage_slot: Field) -> T {\n context.storage_read(storage_slot)\n }\n\n pub unconstrained fn utility_public_storage_read(\n context: UtilityContext,\n storage_slot: Field,\n ) -> T {\n context.storage_read(storage_slot)\n }\n\n pub fn historical_public_storage_read(\n header: BlockHeader,\n address: AztecAddress,\n storage_slot: Field,\n ) -> T {\n let historical_block_number = header.global_variables.block_number;\n\n // We could simply produce historical inclusion proofs for each field in `packed`, but that would require one\n // full sibling path per storage slot (since due to kernel siloing the storage is not contiguous). Instead, we\n // get an oracle to provide us the values, and instead we prove inclusion of their hash, which is both a much\n // smaller proof (a single slot), and also independent of the size of T (except in that we need to pack and hash T).\n let hint = WithHash::new(\n // Safety: We verify that a hash of the hint/packed data matches the stored hash.\n unsafe {\n oracle::storage::storage_read(address, storage_slot, historical_block_number)\n },\n );\n\n let hash = header.public_storage_historical_read(storage_slot + M as Field, address);\n\n if hash != 0 {\n assert_eq(hash, hint.get_hash(), \"Hint values do not match hash\");\n } else {\n // The hash slot can only hold a zero if it is uninitialized. Therefore, the hints must then be zero\n // (i.e. the default value for public storage) as well.\n assert_eq(\n hint.get_value(),\n T::unpack(std::mem::zeroed()),\n \"Non-zero hint for zero hash\",\n );\n };\n\n hint.get_value()\n }\n}\n\n// Note: I don't derive Packable on `WithHash` because `derive_serialize` function does not support setting \"N = M\"\n// as I do here 3 lines below. This could be worked around by placing the \"where\" clause directly on the `WithHash`\n// struct, but Jake mentioned that the syntax is not expected to be supported at least until Noir 1.0.\n// Relevant discussion on Slack:\n// https://aztecprotocol.slack.com/archives/C04QF64EDNV/p1752593876160699?thread_ts=1752589887.955379&cid=C04QF64EDNV\nimpl Packable for WithHash\nwhere\n T: Packable,\n{\n let N: u32 = M + 1;\n\n fn pack(self) -> [Field; Self::N] {\n let mut result: [Field; Self::N] = std::mem::zeroed();\n for i in 0..M {\n result[i] = self.packed[i];\n }\n result[M] = self.hash;\n\n result\n }\n\n fn unpack(packed: [Field; Self::N]) -> Self {\n let mut value_packed = [0; M];\n for i in 0..M {\n value_packed[i] = packed[i];\n }\n let hash = packed[M];\n\n Self { value: T::unpack(value_packed), packed: value_packed, hash }\n }\n}\n\nmod test {\n use crate::{\n test::{helpers::test_environment::TestEnvironment, mocks::mock_struct::MockStruct},\n utils::with_hash::WithHash,\n };\n use dep::protocol_types::hash::poseidon2_hash;\n use dep::protocol_types::traits::{Packable, ToField};\n use dep::std::test::OracleMock;\n\n global STORAGE_SLOT: Field = 47;\n\n #[test]\n unconstrained fn create_and_recover() {\n let value = MockStruct { a: 5, b: 3 };\n let value_with_hash = WithHash::new(value);\n let recovered = WithHash::unpack(value_with_hash.pack());\n\n assert_eq(recovered.value, value);\n assert_eq(recovered.packed, value.pack());\n assert_eq(recovered.hash, poseidon2_hash(value.pack()));\n }\n\n #[test]\n unconstrained fn read_uninitialized_value() {\n let env = TestEnvironment::new();\n\n env.private_context(|context| {\n let result = WithHash::::historical_public_storage_read(\n context.historical_header,\n context.this_address(),\n STORAGE_SLOT,\n );\n\n assert_eq(result, std::mem::zeroed());\n });\n }\n\n #[test]\n unconstrained fn read_initialized_value() {\n let env = TestEnvironment::new();\n\n let value = MockStruct { a: 5, b: 3 };\n let value_with_hash = WithHash::new(value);\n\n env.public_context(|context| { context.storage_write(STORAGE_SLOT, value_with_hash); });\n\n env.private_context(|context| {\n let result = WithHash::::historical_public_storage_read(\n context.historical_header,\n context.this_address(),\n STORAGE_SLOT,\n );\n assert_eq(result, value);\n });\n }\n\n #[test(should_fail_with = \"Non-zero hint for zero hash\")]\n unconstrained fn bad_hint_uninitialized_value() {\n let env = TestEnvironment::new();\n\n env.private_context(|context| {\n let block_header = context.historical_header;\n let address = context.this_address();\n\n // Mock the oracle to return a non-zero hint/packed value\n let value_packed = MockStruct { a: 1, b: 1 }.pack();\n let _ = OracleMock::mock(\"utilityStorageRead\")\n .with_params((\n address.to_field(), STORAGE_SLOT, block_header.global_variables.block_number,\n value_packed.len(),\n ))\n .returns(value_packed)\n .times(1);\n\n // This should fail because the hint value is non-zero and the hash is zero (default value of storage)\n let _ = WithHash::::historical_public_storage_read(\n block_header,\n address,\n STORAGE_SLOT,\n );\n });\n }\n\n #[test(should_fail_with = \"Hint values do not match hash\")]\n unconstrained fn bad_hint_initialized_value() {\n let env = TestEnvironment::new();\n\n env.public_context(|context| {\n // Write the value and hash separately so that the hash is wrong\n let value = MockStruct { a: 5, b: 3 };\n context.storage_write(STORAGE_SLOT, value);\n\n let incorrect_hash = 13;\n let hash_storage_slot = STORAGE_SLOT + (value.pack().len() as Field);\n context.storage_write(hash_storage_slot, [incorrect_hash]);\n });\n\n env.private_context(|context| {\n let _ = WithHash::::historical_public_storage_read(\n context.historical_header,\n context.this_address(),\n STORAGE_SLOT,\n );\n });\n }\n}\n" + }, + "226": { + "path": "/home/josh/nargo/github.com/noir-lang/poseidon/v0.1.1/src/poseidon2.nr", + "source": "use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct 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 #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n 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) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\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 }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> 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\npub struct 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 { _state: &[] }\n }\n}\n" + }, + "245": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr", + "source": "use crate::traits::{Deserialize, Empty, FromField, Serialize, ToField};\nuse std::meta::derive;\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct FunctionSelector {\n // 1st 4-bytes (big-endian leftmost) of abi-encoding of an event.\n pub inner: u32,\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 = crate::hash::poseidon2_hash_bytes(bytes);\n\n // `hash` is automatically truncated to fit within 32 bits.\n FunctionSelector::from_field(hash)\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n\n#[test]\nfn test_is_valid_selector() {\n let selector = FunctionSelector::from_signature(\"IS_VALID()\");\n assert_eq(selector.to_field(), 0x73cdda47);\n}\n\n#[test]\nfn test_long_selector() {\n let selector =\n FunctionSelector::from_signature(\"foo_and_bar_and_baz_and_foo_bar_baz_and_bar_foo\");\n assert_eq(selector.to_field(), 0x7590a997);\n}\n" + }, + "291": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr", + "source": "use crate::{\n address::{\n partial_address::PartialAddress, salted_initialization_hash::SaltedInitializationHash,\n },\n constants::{\n AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1, MAX_FIELD_VALUE,\n MAX_PROTOCOL_CONTRACTS,\n },\n contract_class_id::ContractClassId,\n hash::poseidon2_hash_with_separator,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, ToPoint, TpkM},\n traits::{Deserialize, Empty, FromField, Packable, Serialize, ToField},\n utils::field::{pow, sqrt},\n};\n\n// We do below because `use crate::point::Point;` does not work\nuse dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\n\nuse crate::public_keys::AddressPoint;\nuse std::{\n embedded_curve_ops::{EmbeddedCurveScalar, fixed_base_scalar_mul as derive_public_key},\n ops::Add,\n};\nuse std::meta::derive;\n\n// Aztec address\n#[derive(Deserialize, Eq, Packable, Serialize)]\npub struct AztecAddress {\n pub inner: Field,\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self { inner: 0 }\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 AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn to_address_point(self) -> AddressPoint {\n // We compute the address point by taking our address, setting it to x, and then solving for y in the\n // equation which defines our bn curve:\n // y^2 = x^3 - 17; x = address\n let x = self.inner;\n let y_squared = pow(x, 3) - 17;\n\n // TODO (#8970): Handle cases where we cannot recover a point from an address\n let mut y = sqrt(y_squared);\n\n // If we get a negative y coordinate (any y where y > MAX_FIELD_VALUE / 2), we pin it to the\n // positive one (any value where y <= MAX_FIELD_VALUE / 2) by subtracting it from the Field modulus\n // note: The field modulus is MAX_FIELD_VALUE + 1\n if (!(y.lt(MAX_FIELD_VALUE / 2) | y.eq(MAX_FIELD_VALUE / 2))) {\n y = (MAX_FIELD_VALUE + 1) - y;\n }\n\n AddressPoint { inner: Point { x: self.inner, y, is_infinite: false } }\n }\n\n pub fn compute(public_keys: PublicKeys, partial_address: PartialAddress) -> AztecAddress {\n let public_keys_hash = public_keys.hash();\n\n let pre_address = poseidon2_hash_with_separator(\n [public_keys_hash.to_field(), partial_address.to_field()],\n GENERATOR_INDEX__CONTRACT_ADDRESS_V1,\n );\n\n let address_point = derive_public_key(EmbeddedCurveScalar::from_field(pre_address)).add(\n public_keys.ivpk_m.to_point(),\n );\n\n // Note that our address is only the x-coordinate of the full address_point. This is okay because when people want to encrypt something and send it to us\n // they can recover our full point using the x-coordinate (our address itself). To do this, they recompute the y-coordinate according to the equation y^2 = x^3 - 17.\n // When they do this, they may get a positive y-coordinate (a value that is less than or equal to MAX_FIELD_VALUE / 2) or\n // a negative y-coordinate (a value that is more than MAX_FIELD_VALUE), and we cannot dictate which one they get and hence the recovered point may sometimes be different than the one\n // our secret can decrypt. Regardless though, they should and will always encrypt using point with the positive y-coordinate by convention.\n // This ensures that everyone encrypts to the same point given an arbitrary x-coordinate (address). This is allowed because even though our original point may not have a positive y-coordinate,\n // with our original secret, we will be able to derive the secret to the point with the flipped (and now positive) y-coordinate that everyone encrypts to.\n AztecAddress::from_field(address_point.x)\n }\n\n pub fn compute_from_class_id(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash,\n public_keys: PublicKeys,\n ) -> Self {\n let partial_address = PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n salted_initialization_hash,\n );\n\n AztecAddress::compute(public_keys, partial_address)\n }\n\n pub fn is_protocol_contract(self) -> bool {\n self.inner.lt(MAX_PROTOCOL_CONTRACTS as 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\n#[test]\nfn compute_address_from_partial_and_pub_keys() {\n let public_keys = PublicKeys {\n npk_m: NpkM {\n inner: Point {\n x: 0x22f7fcddfa3ce3e8f0cc8e82d7b94cdd740afa3e77f8e4a63ea78a239432dcab,\n y: 0x0471657de2b6216ade6c506d28fbc22ba8b8ed95c871ad9f3e3984e90d9723a7,\n is_infinite: false,\n },\n },\n ivpk_m: IvpkM {\n inner: Point {\n x: 0x111223493147f6785514b1c195bb37a2589f22a6596d30bb2bb145fdc9ca8f1e,\n y: 0x273bbffd678edce8fe30e0deafc4f66d58357c06fd4a820285294b9746c3be95,\n is_infinite: false,\n },\n },\n ovpk_m: OvpkM {\n inner: Point {\n x: 0x09115c96e962322ffed6522f57194627136b8d03ac7469109707f5e44190c484,\n y: 0x0c49773308a13d740a7f0d4f0e6163b02c5a408b6f965856b6a491002d073d5b,\n is_infinite: false,\n },\n },\n tpk_m: TpkM {\n inner: Point {\n x: 0x00d3d81beb009873eb7116327cf47c612d5758ef083d4fda78e9b63980b2a762,\n y: 0x2f567d22d2b02fe1f4ad42db9d58a36afd1983e7e2909d1cab61cafedad6193a,\n is_infinite: false,\n },\n },\n };\n\n let partial_address = PartialAddress::from_field(\n 0x0a7c585381b10f4666044266a02405bf6e01fa564c8517d4ad5823493abd31de,\n );\n\n let address = AztecAddress::compute(public_keys, partial_address);\n\n // The following value was generated by `derivation.test.ts`.\n // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data.\n let expected_computed_address_from_partial_and_pubkeys =\n 0x24e4646f58b9fbe7d38e317db8d5636c423fbbdfbe119fc190fe9c64747e0c62;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkeys);\n}\n\n#[test]\nfn compute_preaddress_from_partial_and_pub_keys() {\n let pre_address = poseidon2_hash_with_separator([1, 2], GENERATOR_INDEX__CONTRACT_ADDRESS_V1);\n let expected_computed_preaddress_from_partial_and_pubkey =\n 0x23ce9be3fa3c846b0f9245cc796902e731d04f086e8a42473bb29e405fc98075;\n assert(pre_address == expected_computed_preaddress_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 // We use the AZTEC_ADDRESS_LENGTH constant to ensure that there is a match between the derived trait\n // implementation and the constant.\n let serialized: [Field; AZTEC_ADDRESS_LENGTH] = address.serialize();\n let deserialized = AztecAddress::deserialize(serialized);\n assert_eq(address, deserialized);\n}\n" + }, + "3": { + "path": "std/array/mod.nr", + "source": "use crate::cmp::{Eq, Ord};\nuse crate::convert::From;\nuse crate::runtime::is_unconstrained;\n\nmod check_shuffle;\nmod quicksort;\n\nimpl [T; N] {\n /// Returns the length of this array.\n ///\n /// ```noir\n /// fn len(self) -> Field\n /// ```\n ///\n /// example\n ///\n /// ```noir\n /// fn main() {\n /// let array = [42, 42];\n /// assert(array.len() == 2);\n /// }\n /// ```\n #[builtin(array_len)]\n pub fn len(self) -> u32 {}\n\n /// Returns this array as a slice.\n ///\n /// ```noir\n /// let array = [1, 2];\n /// let slice = array.as_slice();\n /// assert_eq(slice, &[1, 2]);\n /// ```\n #[builtin(as_slice)]\n pub fn as_slice(self) -> [T] {}\n\n /// Applies a function to each element of this array, returning a new array containing the mapped elements.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let b = a.map(|a| a * 2);\n /// assert_eq(b, [2, 4, 6]);\n /// ```\n pub fn map(self, f: fn[Env](T) -> U) -> [U; N] {\n let uninitialized = crate::mem::zeroed();\n let mut ret = [uninitialized; N];\n\n for i in 0..self.len() {\n ret[i] = f(self[i]);\n }\n\n ret\n }\n\n /// Applies a function to each element of this array along with its index,\n /// returning a new array containing the mapped elements.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let b = a.mapi(|i, a| i + a * 2);\n /// assert_eq(b, [2, 5, 8]);\n /// ```\n pub fn mapi(self, f: fn[Env](u32, T) -> U) -> [U; N] {\n let uninitialized = crate::mem::zeroed();\n let mut ret = [uninitialized; N];\n\n for i in 0..self.len() {\n ret[i] = f(i, self[i]);\n }\n\n ret\n }\n\n /// Applies a function to each element of this array.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let mut b = [0; 3];\n /// let mut i = 0;\n /// a.for_each(|x| {\n /// b[i] = x;\n /// i += 1;\n /// });\n /// assert_eq(a, b);\n /// ```\n pub fn for_each(self, f: fn[Env](T) -> ()) {\n for i in 0..self.len() {\n f(self[i]);\n }\n }\n\n /// Applies a function to each element of this array along with its index.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let mut b = [0; 3];\n /// a.for_eachi(|i, x| {\n /// b[i] = x;\n /// });\n /// assert_eq(a, b);\n /// ```\n pub fn for_eachi(self, f: fn[Env](u32, T) -> ()) {\n for i in 0..self.len() {\n f(i, self[i]);\n }\n }\n\n /// Applies a function to each element of the array, returning the final accumulated value. The first\n /// parameter is the initial value.\n ///\n /// This is a left fold, so the given function will be applied to the accumulator and first element of\n /// the array, then the second, and so on. For a given call the expected result would be equivalent to:\n ///\n /// ```rust\n /// let a1 = [1];\n /// let a2 = [1, 2];\n /// let a3 = [1, 2, 3];\n ///\n /// let f = |a, b| a - b;\n /// a1.fold(10, f); //=> f(10, 1)\n /// a2.fold(10, f); //=> f(f(10, 1), 2)\n /// a3.fold(10, f); //=> f(f(f(10, 1), 2), 3)\n ///\n /// assert_eq(a3.fold(10, f), 10 - 1 - 2 - 3);\n /// ```\n pub fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U {\n for elem in self {\n accumulator = f(accumulator, elem);\n }\n accumulator\n }\n\n /// Same as fold, but uses the first element as the starting element.\n ///\n /// Requires the input array to be non-empty.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr = [1, 2, 3, 4];\n /// let reduced = arr.reduce(|a, b| a + b);\n /// assert(reduced == 10);\n /// }\n /// ```\n pub fn reduce(self, f: fn[Env](T, T) -> T) -> T {\n let mut accumulator = self[0];\n for i in 1..self.len() {\n accumulator = f(accumulator, self[i]);\n }\n accumulator\n }\n\n /// Returns true if all the elements in this array satisfy the given predicate.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr = [2, 2, 2, 2, 2];\n /// let all = arr.all(|a| a == 2);\n /// assert(all);\n /// }\n /// ```\n pub fn all(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = true;\n for elem in self {\n ret &= predicate(elem);\n }\n ret\n }\n\n /// Returns true if any of the elements in this array satisfy the given predicate.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr = [2, 2, 2, 2, 5];\n /// let any = arr.any(|a| a == 5);\n /// assert(any);\n /// }\n /// ```\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n for elem in self {\n ret |= predicate(elem);\n }\n ret\n }\n\n /// Concatenates this array with another array.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr1 = [1, 2, 3, 4];\n /// let arr2 = [6, 7, 8, 9, 10, 11];\n /// let concatenated_arr = arr1.concat(arr2);\n /// assert(concatenated_arr == [1, 2, 3, 4, 6, 7, 8, 9, 10, 11]);\n /// }\n /// ```\n pub fn concat(self, array2: [T; M]) -> [T; N + M] {\n let mut result = [crate::mem::zeroed(); N + M];\n for i in 0..N {\n result[i] = self[i];\n }\n for i in 0..M {\n result[i + N] = array2[i];\n }\n result\n }\n}\n\nimpl [T; N]\nwhere\n T: Ord + Eq,\n{\n /// Returns a new sorted array. The original array remains untouched. Notice that this function will\n /// only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting\n /// logic it uses internally is optimized specifically for these values. If you need a sort function to\n /// sort any type, you should use the `sort_via` function.\n ///\n /// Example:\n ///\n /// ```rust\n /// fn main() {\n /// let arr = [42, 32];\n /// let sorted = arr.sort();\n /// assert(sorted == [32, 42]);\n /// }\n /// ```\n pub fn sort(self) -> Self {\n self.sort_via(|a, b| a <= b)\n }\n}\n\nimpl [T; N]\nwhere\n T: Eq,\n{\n /// Returns a new sorted array by sorting it with a custom comparison function.\n /// The original array remains untouched.\n /// The ordering function must return true if the first argument should be sorted to be before the second argument or is equal to the second argument.\n ///\n /// Using this method with an operator like `<` that does not return `true` for equal values will result in an assertion failure for arrays with equal elements.\n ///\n /// Example:\n ///\n /// ```rust\n /// fn main() {\n /// let arr = [42, 32]\n /// let sorted_ascending = arr.sort_via(|a, b| a <= b);\n /// assert(sorted_ascending == [32, 42]); // verifies\n ///\n /// let sorted_descending = arr.sort_via(|a, b| a >= b);\n /// assert(sorted_descending == [32, 42]); // does not verify\n /// }\n /// ```\n pub fn sort_via(self, ordering: fn[Env](T, T) -> bool) -> Self {\n // Safety: `sorted` array is checked to be:\n // a. a permutation of `input`'s elements\n // b. satisfying the predicate `ordering`\n let sorted = unsafe { quicksort::quicksort(self, ordering) };\n\n if !is_unconstrained() {\n for i in 0..N - 1 {\n assert(\n ordering(sorted[i], sorted[i + 1]),\n \"Array has not been sorted correctly according to `ordering`.\",\n );\n }\n check_shuffle::check_shuffle(self, sorted);\n }\n sorted\n }\n}\n\nimpl [u8; N] {\n /// Converts a byte array of type `[u8; N]` to a string. Note that this performs no UTF-8 validation -\n /// the given array is interpreted as-is as a string.\n ///\n /// Example:\n ///\n /// ```rust\n /// fn main() {\n /// let hi = [104, 105].as_str_unchecked();\n /// assert_eq(hi, \"hi\");\n /// }\n /// ```\n #[builtin(array_as_str_unchecked)]\n pub fn as_str_unchecked(self) -> str {}\n}\n\nimpl From> for [u8; N] {\n /// Returns an array of the string bytes.\n fn from(s: str) -> Self {\n s.as_bytes()\n }\n}\n\nmod test {\n #[test]\n fn map_empty() {\n assert_eq([].map(|x| x + 1), []);\n }\n\n global arr_with_100_values: [u32; 100] = [\n 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2, 54,\n 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41, 19, 98,\n 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21, 43, 86, 35,\n 21, 62, 82, 0, 108, 120, 72, 72, 62, 80, 12, 71, 70, 86, 116, 73, 38, 15, 127, 81, 30, 8,\n 125, 28, 26, 69, 114, 63, 27, 28, 61, 42, 13, 32,\n ];\n global expected_with_100_values: [u32; 100] = [\n 0, 0, 2, 3, 5, 6, 8, 12, 13, 13, 15, 19, 19, 19, 21, 21, 26, 26, 27, 28, 28, 28, 29, 30, 32,\n 32, 35, 37, 38, 41, 42, 42, 42, 43, 44, 44, 45, 47, 48, 48, 50, 50, 53, 54, 54, 58, 61, 62,\n 62, 63, 64, 66, 66, 68, 69, 70, 70, 71, 71, 72, 72, 73, 74, 80, 80, 81, 81, 82, 84, 84, 86,\n 86, 87, 89, 89, 89, 93, 95, 96, 98, 100, 104, 105, 106, 107, 108, 109, 114, 114, 116, 118,\n 119, 120, 121, 123, 123, 123, 125, 126, 127,\n ];\n fn sort_u32(a: u32, b: u32) -> bool {\n a <= b\n }\n\n #[test]\n fn test_sort() {\n let mut arr: [u32; 7] = [3, 6, 8, 10, 1, 2, 1];\n\n let sorted = arr.sort();\n\n let expected: [u32; 7] = [1, 1, 2, 3, 6, 8, 10];\n assert(sorted == expected);\n }\n\n #[test]\n fn test_sort_100_values() {\n let mut arr: [u32; 100] = [\n 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2,\n 54, 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41,\n 19, 98, 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21,\n 43, 86, 35, 21, 62, 82, 0, 108, 120, 72, 72, 62, 80, 12, 71, 70, 86, 116, 73, 38, 15,\n 127, 81, 30, 8, 125, 28, 26, 69, 114, 63, 27, 28, 61, 42, 13, 32,\n ];\n\n let sorted = arr.sort();\n\n let expected: [u32; 100] = [\n 0, 0, 2, 3, 5, 6, 8, 12, 13, 13, 15, 19, 19, 19, 21, 21, 26, 26, 27, 28, 28, 28, 29, 30,\n 32, 32, 35, 37, 38, 41, 42, 42, 42, 43, 44, 44, 45, 47, 48, 48, 50, 50, 53, 54, 54, 58,\n 61, 62, 62, 63, 64, 66, 66, 68, 69, 70, 70, 71, 71, 72, 72, 73, 74, 80, 80, 81, 81, 82,\n 84, 84, 86, 86, 87, 89, 89, 89, 93, 95, 96, 98, 100, 104, 105, 106, 107, 108, 109, 114,\n 114, 116, 118, 119, 120, 121, 123, 123, 123, 125, 126, 127,\n ];\n assert(sorted == expected);\n }\n\n #[test]\n fn test_sort_100_values_comptime() {\n let sorted = arr_with_100_values.sort();\n assert(sorted == expected_with_100_values);\n }\n\n #[test]\n fn test_sort_via() {\n let mut arr: [u32; 7] = [3, 6, 8, 10, 1, 2, 1];\n\n let sorted = arr.sort_via(sort_u32);\n\n let expected: [u32; 7] = [1, 1, 2, 3, 6, 8, 10];\n assert(sorted == expected);\n }\n\n #[test]\n fn test_sort_via_100_values() {\n let mut arr: [u32; 100] = [\n 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2,\n 54, 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41,\n 19, 98, 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21,\n 43, 86, 35, 21, 62, 82, 0, 108, 120, 72, 72, 62, 80, 12, 71, 70, 86, 116, 73, 38, 15,\n 127, 81, 30, 8, 125, 28, 26, 69, 114, 63, 27, 28, 61, 42, 13, 32,\n ];\n\n let sorted = arr.sort_via(sort_u32);\n\n let expected: [u32; 100] = [\n 0, 0, 2, 3, 5, 6, 8, 12, 13, 13, 15, 19, 19, 19, 21, 21, 26, 26, 27, 28, 28, 28, 29, 30,\n 32, 32, 35, 37, 38, 41, 42, 42, 42, 43, 44, 44, 45, 47, 48, 48, 50, 50, 53, 54, 54, 58,\n 61, 62, 62, 63, 64, 66, 66, 68, 69, 70, 70, 71, 71, 72, 72, 73, 74, 80, 80, 81, 81, 82,\n 84, 84, 86, 86, 87, 89, 89, 89, 93, 95, 96, 98, 100, 104, 105, 106, 107, 108, 109, 114,\n 114, 116, 118, 119, 120, 121, 123, 123, 123, 125, 126, 127,\n ];\n assert(sorted == expected);\n }\n\n #[test]\n fn mapi_empty() {\n assert_eq([].mapi(|i, x| i * x + 1), []);\n }\n\n #[test]\n fn for_each_empty() {\n let empty_array: [Field; 0] = [];\n empty_array.for_each(|_x| assert(false));\n }\n\n #[test]\n fn for_eachi_empty() {\n let empty_array: [Field; 0] = [];\n empty_array.for_eachi(|_i, _x| assert(false));\n }\n\n #[test]\n fn map_example() {\n let a = [1, 2, 3];\n let b = a.map(|a| a * 2);\n assert_eq(b, [2, 4, 6]);\n }\n\n #[test]\n fn mapi_example() {\n let a = [1, 2, 3];\n let b = a.mapi(|i, a| i + a * 2);\n assert_eq(b, [2, 5, 8]);\n }\n\n #[test]\n fn for_each_example() {\n let a = [1, 2, 3];\n let mut b = [0, 0, 0];\n let b_ref = &mut b;\n let mut i = 0;\n let i_ref = &mut i;\n a.for_each(|x| {\n b_ref[*i_ref] = x * 2;\n *i_ref += 1;\n });\n assert_eq(b, [2, 4, 6]);\n assert_eq(i, 3);\n }\n\n #[test]\n fn for_eachi_example() {\n let a = [1, 2, 3];\n let mut b = [0, 0, 0];\n let b_ref = &mut b;\n a.for_eachi(|i, a| { b_ref[i] = i + a * 2; });\n assert_eq(b, [2, 5, 8]);\n }\n\n #[test]\n fn concat() {\n let arr1 = [1, 2, 3, 4];\n let arr2 = [6, 7, 8, 9, 10, 11];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, [1, 2, 3, 4, 6, 7, 8, 9, 10, 11]);\n }\n\n #[test]\n fn concat_zero_length_with_something() {\n let arr1 = [];\n let arr2 = [1];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, [1]);\n }\n\n #[test]\n fn concat_something_with_zero_length() {\n let arr1 = [1];\n let arr2 = [];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, [1]);\n }\n\n #[test]\n fn concat_zero_lengths() {\n let arr1: [Field; 0] = [];\n let arr2: [Field; 0] = [];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, []);\n }\n}\n" + }, + "307": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr", + "source": "/// Utility function to console.log data in the acir simulator.\n/// Example:\n/// debug_log(\"blah blah this is a debug string\");\npub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n\n/// Utility function to console.log data in the acir simulator. This variant receives a format string in which the\n/// `${k}` tokens will be replaced with the k-eth value in the `args` array.\n/// Examples:\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]);\npub fn debug_log_format(msg: str, args: [Field; N]) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe { debug_log_oracle_wrapper(msg, args) };\n}\n\npub unconstrained fn debug_log_oracle_wrapper(\n msg: str,\n args: [Field; N],\n) {\n debug_log_oracle(msg, args.as_slice());\n}\n\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#[oracle(utilityDebugLog)]\nunconstrained fn debug_log_oracle(_msg: str, args: [Field]) {}\n" + }, + "316": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/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,\n note_hash::ScopedNoteHash,\n nullifier::ScopedNullifier,\n private_log::{PrivateLog, PrivateLogData},\n side_effect::{OrderedValue, scoped::Scoped},\n },\n address::{AztecAddress, EthAddress},\n constants::{\n CONTRACT_CLASS_LOG_SIZE_IN_FIELDS, FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__NOTE_HASH_NONCE,\n GENERATOR_INDEX__OUTER_NULLIFIER, GENERATOR_INDEX__SILOED_NOTE_HASH,\n GENERATOR_INDEX__UNIQUE_NOTE_HASH, TWO_POW_64,\n },\n merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::L2ToL1Message,\n poseidon2::Poseidon2Sponge,\n traits::{FromField, Hash, ToField},\n utils::field::{field_from_bytes, field_from_bytes_32_trunc},\n};\nuse std::embedded_curve_ops::EmbeddedCurveScalar;\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256::digest(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(\n function_leaf,\n function_leaf_index,\n function_leaf_sibling_path,\n )\n}\n\npub fn compute_note_hash_nonce(first_nullifier_in_tx: Field, note_index_in_tx: u32) -> Field {\n // Hashing the first nullifier with note index in tx is guaranteed to be unique (because all nullifiers are also\n // unique).\n poseidon2_hash_with_separator(\n [first_nullifier_in_tx, note_index_in_tx as Field],\n GENERATOR_INDEX__NOTE_HASH_NONCE,\n )\n}\n\npub fn compute_unique_note_hash(note_nonce: Field, siloed_note_hash: Field) -> Field {\n let inputs = [note_nonce, siloed_note_hash];\n poseidon2_hash_with_separator(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_nonce_and_unique_note_hash(\n siloed_note_hash: Field,\n first_nullifier: Field,\n note_index_in_tx: u32,\n) -> Field {\n let note_nonce = compute_note_hash_nonce(first_nullifier, note_index_in_tx);\n compute_unique_note_hash(note_nonce, siloed_note_hash)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, note_hash: Field) -> Field {\n poseidon2_hash_with_separator(\n [app.to_field(), note_hash],\n GENERATOR_INDEX__SILOED_NOTE_HASH,\n )\n}\n\n/// Computes unique note hashes from siloed note hashes\npub fn compute_unique_siloed_note_hash(\n siloed_note_hash: Field,\n first_nullifier: Field,\n note_index_in_tx: u32,\n) -> Field {\n if siloed_note_hash == 0 {\n 0\n } else {\n compute_nonce_and_unique_note_hash(siloed_note_hash, first_nullifier, note_index_in_tx)\n }\n}\n\n/// Siloing in the context of Aztec refers to the process of hashing a note hash with a contract address (this way\n/// the note hash is scoped to a specific contract). This is used to prevent intermingling of notes between contracts.\npub fn silo_note_hash(note_hash: ScopedNoteHash) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_note_hash(note_hash.contract_address, note_hash.value())\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n poseidon2_hash_with_separator(\n [app.to_field(), nullifier],\n GENERATOR_INDEX__OUTER_NULLIFIER,\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n // Q: shouldn't we be checking whether the _whole_ nullifier is empty?\n // A: We don't have to. The init and inner circuits add contract address to non-empty nullifiers.\n // So we know we should silo it if the contract address is not empty.\n if nullifier.contract_address.is_zero() {\n // Q: I don't understand this comment. We could still compute a siloed nullifier from a zero contract address.\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_private_log_field(contract_address: AztecAddress, field: Field) -> Field {\n poseidon2_hash([contract_address.to_field(), field])\n}\n\npub fn silo_private_log(private_log: Scoped) -> PrivateLog {\n if private_log.contract_address.is_zero() {\n private_log.inner.log\n } else {\n let mut fields = private_log.inner.log.fields;\n fields[0] = compute_siloed_private_log_field(private_log.contract_address, fields[0]);\n PrivateLog::new(fields, private_log.inner.log.length)\n }\n}\n\npub fn compute_contract_class_log_hash(log: [Field; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS]) -> Field {\n poseidon2_hash(log)\n}\n\npub fn compute_app_secret_key(\n master_secret_key: EmbeddedCurveScalar,\n app_address: AztecAddress,\n app_secret_generator: Field,\n) -> Field {\n poseidon2_hash_with_separator(\n [master_secret_key.hi, master_secret_key.lo, app_address.to_field()],\n app_secret_generator,\n )\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n poseidon2_hash([left, right])\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 contract_address_bytes: [u8; 32] = contract_address.to_field().to_be_bytes();\n let recipient_bytes: [u8; 20] = recipient.to_be_bytes();\n let content_bytes: [u8; 32] = content.to_be_bytes();\n let rollup_version_id_bytes: [u8; 32] = rollup_version_id.to_be_bytes();\n let chain_id_bytes: [u8; 32] = chain_id.to_be_bytes();\n\n let mut bytes: [u8; 148] = std::mem::zeroed();\n for i in 0..32 {\n bytes[i] = contract_address_bytes[i];\n bytes[i + 32] = rollup_version_id_bytes[i];\n // 64 - 84 are for recipient.\n bytes[i + 84] = chain_id_bytes[i];\n bytes[i + 116] = content_bytes[i];\n }\n\n for i in 0..20 {\n bytes[64 + i] = recipient_bytes[i];\n }\n\n sha256_to_field(bytes)\n}\n\npub fn silo_l2_to_l1_message(\n msg: Scoped,\n rollup_version_id: Field,\n chain_id: Field,\n) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.inner.recipient,\n msg.inner.content,\n rollup_version_id,\n chain_id,\n )\n }\n}\n\n/// Computes sha256 hash of 2 input fields.\n///\n/// @returns A truncated field (i.e., the first byte is always 0).\npub fn accumulate_sha256(v0: Field, v1: Field) -> Field {\n // Concatenate two fields into 32 x 2 = 64 bytes\n let v0_as_bytes: [u8; 32] = v0.to_be_bytes();\n let v1_as_bytes: [u8; 32] = v1.to_be_bytes();\n let hash_input_flattened = v0_as_bytes.concat(v1_as_bytes);\n\n sha256_to_field(hash_input_flattened)\n}\n\n#[inline_always]\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n poseidon::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[no_predicates]\npub fn poseidon2_hash_with_separator(inputs: [Field; N], separator: T) -> Field\nwhere\n T: ToField,\n{\n let inputs_with_separator = [separator.to_field()].concat(inputs);\n poseidon2_hash(inputs_with_separator)\n}\n\n// Performs a fixed length hash with a subarray of the given input.\n// Useful for SpongeBlob in which we aborb M things and want to check it vs a hash of M elts of an N-len array.\n// Using stdlib poseidon, this will always absorb an extra 1 as a 'variable' hash, and not match spongeblob.squeeze()\n// or any ts implementation. Also checks that any remaining elts not hashed are empty.\n#[no_predicates]\npub fn poseidon2_hash_subarray(input: [Field; N], in_len: u32) -> Field {\n let mut sponge = poseidon2_absorb_chunks(input, in_len, false);\n sponge.squeeze()\n}\n\n// NB the below is the same as poseidon::poseidon2::Poseidon2::hash(), but replacing a range check with a bit check,\n// and absorbing in chunks of 3 below.\n#[no_predicates]\npub fn poseidon2_cheaper_variable_hash(input: [Field; N], in_len: u32) -> Field {\n let mut sponge = poseidon2_absorb_chunks(input, in_len, true);\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 in_len != N {\n sponge.absorb(1);\n }\n sponge.squeeze()\n}\n\n// The below fn reduces gates of a conditional poseidon2 hash by approx 3x (thank you ~* Giant Brain Dev @IlyasRidhuan *~ for the idea)\n// Why? Because when we call stdlib poseidon, we call absorb for each item. When absorbing is conditional, it seems the compiler does not know\n// what cache_size will be when calling absorb, so it assigns the permutation gates for /each i/ rather than /every 3rd i/, which is actually required.\n// The below code forces the compiler to:\n// - absorb normally up to 2 times to set cache_size to 1\n// - absorb in chunks of 3 to ensure perm. only happens every 3rd absorb\n// - absorb normally up to 2 times to add any remaining values to the hash\n// In fixed len hashes, the compiler is able to tell that it will only need to perform the permutation every 3 absorbs.\n// NB: it also replaces unnecessary range checks (i < thing) with a bit check (&= i != thing), which alone reduces the gates of a var. hash by half.\n\n#[no_predicates]\nfn poseidon2_absorb_chunks(\n input: [Field; N],\n in_len: u32,\n variable: bool,\n) -> Poseidon2Sponge {\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::new(iv);\n // Even though shift is always 1 here, if we input in_len = 0 we get an underflow\n // since we cannot isolate computation branches. The below is just to avoid that.\n let shift = if in_len == 0 { 0 } else { 1 };\n if in_len != 0 {\n // cache_size = 0, init absorb\n sponge.cache[0] = input[0];\n sponge.cache_size = 1;\n // shift = num elts already added to make cache_size 1 = 1 for a fresh sponge\n // M = max_chunks = (N - 1 - (N - 1) % 3) / 3: (must be written as a fn of N to compile)\n // max_remainder = (N - 1) % 3;\n // max_chunks = (N - 1 - max_remainder) / 3;\n sponge = poseidon2_absorb_chunks_loop::(\n sponge,\n input,\n in_len,\n variable,\n shift,\n );\n }\n sponge\n}\n\n// NB: If it's not required to check that the non-absorbed elts of 'input' are 0s, set skip_0_check=true\n#[no_predicates]\npub fn poseidon2_absorb_chunks_existing_sponge(\n in_sponge: Poseidon2Sponge,\n input: [Field; N],\n in_len: u32,\n skip_0_check: bool,\n) -> Poseidon2Sponge {\n let mut sponge = in_sponge;\n // 'shift' is to account for already added inputs\n let mut shift = 0;\n // 'stop' is to avoid an underflow when inputting in_len = 0\n let mut stop = false;\n for i in 0..3 {\n if shift == in_len {\n stop = true;\n }\n if (sponge.cache_size != 1) & (!stop) {\n sponge.absorb(input[i]);\n shift += 1;\n }\n }\n sponge = if stop {\n sponge\n } else {\n // max_chunks = (N - (N % 3)) / 3;\n poseidon2_absorb_chunks_loop::(\n sponge,\n input,\n in_len,\n skip_0_check,\n shift,\n )\n };\n sponge\n}\n\n// The below is the loop to absorb elts into a poseidon sponge in chunks of 3\n// shift - the num of elts already absorbed to ensure the sponge's cache_size = 1\n// M - the max number of chunks required to absorb N things (must be comptime to compile)\n// NB: The 0 checks ('Found non-zero field...') are messy, but having a separate loop over N to check\n// for 0s costs 3N gates. Current approach is approx 2N gates.\n#[no_predicates]\nfn poseidon2_absorb_chunks_loop(\n in_sponge: Poseidon2Sponge,\n input: [Field; N],\n in_len: u32,\n variable: bool,\n shift: u32,\n) -> Poseidon2Sponge {\n assert(in_len <= N, \"Given in_len to absorb is larger than the input array len\");\n // When we have an existing sponge, we may have a shift of 0, and the final 'k+2' below = N\n // The below avoids an overflow\n let skip_last = 3 * M == N;\n // Writing in_sponge: &mut does not compile\n let mut sponge = in_sponge;\n let mut should_add = true;\n // The num of things left over after absorbing in 3s\n let remainder = (in_len - shift) % 3;\n // The num of chunks of 3 to absorb (maximum M)\n let chunks = (in_len - shift - remainder) / 3;\n for i in 0..M {\n // Now we loop through cache size = 1 -> 3\n should_add &= i != chunks;\n // This is the index at the start of the chunk (for readability)\n let k = 3 * i + shift;\n if should_add {\n // cache_size = 1, 2 => just assign\n sponge.cache[1] = input[k];\n sponge.cache[2] = input[k + 1];\n // cache_size = 3 => duplex + perm\n for j in 0..3 {\n sponge.state[j] += sponge.cache[j];\n }\n sponge.state = std::hash::poseidon2_permutation(sponge.state, 4);\n sponge.cache[0] = input[k + 2];\n // cache_size is now 1 again, repeat loop\n } else if (!variable) & (i != chunks) {\n // if we are hashing a fixed len array which is a subarray, we check the remaining elts are 0\n // NB: we don't check at i == chunks, because that chunk contains elts to be absorbed or checked below\n let last_0 = if (i == M - 1) & (skip_last) {\n 0\n } else {\n input[k + 2]\n };\n let all_0 = (input[k] == 0) & (input[k + 1] == 0) & (last_0 == 0);\n assert(all_0, \"Found non-zero field after breakpoint\");\n }\n }\n // we have 'remainder' num of items left to absorb\n should_add = true;\n // below is to avoid overflows (i.e. if inlen is close to N)\n let mut should_check = !variable;\n for i in 0..3 {\n should_add &= i != remainder;\n should_check &= in_len - remainder + i != N;\n if should_add {\n // we want to absorb the final 'remainder' items\n sponge.absorb(input[in_len - remainder + i]);\n } else if should_check {\n assert_eq(input[in_len - remainder + i], 0, \"Found non-zero field after breakpoint\");\n }\n }\n sponge\n}\n\npub fn poseidon2_hash_with_separator_slice(inputs: [Field], separator: T) -> Field\nwhere\n T: ToField,\n{\n let in_len = inputs.len() + 1;\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::new(iv);\n sponge.absorb(separator.to_field());\n\n for i in 0..inputs.len() {\n sponge.absorb(inputs[i]);\n }\n\n sponge.squeeze()\n}\n\n// This function is unconstrained because it is intended to be used in unconstrained context only as\n// in constrained contexts it would be too inefficient.\npub unconstrained fn poseidon2_hash_with_separator_bounded_vec(\n inputs: BoundedVec,\n separator: T,\n) -> Field\nwhere\n T: ToField,\n{\n let in_len = inputs.len() + 1;\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::new(iv);\n sponge.absorb(separator.to_field());\n\n for i in 0..inputs.len() {\n sponge.absorb(inputs.get(i));\n }\n\n sponge.squeeze()\n}\n\n#[no_predicates]\npub fn poseidon2_hash_bytes(inputs: [u8; N]) -> Field {\n let mut fields = [0; (N + 30) / 31];\n let mut field_index = 0;\n let mut current_field = [0; 31];\n for i in 0..inputs.len() {\n let index = i % 31;\n current_field[index] = inputs[i];\n if index == 30 {\n fields[field_index] = field_from_bytes(current_field, false);\n current_field = [0; 31];\n field_index += 1;\n }\n }\n if field_index != fields.len() {\n fields[field_index] = field_from_bytes(current_field, false);\n }\n poseidon2_hash(fields)\n}\n\n#[test]\nfn poseidon_chunks_matches_fixed() {\n let in_len = 501;\n let mut input: [Field; 4096] = [0; 4096];\n let mut fixed_input = [3; 501];\n assert(in_len == fixed_input.len()); // sanity check\n for i in 0..in_len {\n input[i] = 3;\n }\n let sub_chunk_hash = poseidon2_hash_subarray(input, in_len);\n let fixed_len_hash = poseidon::poseidon2::Poseidon2::hash(fixed_input, fixed_input.len());\n assert(sub_chunk_hash == fixed_len_hash);\n}\n\n#[test]\nfn poseidon_chunks_matches_variable() {\n let in_len = 501;\n let mut input: [Field; 4096] = [0; 4096];\n for i in 0..in_len {\n input[i] = 3;\n }\n let variable_chunk_hash = poseidon2_cheaper_variable_hash(input, in_len);\n let variable_len_hash = poseidon::poseidon2::Poseidon2::hash(input, in_len);\n assert(variable_chunk_hash == variable_len_hash);\n}\n\n#[test]\nfn existing_sponge_poseidon_chunks_matches_fixed() {\n let in_len = 501;\n let mut input: [Field; 4096] = [0; 4096];\n let mut fixed_input = [3; 501];\n assert(in_len == fixed_input.len()); // sanity check\n for i in 0..in_len {\n input[i] = 3;\n }\n // absorb 250 of the 501 things\n let empty_sponge = Poseidon2Sponge::new((in_len as Field) * TWO_POW_64);\n let first_sponge = poseidon2_absorb_chunks_existing_sponge(empty_sponge, input, 250, true);\n // now absorb the final 251 (since they are all 3s, im being lazy and not making a new array)\n let mut final_sponge = poseidon2_absorb_chunks_existing_sponge(first_sponge, input, 251, true);\n let fixed_len_hash = Poseidon2Sponge::hash(fixed_input, fixed_input.len());\n assert(final_sponge.squeeze() == fixed_len_hash);\n}\n\n#[test]\nfn poseidon_chunks_empty_inputs() {\n let in_len = 0;\n let mut input: [Field; 4096] = [0; 4096];\n let mut constructed_empty_sponge = poseidon2_absorb_chunks(input, in_len, true);\n let mut first_sponge =\n poseidon2_absorb_chunks_existing_sponge(constructed_empty_sponge, input, in_len, true);\n assert(first_sponge.squeeze() == constructed_empty_sponge.squeeze());\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, 20, 21, 22, 23, 24,\n 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\n 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,\n 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,\n 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,\n 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,\n 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,\n 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::digest(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 =\n compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0x3b18c58c739716e76429634a61375c45b3b5cd470c22ab6d3e14cee23dd992);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(\n AztecAddress::from_field(1),\n EthAddress::from_field(3),\n 5,\n 2,\n 4,\n );\n assert(hash_result == 0xaab2a5828156782b12a1dc6f336e2bc627eb1b9514b02d511f66296990c050);\n}\n\n#[test]\nfn silo_l2_to_l1_message_matches_typescript() {\n let version = 4;\n let chainId = 5;\n\n let hash = silo_l2_to_l1_message(\n L2ToL1Message { recipient: EthAddress::from_field(1), content: 2 }.scope(\n AztecAddress::from_field(3),\n ),\n version,\n chainId,\n );\n\n // The following value was generated by `yarn-project/stdlib/src/hash/hash.test.ts`\n let hash_from_typescript = 0x0081edf209e087ad31b3fd24263698723d57190bd1d6e9fe056fc0c0a68ee661;\n\n assert_eq(hash, hash_from_typescript);\n}\n\n#[test]\nunconstrained fn poseidon2_hash_with_separator_bounded_vec_matches_non_bounded_vec_version() {\n let inputs = BoundedVec::::from_array([1, 2, 3]);\n let separator = 42;\n\n // Hash using bounded vec version\n let bounded_result = poseidon2_hash_with_separator_bounded_vec(inputs, separator);\n\n // Hash using regular version\n let regular_result = poseidon2_hash_with_separator([1, 2, 3], separator);\n\n // Results should match\n assert_eq(bounded_result, regular_result);\n}\n" + }, + "330": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/meta/mod.nr", + "source": "/// Generates the generic parameter declarations for a struct's trait implementation.\n///\n/// This function takes a struct type definition and generates the generic parameter declarations\n/// that go after the `impl` keyword. For example, given a struct with generics `N: u32` and `T`,\n/// it generates ``.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate generic declarations for\n///\n/// # Returns\n/// A quoted code block containing the generic parameter declarations, or an empty quote if the struct\n/// has no generic parameters\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Container {\n/// items: [T; N],\n/// count: u32\n/// }\n/// ```\n///\n/// This function generates:\n/// ```\n/// \n/// ```\ncomptime fn get_generics_declarations(s: TypeDefinition) -> Quoted {\n let generics = s.generics();\n\n if generics.len() > 0 {\n let generics_declarations_items = generics\n .map(|(name, maybe_integer_typ)| {\n // The second item in the generics tuple is an Option of an integer type that is Some only if\n // the generic is numeric.\n if maybe_integer_typ.is_some() {\n // The generic is numeric, so we return a quote defined as e.g. \"let N: u32\"\n let integer_type = maybe_integer_typ.unwrap();\n quote {let $name: $integer_type}\n } else {\n // The generic is not numeric, so we return a quote containing the name of the generic (e.g. \"T\")\n quote {$name}\n }\n })\n .join(quote {,});\n quote {<$generics_declarations_items>}\n } else {\n // The struct doesn't have any generics defined, so we just return an empty quote.\n quote {}\n }\n}\n\n/// Generates the `where` clause for a trait implementation that constrains non-numeric generic type parameters.\n///\n/// This function takes a struct type definition and a trait name, and generates a `where` clause that\n/// requires all non-numeric generic type parameters to implement the specified trait.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate the where clause for\n/// - `trait_name`: The name of the trait that non-numeric generic parameters must implement\n///\n/// # Returns\n/// A quoted code block containing the where clause, or an empty quote if the struct has no non-numeric\n/// generic parameters\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Container {\n/// items: [T; N],\n/// count: u32\n/// }\n/// ```\n///\n/// And trait name \"Serialize\", this function generates:\n/// ```\n/// where T: Serialize\n/// ```\ncomptime fn get_where_trait_clause(s: TypeDefinition, trait_name: Quoted) -> Quoted {\n let generics = s.generics();\n\n // The second item in the generics tuple is an Option of an integer type that is Some only if the generic is\n // numeric.\n let non_numeric_generics =\n generics.filter(|(_, maybe_integer_typ)| maybe_integer_typ.is_none());\n\n if non_numeric_generics.len() > 0 {\n let non_numeric_generics_declarations =\n non_numeric_generics.map(|(name, _)| quote {$name: $trait_name}).join(quote {,});\n quote {where $non_numeric_generics_declarations}\n } else {\n // There are no non-numeric generics, so we return an empty quote.\n quote {}\n }\n}\n\n/// Generates a `Serialize` trait implementation for a struct type.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A quoted code block containing the trait implementation\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Log {\n/// fields: [Field; N],\n/// length: u32\n/// }\n/// ```\n///\n/// This function generates code equivalent to:\n/// ```\n/// impl Serialize for Log {\n/// let N: u32 = <[Field; N] as Serialize>::N + ::N;\n///\n/// #[inline_always]\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut result = [0; _];\n/// let mut offset = 0;\n///\n/// let serialized_member = Serialize::serialize(self.fields);\n/// let serialized_member_len = <[Field; N] as Serialize>::N;\n/// for i in 0..serialized_member_len {\n/// result[i + offset] = serialized_member[i];\n/// }\n/// offset += serialized_member_len;\n///\n/// let serialized_member = Serialize::serialize(self.length);\n/// let serialized_member_len = ::N;\n/// for i in 0..serialized_member_len {\n/// result[i + offset] = serialized_member[i];\n/// }\n/// offset += serialized_member_len;\n///\n/// result\n/// }\n/// }\n/// ```\npub comptime fn derive_serialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.0.fields(nested_struct.1);\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Serialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_serialize_clause = get_where_trait_clause(s, quote {Serialize});\n\n // The following will give us ::N + ::N + ...\n let right_hand_side_of_definition_of_n = params\n .map(|(_, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n <$param_type as $crate::traits::Serialize>::N\n }\n })\n .join(quote {+});\n\n // For structs containing a single member, we can enhance performance by directly returning the serialized member,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let function_body = if params.len() > 1 {\n // For multiple struct members, generate serialization code that:\n // 1. Serializes each member\n // 2. Copies the serialized fields into the result array at the correct offset\n // 3. Updates the offset for the next member\n let serialization_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let serialized_member = $crate::traits::Serialize::serialize(self.$param_name);\n let serialized_member_len = <$param_type as $crate::traits::Serialize>::N;\n for i in 0..serialized_member_len {\n result[i + offset] = serialized_member[i];\n }\n offset += serialized_member_len;\n }\n })\n .join(quote {});\n\n quote {\n let mut result = [0; _];\n let mut offset = 0;\n\n $serialization_of_struct_members\n\n result\n }\n } else {\n let param_name = params[0].0;\n quote {\n $crate::traits::Serialize::serialize(self.$param_name)\n }\n };\n\n quote {\n impl$generics_declarations $crate::traits::Serialize for $typ\n $where_serialize_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n $function_body\n }\n }\n }\n}\n\n/// Generates a `Deserialize` trait implementation for a given struct `s`.\n///\n/// # Arguments\n/// * `s` - The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A `Quoted` block containing the generated trait implementation\n///\n/// # Requirements\n/// Each struct member type must implement the `Deserialize` trait (it gets used in the generated code).\n///\n/// # Example\n/// For a struct like:\n/// ```\n/// struct MyStruct {\n/// x: AztecAddress,\n/// y: Field,\n/// }\n/// ```\n///\n/// This generates:\n/// ```\n/// impl Deserialize for MyStruct {\n/// let N: u32 = ::N + ::N;\n///\n/// fn deserialize(serialized: [Field; Self::N]) -> Self {\n/// let mut offset = 0;\n/// let mut member_fields = [0; ::N];\n/// for i in 0..::N {\n/// member_fields[i] = serialized[i + offset];\n/// }\n/// let x = ::deserialize(member_fields);\n/// offset += ::N;\n///\n/// let mut member_fields = [0; ::N];\n/// for i in 0..::N {\n/// member_fields[i] = serialized[i + offset];\n/// }\n/// let y = ::deserialize(member_fields);\n/// offset += ::N;\n///\n/// Self { x, y }\n/// }\n/// }\n/// ```\npub(crate) comptime fn derive_deserialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.0.fields(nested_struct.1);\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Deserialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_deserialize_clause = get_where_trait_clause(s, quote {Deserialize});\n\n // The following will give us ::N + ::N + ...\n let right_hand_side_of_definition_of_n = params\n .map(|(_, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n <$param_type as $crate::traits::Deserialize>::N\n }\n })\n .join(quote {+});\n\n // For structs containing a single member, we can enhance performance by directly deserializing the input array,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let function_body = if params.len() > 1 {\n // This generates deserialization code for each struct member and concatenates them together.\n let deserialization_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let mut member_fields = [0; <$param_type as Deserialize>::N];\n for i in 0..<$param_type as Deserialize>::N {\n member_fields[i] = serialized[i + offset];\n }\n let $param_name = <$param_type as Deserialize>::deserialize(member_fields);\n offset += <$param_type as Deserialize>::N;\n }\n })\n .join(quote {});\n\n // We join the struct member names with a comma to be used in the `Self { ... }` syntax\n // This will give us e.g. `a, b, c` for a struct with three fields named `a`, `b`, and `c`.\n let struct_members = params\n .map(|(param_name, _, _): (Quoted, Type, Quoted)| quote { $param_name })\n .join(quote {,});\n\n quote {\n let mut offset = 0;\n\n $deserialization_of_struct_members\n\n Self { $struct_members }\n }\n } else {\n let param_name = params[0].0;\n quote {\n Self { $param_name: $crate::traits::Deserialize::deserialize(serialized) }\n }\n };\n\n quote {\n impl$generics_declarations $crate::traits::Deserialize for $typ\n $where_deserialize_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n #[inline_always]\n fn deserialize(serialized: [Field; Self::N]) -> Self {\n $function_body\n }\n }\n }\n}\n\n/// Generates a `Packable` trait implementation for a given struct `s`.\n///\n/// # Arguments\n/// * `s` - The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A `Quoted` block containing the generated trait implementation\n///\n/// # Requirements\n/// Each struct member type must implement the `Packable` trait (it gets used in the generated code).\n///\n/// # Example\n/// For a struct like:\n/// ```\n/// struct MyStruct {\n/// x: AztecAddress,\n/// y: Field,\n/// }\n/// ```\n///\n/// This generates:\n/// ```\n/// impl Packable for MyStruct {\n/// let N: u32 = 2;\n///\n/// fn pack(self) -> [Field; 2] {\n/// let mut result: [Field; 2] = [0_Field; 2];\n/// let mut offset: u32 = 0_u32;\n/// let packed_member: [Field; 1] = self.x.pack();\n/// let packed_member_len: u32 = ::N;\n/// for i in 0_u32..packed_member_len {\n/// {\n/// result[i + offset] = packed_member[i];\n/// }\n/// }\n/// offset = offset + packed_member_len;\n/// let packed_member: [Field; 1] = self.y.pack();\n/// let packed_member_len: u32 = ::N;\n/// for i in 0_u32..packed_member_len {\n/// {\n/// result[i + offset] = packed_member[i];\n/// }\n/// }\n/// offset = offset + packed_member_len;\n/// result\n/// }\n///\n/// fn unpack(packed: [Field; 2]) -> Self {\n/// let mut offset: u32 = 0_u32;\n/// let mut member_fields: [Field; 1] = [0_Field; 1];\n/// for i in 0_u32..::N {\n/// member_fields[i] = packed[i + offset];\n/// }\n/// let x: AztecAddress = ::unpack(member_fields);\n/// offset = offset + ::N;\n/// let mut member_fields: [Field; 1] = [0_Field; 1];\n/// for i in 0_u32..::N {\n/// member_fields[i] = packed[i + offset];\n/// }\n/// let y: Field = ::unpack(member_fields);\n/// offset = offset + ::N;\n/// Self { x: x, y: y }\n/// }\n/// }\n/// ```\npub comptime fn derive_packable(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.0.fields(nested_struct.1);\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Packable` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_packable_clause = get_where_trait_clause(s, quote {Packable});\n\n // The following will give us ::N + ::N + ...\n let right_hand_side_of_definition_of_n = params\n .map(|(_, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n <$param_type as $crate::traits::Packable>::N\n }\n })\n .join(quote {+});\n\n // For structs containing a single member, we can enhance performance by directly returning the packed member,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let pack_function_body = if params.len() > 1 {\n // For multiple struct members, generate packing code that:\n // 1. Packs each member\n // 2. Copies the packed fields into the result array at the correct offset\n // 3. Updates the offset for the next member\n let packing_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let packed_member = $crate::traits::Packable::pack(self.$param_name);\n let packed_member_len = <$param_type as $crate::traits::Packable>::N;\n for i in 0..packed_member_len {\n result[i + offset] = packed_member[i];\n }\n offset += packed_member_len;\n }\n })\n .join(quote {});\n\n quote {\n let mut result = [0; Self::N];\n let mut offset = 0;\n\n $packing_of_struct_members\n\n result\n }\n } else {\n let param_name = params[0].0;\n quote {\n $crate::traits::Packable::pack(self.$param_name)\n }\n };\n\n // For structs containing a single member, we can enhance performance by directly unpacking the input array,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let unpack_function_body = if params.len() > 1 {\n // For multiple struct members, generate unpacking code that:\n // 1. Unpacks each member\n // 2. Copies packed fields into member array at correct offset\n // 3. Updates offset for next member\n let unpacking_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let mut member_fields = [0; <$param_type as $crate::traits::Packable>::N];\n for i in 0..<$param_type as $crate::traits::Packable>::N {\n member_fields[i] = packed[i + offset];\n }\n let $param_name = <$param_type as $crate::traits::Packable>::unpack(member_fields);\n offset += <$param_type as $crate::traits::Packable>::N;\n }\n })\n .join(quote {});\n\n // We join the struct member names with a comma to be used in the `Self { ... }` syntax\n let struct_members = params\n .map(|(param_name, _, _): (Quoted, Type, Quoted)| quote { $param_name })\n .join(quote {,});\n\n quote {\n let mut offset = 0;\n $unpacking_of_struct_members\n Self { $struct_members }\n }\n } else {\n let param_name = params[0].0;\n quote {\n Self { $param_name: $crate::traits::Packable::unpack(packed) }\n }\n };\n\n quote {\n impl$generics_declarations $crate::traits::Packable for $typ\n $where_packable_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n $pack_function_body\n }\n\n #[inline_always]\n fn unpack(packed: [Field; Self::N]) -> Self {\n $unpack_function_body\n }\n }\n }\n}\n\nmod test {\n use crate::traits::{Deserialize, Packable, Serialize};\n\n #[derive(Deserialize, Eq, Packable, Serialize)]\n pub struct Smol {\n a: Field,\n b: Field,\n }\n\n #[derive(Deserialize, Eq, Serialize)]\n pub struct HasArray {\n a: [Field; 2],\n b: bool,\n }\n\n #[derive(Deserialize, Eq, Serialize)]\n pub struct Fancier {\n a: Smol,\n b: [Field; 2],\n c: [u8; 3],\n d: str<16>,\n }\n\n #[derive(Deserialize, Eq, Packable, Serialize)]\n pub struct HasArrayWithGenerics {\n pub fields: [T; N],\n pub length: u32,\n }\n\n #[test]\n fn serde_on_smol() {\n let smol = Smol { a: 1, b: 2 };\n let serialized = smol.serialize();\n assert(serialized == [1, 2], serialized);\n let deserialized = Smol::deserialize(serialized);\n assert(deserialized == smol);\n\n // None of the struct members implements the `Packable` trait so the packed and serialized data should be the same\n let packed = smol.pack();\n assert_eq(packed, serialized, \"Packed does not match serialized\");\n }\n\n #[test]\n fn serde_on_has_array() {\n let has_array = HasArray { a: [1, 2], b: true };\n let serialized = has_array.serialize();\n assert(serialized == [1, 2, 1], serialized);\n let deserialized = HasArray::deserialize(serialized);\n assert(deserialized == has_array);\n }\n\n #[test]\n fn serde_on_fancier() {\n let fancier =\n Fancier { a: Smol { a: 1, b: 2 }, b: [0, 1], c: [1, 2, 3], d: \"metaprogramming!\" };\n let serialized = fancier.serialize();\n assert(\n serialized\n == [\n 1, 2, 0, 1, 1, 2, 3, 0x6d, 0x65, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61,\n 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x21,\n ],\n serialized,\n );\n let deserialized = Fancier::deserialize(serialized);\n assert(deserialized == fancier);\n }\n\n #[test]\n fn serde_on_contains_array_with_generics() {\n let struct_with_array_of_generics = HasArrayWithGenerics { fields: [1, 2, 3], length: 3 };\n let serialized = struct_with_array_of_generics.serialize();\n assert(serialized == [1, 2, 3, 3], serialized);\n let deserialized = HasArrayWithGenerics::deserialize(serialized);\n assert(deserialized == struct_with_array_of_generics);\n }\n\n #[test]\n fn packable_on_contains_array_with_generics() {\n let struct_with_array_of_generics = HasArrayWithGenerics { fields: [1, 2, 3], length: 3 };\n let packed = struct_with_array_of_generics.pack();\n assert(packed == [1, 2, 3, 3], packed);\n\n let unpacked = HasArrayWithGenerics::unpack(packed);\n assert(unpacked == struct_with_array_of_generics);\n }\n\n}\n" + }, + "331": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/point.nr", + "source": "pub use dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\nuse crate::{hash::poseidon2_hash, traits::{Deserialize, Empty, Hash, Packable, Serialize}};\n\npub global POINT_LENGTH: u32 = 3;\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl Serialize for Point {\n let N: u32 = POINT_LENGTH;\n\n fn serialize(self: Self) -> [Field; Self::N] {\n [self.x, self.y, self.is_infinite as Field]\n }\n}\n\nimpl Hash for Point {\n fn hash(self) -> Field {\n poseidon2_hash(self.serialize())\n }\n}\n\nimpl Empty for Point {\n /// Note: Does not return a valid point on curve - instead represents an empty/\"unpopulated\" point struct (e.g.\n /// empty/unpopulated value in an array of points).\n fn empty() -> Self {\n Point { x: 0, y: 0, is_infinite: false }\n }\n}\n\nimpl Deserialize for Point {\n let N: u32 = POINT_LENGTH;\n\n fn deserialize(serialized: [Field; Self::N]) -> Self {\n Point { x: serialized[0], y: serialized[1], is_infinite: serialized[2] != 0 }\n }\n}\n\n// TODO(#11356): use compact representation here.\nimpl Packable for Point {\n let N: u32 = POINT_LENGTH;\n\n fn pack(self) -> [Field; Self::N] {\n self.serialize()\n }\n\n fn unpack(packed: [Field; Self::N]) -> Self {\n Self::deserialize(packed)\n }\n}\n" + }, + "332": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/poseidon2.nr", + "source": "use crate::constants::TWO_POW_64;\nuse crate::traits::{Deserialize, Serialize};\nuse std::meta::derive;\n// NB: This is a clone of noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr\n// It exists as we sometimes need to perform custom absorption, but the stdlib version\n// has a private absorb() method (it's also designed to just be a hasher)\n// Can be removed when standalone noir poseidon lib exists: See noir#6679\n\ncomptime global RATE: u32 = 3;\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct Poseidon2Sponge {\n pub cache: [Field; 3],\n pub state: [Field; 4],\n pub cache_size: u32,\n pub squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2Sponge {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2Sponge::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2Sponge {\n let mut result =\n Poseidon2Sponge { 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) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = std::hash::poseidon2_permutation(self.state, 4);\n }\n\n pub fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\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 }\n }\n\n pub fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> Field {\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::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" + }, + "342": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/public_keys.nr", + "source": "use crate::{\n address::public_keys_hash::PublicKeysHash,\n constants::{\n DEFAULT_IVPK_M_X, DEFAULT_IVPK_M_Y, DEFAULT_NPK_M_X, DEFAULT_NPK_M_Y, DEFAULT_OVPK_M_X,\n DEFAULT_OVPK_M_Y, DEFAULT_TPK_M_X, DEFAULT_TPK_M_Y, GENERATOR_INDEX__PUBLIC_KEYS_HASH,\n },\n hash::poseidon2_hash_with_separator,\n traits::{Deserialize, Hash, Serialize},\n};\n\nuse dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\nuse std::{default::Default, meta::derive};\n\npub trait ToPoint {\n fn to_point(self) -> Point;\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct NpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for NpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n// Note: If we store npk_m_hash directly we can remove this trait implementation. See #8091\nimpl Hash for NpkM {\n fn hash(self) -> Field {\n self.inner.hash()\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct IvpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for IvpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct OvpkM {\n pub inner: Point,\n}\n\nimpl Hash for OvpkM {\n fn hash(self) -> Field {\n self.inner.hash()\n }\n}\n\nimpl ToPoint for OvpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct TpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for TpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct PublicKeys {\n pub npk_m: NpkM,\n pub ivpk_m: IvpkM,\n pub ovpk_m: OvpkM,\n pub tpk_m: TpkM,\n}\n\nimpl Default for PublicKeys {\n fn default() -> Self {\n PublicKeys {\n npk_m: NpkM {\n inner: Point { x: DEFAULT_NPK_M_X, y: DEFAULT_NPK_M_Y, is_infinite: false },\n },\n ivpk_m: IvpkM {\n inner: Point { x: DEFAULT_IVPK_M_X, y: DEFAULT_IVPK_M_Y, is_infinite: false },\n },\n ovpk_m: OvpkM {\n inner: Point { x: DEFAULT_OVPK_M_X, y: DEFAULT_OVPK_M_Y, is_infinite: false },\n },\n tpk_m: TpkM {\n inner: Point { x: DEFAULT_TPK_M_X, y: DEFAULT_TPK_M_Y, is_infinite: false },\n },\n }\n }\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(poseidon2_hash_with_separator(\n self.serialize(),\n GENERATOR_INDEX__PUBLIC_KEYS_HASH as Field,\n ))\n }\n}\n\npub struct AddressPoint {\n pub inner: Point,\n}\n\nimpl ToPoint for AddressPoint {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\nmod test {\n use crate::{\n point::POINT_LENGTH,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, TpkM},\n traits::{Deserialize, Serialize},\n };\n use dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\n\n #[test]\n unconstrained fn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: 1, y: 2, is_infinite: false } },\n ivpk_m: IvpkM { inner: Point { x: 3, y: 4, is_infinite: false } },\n ovpk_m: OvpkM { inner: Point { x: 5, y: 6, is_infinite: false } },\n tpk_m: TpkM { inner: Point { x: 7, y: 8, is_infinite: false } },\n };\n\n let actual = keys.hash();\n let expected_public_keys_hash =\n 0x0fecd9a32db731fec1fded1b9ff957a1625c069245a3613a2538bd527068b0ad;\n\n assert(actual.to_field() == expected_public_keys_hash);\n }\n\n #[test]\n unconstrained fn compute_default_hash() {\n let keys = PublicKeys::default();\n\n let actual = keys.hash();\n let test_data_default_hash =\n 0x1d3bf1fb93ae0e9cda83b203dd91c3bfb492a9aecf30ec90e1057eced0f0e62d;\n\n assert(actual.to_field() == test_data_default_hash);\n }\n\n #[test]\n unconstrained fn serde() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: 1, y: 2, is_infinite: false } },\n ivpk_m: IvpkM { inner: Point { x: 3, y: 4, is_infinite: false } },\n ovpk_m: OvpkM { inner: Point { x: 5, y: 6, is_infinite: false } },\n tpk_m: TpkM { inner: Point { x: 7, y: 8, is_infinite: false } },\n };\n\n // We use the PUBLIC_KEYS_LENGTH constant to ensure that there is a match between the derived trait\n let serialized: [Field; POINT_LENGTH * 4] = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys, deserialized);\n }\n}\n" + }, + "344": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr", + "source": "use crate::{hash::poseidon2_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field\nwhere\n K: ToField,\n{\n poseidon2_hash([storage_slot, key.to_field()])\n}\n\nmod test {\n use crate::{address::AztecAddress, storage::map::derive_storage_slot_in_map, traits::FromField};\n\n #[test]\n fn test_derive_storage_slot_in_map_matches_typescript() {\n let map_slot = 0x132258fb6962c4387ba659d9556521102d227549a386d39f0b22d1890d59c2b5;\n let key = AztecAddress::from_field(\n 0x302dbc2f9b50a73283d5fb2f35bc01eae8935615817a0b4219a057b2ba8a5a3f,\n );\n\n let slot = derive_storage_slot_in_map(map_slot, key);\n\n // The following value was generated by `map_slot.test.ts`\n let slot_from_typescript =\n 0x15b9fe39449affd8b377461263e9d2b610b9ad40580553500b4e41d9cbd887ac;\n\n assert_eq(slot, slot_from_typescript);\n }\n}\n" + }, + "357": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr", + "source": "use crate::meta::{derive_deserialize, derive_packable, derive_serialize};\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.\npub trait Empty: Eq {\n fn empty() -> Self;\n\n fn is_empty(self) -> bool {\n self.eq(Self::empty())\n }\n\n // Requires this Noir fix: https://github.com/noir-lang/noir/issues/9002\n // fn assert_not_empty(self, msg: str) { // This msg version was failing with weird compiler errors.\n // // We provide a default impl but it's likely inefficient.\n // // The reason we include this function is because there's a lot of\n // // opportunity for optimisation on a per-struct basis.\n // // You only need to show one element is not empty to know that the whole thing\n // // is not empty.\n // // If you know an element of your struct which should always be nonempty,\n // // you can write an impl that solely checks that that element is nonempty.\n // assert(!self.is_empty(), msg);\n // }\n\n // This default impl is overwritten by types like arrays, because there's a much\n // more efficient approach.\n fn assert_empty(self, msg: str) {\n assert(self.is_empty(), msg);\n }\n}\n\nimpl Empty for Field {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\n\nimpl Empty for u1 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u8 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u16 {\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u32 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u64 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u128 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\n\nimpl Empty for [T; N]\nwhere\n T: Empty,\n{\n #[inline_always]\n fn empty() -> Self {\n [T::empty(); N]\n }\n\n fn is_empty(self) -> bool {\n self.all(|elem| elem.is_empty())\n }\n\n fn assert_empty(self, msg: str) -> () {\n self.for_each(|elem| elem.assert_empty(msg))\n }\n}\n\nimpl Empty for [T]\nwhere\n T: Empty,\n{\n #[inline_always]\n fn empty() -> Self {\n [T::empty()]\n }\n\n fn is_empty(self) -> bool {\n self.all(|elem| elem.is_empty())\n }\n\n fn assert_empty(self, msg: str) -> () {\n self.for_each(|elem| elem.assert_empty(msg))\n }\n}\nimpl Empty for (A, B)\nwhere\n A: Empty,\n B: Empty,\n{\n #[inline_always]\n fn empty() -> Self {\n (A::empty(), B::empty())\n }\n}\n\nimpl Empty for Option\nwhere\n T: Eq,\n{\n #[inline_always]\n fn empty() -> Self {\n Option::none()\n }\n}\n\n// pub fn is_empty(item: T) -> bool\n// where\n// T: Empty,\n// {\n// item.eq(T::empty())\n// }\n\n// pub fn is_empty_array(array: [T; N]) -> bool\n// where\n// T: Empty,\n// {\n// array.all(|elem| is_empty(elem))\n// }\n\n// pub fn assert_empty(item: T) -> ()\n// where\n// T: Empty,\n// {\n// assert(item.eq(T::empty()))\n// }\n\n// pub fn assert_empty_array(array: [T; N]) -> ()\n// where\n// T: Empty,\n// {\n// // A cheaper option than `is_empty_array` for if you don't need to gracefully\n// // handle a bool result.\n// // Avoids the `&` operator of `is_empty_array`'s `.all()` call.\n// for i in 0..N {\n// assert(is_empty(array[i]));\n// }\n// }\n\npub trait Hash {\n fn hash(self) -> Field;\n}\n\npub trait ToField {\n fn to_field(self) -> Field;\n}\n\nimpl ToField for Field {\n #[inline_always]\n fn to_field(self) -> Field {\n self\n }\n}\n\nimpl ToField for bool {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u1 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u8 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u16 {\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u32 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u64 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u128 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for str {\n #[inline_always]\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\npub trait FromField {\n fn from_field(value: Field) -> Self;\n}\n\nimpl FromField for Field {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value\n }\n}\n\nimpl FromField for bool {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value != 0\n }\n}\nimpl FromField for u1 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u1\n }\n}\nimpl FromField for u8 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u8\n }\n}\nimpl FromField for u16 {\n fn from_field(value: Field) -> Self {\n value as u16\n }\n}\nimpl FromField for u32 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u32\n }\n}\nimpl FromField for u64 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u64\n }\n}\nimpl FromField for u128 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u128\n }\n}\n\n// docs:start:serialize\n/// Trait for serializing Noir types into arrays of Fields.\n///\n/// An implementation of the Serialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait (and Deserialize) are\n/// typically used to communicate between Noir and TypeScript (via oracles and function arguments).\n///\n/// # On Following Noir's Intrinsic Serialization\n/// When calling a Noir function from TypeScript (TS), first the function arguments are serialized into an array\n/// of fields. This array is then included in the initial witness. Noir's intrinsic serialization is then used\n/// to deserialize the arguments from the witness. When the same Noir function is called from Noir this Serialize trait\n/// is used instead of the serialization in TS. For this reason we need to have a match between TS serialization,\n/// Noir's intrinsic serialization and the implementation of this trait. If there is a mismatch, the function calls\n/// fail with an arguments hash mismatch error message.\n///\n/// # Associated Constants\n/// * `N` - The length of the output Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl Serialize for str {\n/// let N: u32 = N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let bytes = self.as_bytes();\n/// let mut fields = [0; Self::N];\n/// for i in 0..bytes.len() {\n/// fields[i] = bytes[i] as Field; // Each byte gets its own Field\n/// }\n/// fields\n/// }\n/// }\n/// ```\n#[derive_via(derive_serialize)]\npub trait Serialize {\n let N: u32;\n\n fn serialize(self) -> [Field; N];\n}\n// docs:end:serialize\n\nimpl Serialize for str {\n let N: u32 = M;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let bytes = self.as_bytes();\n let mut fields = [0; Self::N];\n for i in 0..bytes.len() {\n fields[i] = bytes[i] as Field;\n }\n fields\n }\n}\n\n/// Implementation of Deserialize for BoundedVec.\n///\n/// This implementation deserializes a BoundedVec from an array of Fields. The array contains:\n/// 1. The serialized items, each taking up T::N Fields\n/// 2. The length of the BoundedVec as the last Field\n///\n/// # Type Parameters\n/// * `T` - The type of items stored in the BoundedVec, must implement Deserialize\n/// * `M` - The maximum length of the BoundedVec\n///\n/// # Fields Array Layout\n/// [item1_field1, item1_field2, ..., item2_field1, item2_field2, ..., length]\n/// Where:\n/// - itemN_fieldM: The M-th Field of the N-th item (T::N Fields per item)\n/// - length: The number of items in the BoundedVec (1 Field)\n///\n/// Total length N = T::N * M + 1, where:\n/// - T::N is the number of Fields needed to deserialize one item\n/// - M is the maximum length of the BoundedVec\n/// - +1 is for storing the length\n///\n/// # Note\n/// Not deriving this because it's not supported to call derive_deserialize on a \"remote\" struct (and it will never\n/// be supported).\nimpl Deserialize for BoundedVec\nwhere\n T: Deserialize,\n{\n let N: u32 = ::N * M + 1;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut new_bounded_vec: BoundedVec = BoundedVec::new();\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n let len = fields[::N * M] as u32;\n\n for i in 0..len {\n let mut nested_fields = [0; ::N];\n for j in 0..::N {\n nested_fields[j] = fields[i * ::N + j];\n }\n\n let item = T::deserialize(nested_fields);\n new_bounded_vec.push(item);\n }\n\n new_bounded_vec\n }\n}\n\n// This may cause issues if used as program input, because noir disallows empty arrays for program input.\n// I think this is okay because I don't foresee a unit type being used as input. But leaving this comment as a hint\n// if someone does run into this in the future.\nimpl Deserialize for () {\n let N: u32 = 0;\n\n fn deserialize(_fields: [Field; Self::N]) -> Self {\n ()\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl Serialize for BoundedVec\nwhere\n T: Serialize,\n{\n let N: u32 = ::N * M + 1; // +1 for the length of the BoundedVec\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let mut fields = [0; Self::N];\n\n let storage = self.storage();\n\n for i in 0..M {\n let serialized_item = storage[i].serialize();\n\n for j in 0..::N {\n fields[i * ::N + j] = serialized_item[j];\n }\n }\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n fields[::N * M] = self.len() as Field;\n\n fields\n }\n}\n\n// docs:start:deserialize\n/// Trait for deserializing Noir types from arrays of Fields.\n///\n/// An implementation of the Deserialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait is typically used when\n/// deserializing return values from function calls in Noir. Since the same function could be called from TypeScript\n/// (TS), in which case the TS deserialization would get used, we need to have a match between the 2.\n///\n/// # Associated Constants\n/// * `N` - The length of the input Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl Deserialize for str {\n/// let N: u32 = M;\n///\n/// #[inline_always]\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// str::::from(fields.map(|value| value as u8))\n/// }\n/// }\n/// ```\n#[derive_via(derive_deserialize)]\npub trait Deserialize {\n let N: u32;\n\n fn deserialize(fields: [Field; N]) -> Self;\n}\n// docs:end:deserialize\n\nimpl Deserialize for str {\n let N: u32 = M;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n str::::from(fields.map(|value| value as u8))\n }\n}\n\n/// Trait for efficiently packing and unpacking Noir types into and from arrays of Fields.\n///\n/// The `Packable` trait allows types to be serialized and deserialized with a focus on minimizing the size of\n/// the resulting Field array. This trait is used when storage efficiency is critical (e.g. when storing data\n/// in the contract's public storage).\n///\n/// # Associated Constants\n/// * `N` - The length of the Field array, known at compile time\n#[derive_via(derive_packable)]\npub trait Packable {\n let N: u32;\n\n /// Packs the current value into a compact array of `Field` elements.\n fn pack(self) -> [Field; N];\n\n /// Unpacks a compact array of `Field` elements into the original value.\n fn unpack(fields: [Field; N]) -> Self;\n}\n\n#[test]\nunconstrained fn bounded_vec_serialization() {\n // Test empty BoundedVec\n let empty_vec: BoundedVec = BoundedVec::from_array([]);\n let serialized = empty_vec.serialize();\n let deserialized = BoundedVec::::deserialize(serialized);\n assert_eq(empty_vec, deserialized);\n assert_eq(deserialized.len(), 0);\n\n // Test partially filled BoundedVec\n let partial_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2]]);\n let serialized = partial_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(partial_vec, deserialized);\n assert_eq(deserialized.len(), 1);\n assert_eq(deserialized.get(0), [1, 2]);\n\n // Test full BoundedVec\n let full_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2], [3, 4], [5, 6]]);\n let serialized = full_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(full_vec, deserialized);\n assert_eq(deserialized.len(), 3);\n assert_eq(deserialized.get(0), [1, 2]);\n assert_eq(deserialized.get(1), [3, 4]);\n assert_eq(deserialized.get(2), [5, 6]);\n}\n" + }, + "359": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/type_packing.nr", + "source": "use crate::traits::Packable;\n\nglobal BOOL_PACKED_LEN: u32 = 1;\nglobal U8_PACKED_LEN: u32 = 1;\nglobal U16_PACKED_LEN: u32 = 1;\nglobal U32_PACKED_LEN: u32 = 1;\nglobal U64_PACKED_LEN: u32 = 1;\nglobal U128_PACKED_LEN: u32 = 1;\nglobal FIELD_PACKED_LEN: u32 = 1;\nglobal I8_PACKED_LEN: u32 = 1;\nglobal I16_PACKED_LEN: u32 = 1;\nglobal I32_PACKED_LEN: u32 = 1;\nglobal I64_PACKED_LEN: u32 = 1;\n\nimpl Packable for bool {\n let N: u32 = BOOL_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> bool {\n (fields[0] as u1) != 0\n }\n}\n\nimpl Packable for u8 {\n let N: u32 = U8_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Packable for u16 {\n let N: u32 = U16_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u16\n }\n}\n\nimpl Packable for u32 {\n let N: u32 = U32_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Packable for u64 {\n let N: u32 = U64_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Packable for u128 {\n let N: u32 = U128_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u128\n }\n}\n\nimpl Packable for Field {\n let N: u32 = FIELD_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0]\n }\n}\n\nimpl Packable for i8 {\n let N: u32 = I8_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u8 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u8 as i8\n }\n}\n\nimpl Packable for i16 {\n let N: u32 = I16_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u16 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u16 as i16\n }\n}\n\nimpl Packable for i32 {\n let N: u32 = I32_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u32 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u32 as i32\n }\n}\n\nimpl Packable for i64 {\n let N: u32 = I64_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u64 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u64 as i64\n }\n}\n\nimpl Packable for [T; M]\nwhere\n T: Packable,\n{\n let N: u32 = M * ::N;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n let mut result: [Field; Self::N] = std::mem::zeroed();\n for i in 0..M {\n let serialized = self[i].pack();\n for j in 0..::N {\n result[i * ::N + j] = serialized[j];\n }\n }\n result\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::utils::reader::Reader::new(fields);\n let mut result: [T; M] = std::mem::zeroed();\n reader.read_struct_array::::N, M>(Packable::unpack, result)\n }\n}\n\n#[test]\nfn test_u16_packing() {\n let a: u16 = 10;\n assert_eq(a, u16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i8_packing() {\n let a: i8 = -10;\n assert_eq(a, i8::unpack(a.pack()));\n}\n\n#[test]\nfn test_i16_packing() {\n let a: i16 = -10;\n assert_eq(a, i16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i32_packing() {\n let a: i32 = -10;\n assert_eq(a, i32::unpack(a.pack()));\n}\n\n#[test]\nfn test_i64_packing() {\n let a: i64 = -10;\n assert_eq(a, i64::unpack(a.pack()));\n}\n" + }, + "360": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/type_serialization.nr", + "source": "use crate::traits::{Deserialize, Serialize};\n\nglobal BOOL_SERIALIZED_LEN: u32 = 1;\nglobal U8_SERIALIZED_LEN: u32 = 1;\nglobal U16_SERIALIZED_LEN: u32 = 1;\nglobal U32_SERIALIZED_LEN: u32 = 1;\nglobal U64_SERIALIZED_LEN: u32 = 1;\nglobal U128_SERIALIZED_LEN: u32 = 1;\nglobal FIELD_SERIALIZED_LEN: u32 = 1;\nglobal I8_SERIALIZED_LEN: u32 = 1;\nglobal I16_SERIALIZED_LEN: u32 = 1;\nglobal I32_SERIALIZED_LEN: u32 = 1;\nglobal I64_SERIALIZED_LEN: u32 = 1;\n\nimpl Serialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> bool {\n fields[0] != 0\n }\n}\n\nimpl Serialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Serialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u16\n }\n}\n\nimpl Serialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Serialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Serialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u128\n }\n}\n\nimpl Serialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self]\n }\n}\n\nimpl Deserialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0]\n }\n}\n\nimpl Serialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u8 as Field]\n }\n}\n\nimpl Deserialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u8 as i8\n }\n}\n\nimpl Serialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u16 as Field]\n }\n}\n\nimpl Deserialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u16 as i16\n }\n}\n\nimpl Serialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u32 as Field]\n }\n}\n\nimpl Deserialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u32 as i32\n }\n}\n\nimpl Serialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u64 as Field]\n }\n}\n\nimpl Deserialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u64 as i64\n }\n}\n\nimpl Serialize for [T; M]\nwhere\n T: Serialize,\n{\n let N: u32 = ::N * M;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let mut result: [Field; _] = std::mem::zeroed();\n for i in 0..M {\n let serialized_t = self[i].serialize();\n for j in 0..::N {\n result[i * ::N + j] = serialized_t[j];\n }\n }\n result\n }\n}\n\nimpl Deserialize for [T; M]\nwhere\n T: Deserialize,\n{\n let N: u32 = ::N * M;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::utils::reader::Reader::new(fields);\n let mut result: [T; M] = std::mem::zeroed();\n reader.read_struct_array::::N, M>(Deserialize::deserialize, result)\n }\n}\n\nimpl Serialize for Option\nwhere\n T: Serialize,\n{\n let N: u32 = ::N + 1;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let mut result: [Field; Self::N] = std::mem::zeroed();\n\n result[0] = if self.is_some() { 1 } else { 0 };\n\n let value_serialized = self.unwrap_unchecked().serialize();\n for i in 0..::N {\n result[1 + i] = value_serialized[i];\n }\n\n result\n }\n}\n\nimpl Deserialize for Option\nwhere\n T: Deserialize,\n{\n let N: u32 = ::N + 1;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n if fields[0] == 1 {\n let mut value_fields = [0; ::N];\n for i in 0..::N {\n value_fields[i] = fields[1 + i];\n }\n\n Option::some(T::deserialize(value_fields))\n } else {\n Option::none()\n }\n }\n}\n\nmod test {\n use crate::traits::{Deserialize, Serialize};\n\n #[test]\n fn u16_serialization() {\n let a: u16 = 10;\n assert_eq(a, u16::deserialize(a.serialize()));\n }\n\n #[test]\n fn i8_serialization() {\n let a: i8 = -10;\n assert_eq(a, i8::deserialize(a.serialize()));\n }\n\n #[test]\n fn i16_serialization() {\n let a: i16 = -10;\n assert_eq(a, i16::deserialize(a.serialize()));\n }\n\n #[test]\n fn i32_serialization() {\n let a: i32 = -10;\n assert_eq(a, i32::deserialize(a.serialize()));\n }\n\n #[test]\n fn i64_serialization() {\n let a: i64 = -10;\n assert_eq(a, i64::deserialize(a.serialize()));\n }\n\n #[test]\n fn option_field_serialization() {\n let opt_some = Option::some(5);\n assert_eq(Option::<_>::deserialize(opt_some.serialize()), opt_some);\n\n let opt_none = Option::none();\n assert_eq(Option::::deserialize(opt_none.serialize()), opt_none);\n }\n\n #[test]\n fn option_array_serialization() {\n let opt_some = Option::some([2, 5]);\n assert_eq(Option::<_>::deserialize(opt_some.serialize()), opt_some);\n\n let opt_none = Option::none();\n assert_eq(Option::::deserialize(opt_none.serialize()), opt_none);\n }\n}\n" + }, + "380": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr", + "source": "pub 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_u64(&mut self) -> u64 {\n self.read() as u64\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() != 0\n }\n\n pub fn read_array(&mut self) -> [Field; K] {\n let mut result = [0; 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 pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array());\n result\n }\n\n pub fn read_struct_array(\n &mut self,\n deserialise: fn([Field; K]) -> T,\n mut result: [T; C],\n ) -> [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_eq(self.offset, self.data.len(), \"Reader did not read all data\");\n }\n}\n" + }, + "42": { + "path": "std/option.nr", + "source": "use crate::cmp::{Eq, Ord, Ordering};\nuse crate::default::Default;\nuse crate::hash::{Hash, Hasher};\n\npub struct 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::mem::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 {\n self._value\n } else {\n default\n }\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 pub 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 {\n self\n } else {\n other\n }\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 {\n self\n } else {\n default()\n }\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 {\n Option::none()\n } else {\n self\n }\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\nwhere\n T: Eq,\n{\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\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\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\nwhere\n T: Ord,\n{\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 if other._is_some {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n" + }, + "43": { + "path": "std/panic.nr", + "source": "pub fn panic(message: fmtstr) -> U {\n assert(false, message);\n crate::mem::zeroed()\n}\n" + }, + "5": { + "path": "std/cmp.nr", + "source": "use crate::meta::derive_via;\n\n#[derive_via(derive_eq)]\n// docs:start:eq-trait\npub trait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\n// docs:start:derive_eq\ncomptime fn derive_eq(s: TypeDefinition) -> Quoted {\n let signature = quote { fn eq(_self: Self, _other: Self) -> bool };\n let for_each_field = |name| quote { (_self.$name == _other.$name) };\n let body = |fields| {\n if s.fields_as_written().len() == 0 {\n quote { true }\n } else {\n fields\n }\n };\n crate::meta::make_trait_impl(\n s,\n quote { $crate::cmp::Eq },\n signature,\n for_each_field,\n quote { & },\n body,\n )\n}\n// docs:end:derive_eq\n\nimpl Eq for Field {\n fn eq(self, other: Field) -> bool {\n self == other\n }\n}\n\nimpl Eq for u128 {\n fn eq(self, other: u128) -> bool {\n self == other\n }\n}\nimpl Eq for u64 {\n fn eq(self, other: u64) -> bool {\n self == other\n }\n}\nimpl Eq for u32 {\n fn eq(self, other: u32) -> bool {\n self == other\n }\n}\nimpl Eq for u16 {\n fn eq(self, other: u16) -> bool {\n self == other\n }\n}\nimpl Eq for u8 {\n fn eq(self, other: u8) -> bool {\n self == other\n }\n}\nimpl Eq for u1 {\n fn eq(self, other: u1) -> bool {\n self == other\n }\n}\n\nimpl Eq for i8 {\n fn eq(self, other: i8) -> bool {\n self == other\n }\n}\nimpl Eq for i16 {\n fn eq(self, other: i16) -> bool {\n self == other\n }\n}\nimpl Eq for i32 {\n fn eq(self, other: i32) -> bool {\n self == other\n }\n}\nimpl Eq for i64 {\n fn eq(self, other: i64) -> bool {\n self == other\n }\n}\n\nimpl Eq for () {\n fn eq(_self: Self, _other: ()) -> bool {\n true\n }\n}\nimpl Eq for bool {\n fn eq(self, other: bool) -> bool {\n self == other\n }\n}\n\nimpl Eq for [T; N]\nwhere\n T: Eq,\n{\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]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n if result {\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\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)\nwhere\n A: Eq,\n B: Eq,\n{\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)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n{\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)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n{\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)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n E: Eq,\n{\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0)\n & self.1.eq(other.1)\n & self.2.eq(other.2)\n & self.3.eq(other.3)\n & 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.\npub struct 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#[derive_via(derive_ord)]\n// docs:start:ord-trait\npub trait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// docs:start:derive_ord\ncomptime fn derive_ord(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::cmp::Ord };\n let signature = quote { fn cmp(_self: Self, _other: Self) -> $crate::cmp::Ordering };\n let for_each_field = |name| quote {\n if result == $crate::cmp::Ordering::equal() {\n result = _self.$name.cmp(_other.$name);\n }\n };\n let body = |fields| quote {\n let mut result = $crate::cmp::Ordering::equal();\n $fields\n result\n };\n crate::meta::make_trait_impl(s, name, signature, for_each_field, quote {}, body)\n}\n// docs:end:derive_ord\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u128 {\n fn cmp(self, other: u128) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\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 u16 {\n fn cmp(self, other: u16) -> 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 i16 {\n fn cmp(self, other: i16) -> 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 if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for [T; N]\nwhere\n T: Ord,\n{\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 result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for [T]\nwhere\n T: Ord,\n{\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 self_len = self.len();\n let other_len = other.len();\n let min_len = if self_len < other_len {\n self_len\n } else {\n other_len\n };\n\n let mut result = Ordering::equal();\n for i in 0..min_len {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n\n if result != Ordering::equal() {\n result\n } else {\n self_len.cmp(other_len)\n }\n }\n}\n\nimpl Ord for (A, B)\nwhere\n A: Ord,\n B: Ord,\n{\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)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n{\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)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n{\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)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n E: Ord,\n{\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\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v1\n } else {\n v2\n }\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\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v2\n } else {\n v1\n }\n}\n\nmod cmp_tests {\n use super::{Eq, max, min, Ord};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0_u64, 1), 0);\n assert_eq(min(0_u64, 0), 0);\n assert_eq(min(1_u64, 1), 1);\n assert_eq(min(255_u8, 0), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0_u64, 1), 1);\n assert_eq(max(0_u64, 0), 0);\n assert_eq(max(1_u64, 1), 1);\n assert_eq(max(255_u8, 0), 255);\n }\n\n #[test]\n fn correctly_handles_unequal_length_slices() {\n let slice_1 = &[0, 1, 2, 3];\n let slice_2 = &[0, 1, 2];\n assert(!slice_1.eq(slice_2));\n }\n\n #[test]\n fn lexicographic_ordering_for_slices() {\n assert(&[2_u32].cmp(&[1_u32, 1_u32, 1_u32]) == super::Ordering::greater());\n assert(&[1_u32, 2_u32].cmp(&[1_u32, 2_u32, 3_u32]) == super::Ordering::less());\n }\n}\n" + }, + "50": { + "path": "/home/josh/Documents/Github/aztec-web-starter/contracts/src/main.nr", + "source": "use dep::aztec::macros::aztec;\n\n#[aztec]\npub contract PrivateVoting {\n use dep::aztec::keys::getters::get_public_keys;\n use dep::aztec::macros::{\n functions::{initializer, internal, private, public, utility},\n storage::storage,\n };\n use dep::aztec::protocol_types::{address::AztecAddress, traits::{Hash, ToField}};\n use dep::aztec::state_vars::{Map, PublicImmutable, PublicMutable};\n\n #[storage]\n struct Storage {\n admin: PublicMutable, // admin can end vote\n tally: Map, Context>, // we will store candidate as key and number of votes as value\n vote_ended: PublicMutable, // vote_ended is boolean\n active_at_block: PublicImmutable, // when people can start voting\n }\n\n #[public]\n #[initializer]\n fn constructor(admin: AztecAddress) {\n storage.admin.write(admin);\n storage.vote_ended.write(false);\n storage.active_at_block.initialize(context.block_number());\n }\n\n #[private]\n fn cast_vote(candidate: Field) {\n let msg_sender_npk_m_hash = get_public_keys(context.msg_sender()).npk_m.hash();\n\n let secret = context.request_nsk_app(msg_sender_npk_m_hash); // get secret key of caller of function\n let nullifier = std::hash::pedersen_hash([context.msg_sender().to_field(), secret]); // derive nullifier from sender and secret\n context.push_nullifier(nullifier);\n PrivateVoting::at(context.this_address()).add_to_tally_public(candidate).enqueue(\n &mut context,\n );\n }\n\n #[public]\n #[internal]\n fn add_to_tally_public(candidate: Field) {\n assert(storage.vote_ended.read() == false, \"Vote has ended\"); // assert that vote has not ended\n let new_tally = storage.tally.at(candidate).read() + 1;\n storage.tally.at(candidate).write(new_tally);\n }\n\n #[public]\n fn end_vote() {\n assert(storage.admin.read().eq(context.msg_sender()), \"Only admin can end votes\"); // assert that caller is admin\n storage.vote_ended.write(true);\n }\n\n #[utility]\n unconstrained fn get_vote(candidate: Field) -> Field {\n storage.tally.at(candidate).read()\n }\n}\n" + }, + "6": { + "path": "std/collections/bounded_vec.nr", + "source": "use crate::{cmp::Eq, convert::From, runtime::is_unconstrained, static_assert};\n\n/// A `BoundedVec` is a growable storage similar to a `Vec` except that it\n/// is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented\n/// via slices and thus is not subject to the same restrictions slices are (notably, nested\n/// slices - and thus nested vectors as well - are disallowed).\n///\n/// Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by\n/// pushing an additional element is also more efficient - the length only needs to be increased\n/// by one.\n///\n/// For these reasons `BoundedVec` should generally be preferred over `Vec` when there\n/// is a reasonable maximum bound that can be placed on the vector.\n///\n/// Example:\n///\n/// ```noir\n/// let mut vector: BoundedVec = BoundedVec::new();\n/// for i in 0..5 {\n/// vector.push(i);\n/// }\n/// assert(vector.len() == 5);\n/// assert(vector.max_len() == 10);\n/// ```\npub struct BoundedVec {\n storage: [T; MaxLen],\n len: u32,\n}\n\nimpl BoundedVec {\n /// Creates a new, empty vector of length zero.\n ///\n /// Since this container is backed by an array internally, it still needs an initial value\n /// to give each element. To resolve this, each element is zeroed internally. This value\n /// is guaranteed to be inaccessible unless `get_unchecked` is used.\n ///\n /// Example:\n ///\n /// ```noir\n /// let empty_vector: BoundedVec = BoundedVec::new();\n /// assert(empty_vector.len() == 0);\n /// ```\n ///\n /// Note that whenever calling `new` the maximum length of the vector should always be specified\n /// via a type signature:\n ///\n /// ```noir\n /// fn good() -> BoundedVec {\n /// // Ok! MaxLen is specified with a type annotation\n /// let v1: BoundedVec = BoundedVec::new();\n /// let v2 = BoundedVec::new();\n ///\n /// // Ok! MaxLen is known from the type of `good`'s return value\n /// v2\n /// }\n ///\n /// fn bad() {\n /// // Error: Type annotation needed\n /// // The compiler can't infer `MaxLen` from the following code:\n /// let mut v3 = BoundedVec::new();\n /// v3.push(5);\n /// }\n /// ```\n ///\n /// This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions\n /// but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a\n /// constraint failure at runtime when the vec is pushed to.\n pub fn new() -> Self {\n let zeroed = crate::mem::zeroed();\n BoundedVec { storage: [zeroed; MaxLen], len: 0 }\n }\n\n /// Retrieves an element from the vector at the given index, starting from zero.\n ///\n /// If the given index is equal to or greater than the length of the vector, this\n /// will issue a constraint failure.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn foo(v: BoundedVec) {\n /// let first = v.get(0);\n /// let last = v.get(v.len() - 1);\n /// assert(first != last);\n /// }\n /// ```\n pub fn get(self, index: u32) -> T {\n assert(index < self.len, \"Attempted to read past end of BoundedVec\");\n self.get_unchecked(index)\n }\n\n /// Retrieves an element from the vector at the given index, starting from zero, without\n /// performing a bounds check.\n ///\n /// Since this function does not perform a bounds check on length before accessing the element,\n /// it is unsafe! Use at your own risk!\n ///\n /// Example:\n ///\n /// ```noir\n /// fn sum_of_first_three(v: BoundedVec) -> u32 {\n /// // Always ensure the length is larger than the largest\n /// // index passed to get_unchecked\n /// assert(v.len() > 2);\n /// let first = v.get_unchecked(0);\n /// let second = v.get_unchecked(1);\n /// let third = v.get_unchecked(2);\n /// first + second + third\n /// }\n /// ```\n pub fn get_unchecked(self, index: u32) -> T {\n self.storage[index]\n }\n\n /// Writes an element to the vector at the given index, starting from zero.\n ///\n /// If the given index is equal to or greater than the length of the vector, this will issue a constraint failure.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn foo(v: BoundedVec) {\n /// let first = v.get(0);\n /// assert(first != 42);\n /// v.set(0, 42);\n /// let new_first = v.get(0);\n /// assert(new_first == 42);\n /// }\n /// ```\n pub fn set(&mut self, index: u32, value: T) {\n assert(index < self.len, \"Attempted to write past end of BoundedVec\");\n self.set_unchecked(index, value)\n }\n\n /// Writes an element to the vector at the given index, starting from zero, without performing a bounds check.\n ///\n /// Since this function does not perform a bounds check on length before accessing the element, it is unsafe! Use at your own risk!\n ///\n /// Example:\n ///\n /// ```noir\n /// fn set_unchecked_example() {\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_array([1, 2]);\n ///\n /// // Here we're safely writing within the valid range of `vec`\n /// // `vec` now has the value [42, 2]\n /// vec.set_unchecked(0, 42);\n ///\n /// // We can then safely read this value back out of `vec`.\n /// // Notice that we use the checked version of `get` which would prevent reading unsafe values.\n /// assert_eq(vec.get(0), 42);\n ///\n /// // We've now written past the end of `vec`.\n /// // As this index is still within the maximum potential length of `v`,\n /// // it won't cause a constraint failure.\n /// vec.set_unchecked(2, 42);\n /// println(vec);\n ///\n /// // This will write past the end of the maximum potential length of `vec`,\n /// // it will then trigger a constraint failure.\n /// vec.set_unchecked(5, 42);\n /// println(vec);\n /// }\n /// ```\n pub fn set_unchecked(&mut self, index: u32, value: T) {\n self.storage[index] = value;\n }\n\n /// Pushes an element to the end of the vector. This increases the length\n /// of the vector by one.\n ///\n /// Panics if the new length of the vector will be greater than the max length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// v.push(1);\n /// v.push(2);\n ///\n /// // Panics with failed assertion \"push out of bounds\"\n /// v.push(3);\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 /// Returns the current length of this vector\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// assert(v.len() == 0);\n ///\n /// v.push(100);\n /// assert(v.len() == 1);\n ///\n /// v.push(200);\n /// v.push(300);\n /// v.push(400);\n /// assert(v.len() == 4);\n ///\n /// let _ = v.pop();\n /// let _ = v.pop();\n /// assert(v.len() == 2);\n /// ```\n pub fn len(self) -> u32 {\n self.len\n }\n\n /// Returns the maximum length of this vector. This is always\n /// equal to the `MaxLen` parameter this vector was initialized with.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// assert(v.max_len() == 5);\n /// v.push(10);\n /// assert(v.max_len() == 5);\n /// ```\n pub fn max_len(_self: BoundedVec) -> u32 {\n MaxLen\n }\n\n /// Returns the internal array within this vector.\n ///\n /// Since arrays in Noir are immutable, mutating the returned storage array will not mutate\n /// the storage held internally by this vector.\n ///\n /// Note that uninitialized elements may be zeroed out!\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// assert(v.storage() == [0, 0, 0, 0, 0]);\n ///\n /// v.push(57);\n /// assert(v.storage() == [57, 0, 0, 0, 0]);\n /// ```\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n /// Pushes each element from the given array to this vector.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_array([2, 4]);\n ///\n /// assert(vec.len == 2);\n /// assert(vec.get(0) == 2);\n /// assert(vec.get(1) == 4);\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 /// Pushes each element from the given slice to this vector.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_slice(&[2, 4]);\n ///\n /// assert(vec.len == 2);\n /// assert(vec.get(0) == 2);\n /// assert(vec.get(1) == 4);\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 /// Pushes each element from the other vector to this vector. The length of\n /// the other vector is left unchanged.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// ```noir\n /// let mut v1: BoundedVec = BoundedVec::new();\n /// let mut v2: BoundedVec = BoundedVec::new();\n ///\n /// v2.extend_from_array([1, 2, 3]);\n /// v1.extend_from_bounded_vec(v2);\n ///\n /// assert(v1.storage() == [1, 2, 3, 0, 0]);\n /// assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]);\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 if is_unconstrained() {\n for i in 0..append_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n } else {\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 }\n self.len = new_len;\n }\n\n /// Creates a new vector, populating it with values derived from an array input.\n /// The maximum length of the vector is determined based on the type signature.\n ///\n /// Example:\n ///\n /// ```noir\n /// let bounded_vec: BoundedVec = BoundedVec::from_array([1, 2, 3])\n /// ```\n pub fn from_array(array: [T; Len]) -> Self {\n static_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 /// Pops the element at the end of the vector. This will decrease the length\n /// of the vector by one.\n ///\n /// Panics if the vector is empty.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// v.push(1);\n /// v.push(2);\n ///\n /// let two = v.pop();\n /// let one = v.pop();\n ///\n /// assert(two == 2);\n /// assert(one == 1);\n ///\n /// // error: cannot pop from an empty vector\n /// let _ = v.pop();\n /// ```\n pub fn pop(&mut self) -> T {\n assert(self.len > 0, \"cannot pop from an empty vector\");\n self.len -= 1;\n\n let elem = self.storage[self.len];\n self.storage[self.len] = crate::mem::zeroed();\n elem\n }\n\n /// Returns true if the given predicate returns true for any element\n /// in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// v.extend_from_array([2, 4, 6]);\n ///\n /// let all_even = !v.any(|elem: u32| elem % 2 != 0);\n /// assert(all_even);\n /// ```\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n if is_unconstrained() {\n for i in 0..self.len {\n ret |= predicate(self.storage[i]);\n }\n } else {\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 }\n ret\n }\n\n /// Creates a new vector of equal size by calling a closure on each element in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let result = vec.map(|value| value * 2);\n ///\n /// let expected = BoundedVec::from_array([2, 4, 6, 8]);\n /// assert_eq(result, expected);\n /// ```\n pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec {\n let mut ret = BoundedVec::new();\n ret.len = self.len();\n\n if is_unconstrained() {\n for i in 0..self.len() {\n ret.storage[i] = f(self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n ret.storage[i] = f(self.get_unchecked(i));\n }\n }\n }\n\n ret\n }\n\n /// Creates a new vector of equal size by calling a closure on each element\n /// in this vector, along with its index.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let result = vec.mapi(|i, value| i + value * 2);\n ///\n /// let expected = BoundedVec::from_array([2, 5, 8, 11]);\n /// assert_eq(result, expected);\n /// ```\n pub fn mapi(self, f: fn[Env](u32, T) -> U) -> BoundedVec {\n let mut ret = BoundedVec::new();\n ret.len = self.len();\n\n if is_unconstrained() {\n for i in 0..self.len() {\n ret.storage[i] = f(i, self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n ret.storage[i] = f(i, self.get_unchecked(i));\n }\n }\n }\n\n ret\n }\n\n /// Calls a closure on each element in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let mut result = BoundedVec::::new();\n /// vec.for_each(|value| result.push(value * 2));\n ///\n /// let expected = BoundedVec::from_array([2, 4, 6, 8]);\n /// assert_eq(result, expected);\n /// ```\n pub fn for_each(self, f: fn[Env](T) -> ()) {\n if is_unconstrained() {\n for i in 0..self.len() {\n f(self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n f(self.get_unchecked(i));\n }\n }\n }\n }\n\n /// Calls a closure on each element in this vector, along with its index.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let mut result = BoundedVec::::new();\n /// vec.for_eachi(|i, value| result.push(i + value * 2));\n ///\n /// let expected = BoundedVec::from_array([2, 5, 8, 11]);\n /// assert_eq(result, expected);\n /// ```\n pub fn for_eachi(self, f: fn[Env](u32, T) -> ()) {\n if is_unconstrained() {\n for i in 0..self.len() {\n f(i, self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n f(i, self.get_unchecked(i));\n }\n }\n }\n }\n\n /// Creates a new BoundedVec from the given array and length.\n /// The given length must be less than or equal to the length of the array.\n ///\n /// This function will zero out any elements at or past index `len` of `array`.\n /// This incurs an extra runtime cost of O(MaxLen). If you are sure your array is\n /// zeroed after that index, you can use `from_parts_unchecked` to remove the extra loop.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_parts([1, 2, 3, 0], 3);\n /// assert_eq(vec.len(), 3);\n /// ```\n pub fn from_parts(mut array: [T; MaxLen], len: u32) -> Self {\n assert(len <= MaxLen);\n let zeroed = crate::mem::zeroed();\n\n if is_unconstrained() {\n for i in len..MaxLen {\n array[i] = zeroed;\n }\n } else {\n for i in 0..MaxLen {\n if i >= len {\n array[i] = zeroed;\n }\n }\n }\n\n BoundedVec { storage: array, len }\n }\n\n /// Creates a new BoundedVec from the given array and length.\n /// The given length must be less than or equal to the length of the array.\n ///\n /// This function is unsafe because it expects all elements past the `len` index\n /// of `array` to be zeroed, but does not check for this internally. Use `from_parts`\n /// for a safe version of this function which does zero out any indices past the\n /// given length. Invalidating this assumption can notably cause `BoundedVec::eq`\n /// to give incorrect results since it will check even elements past `len`.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 0], 3);\n /// assert_eq(vec.len(), 3);\n ///\n /// // invalid use!\n /// let vec1: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 1], 3);\n /// let vec2: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 2], 3);\n ///\n /// // both vecs have length 3 so we'd expect them to be equal, but this\n /// // fails because elements past the length are still checked in eq\n /// assert_eq(vec1, vec2); // fails\n /// ```\n pub fn from_parts_unchecked(array: [T; MaxLen], len: u32) -> Self {\n assert(len <= MaxLen);\n BoundedVec { storage: array, len }\n }\n}\n\nimpl Eq for BoundedVec\nwhere\n T: Eq,\n{\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 if self.len == other.len {\n self.storage == other.storage\n } else {\n false\n }\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\n mod get {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test(should_fail_with = \"Attempted to read past end of BoundedVec\")]\n fn panics_when_reading_elements_past_end_of_vec() {\n let vec: BoundedVec = BoundedVec::new();\n\n let _ = vec.get(0);\n }\n\n #[test(should_fail_with = \"Attempted to read past end of BoundedVec\")]\n fn panics_when_reading_beyond_length() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n let _ = vec.get(3);\n }\n\n #[test]\n fn get_works_within_bounds() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(2), 3);\n assert_eq(vec.get(4), 5);\n }\n\n #[test]\n fn get_unchecked_works() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n assert_eq(vec.get_unchecked(0), 1);\n assert_eq(vec.get_unchecked(2), 3);\n }\n\n #[test]\n fn get_unchecked_works_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n assert_eq(vec.get_unchecked(4), 0);\n }\n }\n\n mod set {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn set_updates_values_properly() {\n let mut vec = BoundedVec::from_array([0, 0, 0, 0, 0]);\n\n vec.set(0, 42);\n assert_eq(vec.storage, [42, 0, 0, 0, 0]);\n\n vec.set(1, 43);\n assert_eq(vec.storage, [42, 43, 0, 0, 0]);\n\n vec.set(2, 44);\n assert_eq(vec.storage, [42, 43, 44, 0, 0]);\n\n vec.set(1, 10);\n assert_eq(vec.storage, [42, 10, 44, 0, 0]);\n\n vec.set(0, 0);\n assert_eq(vec.storage, [0, 10, 44, 0, 0]);\n }\n\n #[test(should_fail_with = \"Attempted to write past end of BoundedVec\")]\n fn panics_when_writing_elements_past_end_of_vec() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.set(0, 42);\n }\n\n #[test(should_fail_with = \"Attempted to write past end of BoundedVec\")]\n fn panics_when_setting_beyond_length() {\n let mut vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.set(3, 4);\n }\n\n #[test]\n fn set_unchecked_operations() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n\n vec.set_unchecked(0, 10);\n assert_eq(vec.get(0), 10);\n }\n\n #[test(should_fail_with = \"Attempted to read past end of BoundedVec\")]\n fn set_unchecked_operations_past_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n\n vec.set_unchecked(3, 40);\n assert_eq(vec.get(3), 40);\n }\n\n #[test]\n fn set_preserves_other_elements() {\n let mut vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n\n vec.set(2, 30);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 30);\n assert_eq(vec.get(3), 4);\n assert_eq(vec.get(4), 5);\n }\n }\n\n mod any {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn returns_false_if_predicate_not_satisfied() {\n let vec: BoundedVec = BoundedVec::from_array([false, false, false, false]);\n let result = vec.any(|value| value);\n\n assert(!result);\n }\n\n #[test]\n fn returns_true_if_predicate_satisfied() {\n let vec: BoundedVec = BoundedVec::from_array([false, false, true, true]);\n let result = vec.any(|value| value);\n\n assert(result);\n }\n\n #[test]\n fn returns_false_on_empty_boundedvec() {\n let vec: BoundedVec = BoundedVec::new();\n let result = vec.any(|value| value);\n\n assert(!result);\n }\n\n #[test]\n fn any_with_complex_predicates() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n\n assert(vec.any(|x| x > 3));\n assert(!vec.any(|x| x > 10));\n assert(vec.any(|x| x % 2 == 0)); // has a even number\n assert(vec.any(|x| x == 3)); // has a specific value\n }\n\n #[test]\n fn any_with_partial_vector() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n\n assert(vec.any(|x| x == 1));\n assert(vec.any(|x| x == 2));\n assert(!vec.any(|x| x == 3));\n }\n }\n\n mod map {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn applies_function_correctly() {\n // docs:start:bounded-vec-map-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|value| value * 2);\n // docs:end:bounded-vec-map-example\n let expected = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|value| (value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = vec.map(|value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn map_with_conditional_logic() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n\n let result = vec.map(|x| if x % 2 == 0 { x * 2 } else { x });\n let expected = BoundedVec::from_array([1, 4, 3, 8]);\n assert_eq(result, expected);\n }\n\n #[test]\n fn map_preserves_length() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|x| x * 2);\n\n assert_eq(result.len(), vec.len());\n assert_eq(result.max_len(), vec.max_len());\n }\n\n #[test]\n fn map_on_empty_vector() {\n let vec: BoundedVec = BoundedVec::new();\n let result = vec.map(|x| x * 2);\n assert_eq(result, vec);\n assert_eq(result.len(), 0);\n assert_eq(result.max_len(), 5);\n }\n }\n\n mod mapi {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn applies_function_correctly() {\n // docs:start:bounded-vec-mapi-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.mapi(|i, value| i + value * 2);\n // docs:end:bounded-vec-mapi-example\n let expected = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.mapi(|i, value| (i + value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = vec.mapi(|_, value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn mapi_with_index_branching_logic() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n\n let result = vec.mapi(|i, x| if i % 2 == 0 { x * 2 } else { x });\n let expected = BoundedVec::from_array([2, 2, 6, 4]);\n assert_eq(result, expected);\n }\n }\n\n mod for_each {\n use crate::collections::bounded_vec::BoundedVec;\n\n // map in terms of for_each\n fn for_each_map(\n input: BoundedVec,\n f: fn[Env](T) -> U,\n ) -> BoundedVec {\n let mut output = BoundedVec::::new();\n let output_ref = &mut output;\n input.for_each(|x| output_ref.push(f(x)));\n output\n }\n\n #[test]\n fn smoke_test() {\n let mut acc = 0;\n let acc_ref = &mut acc;\n // docs:start:bounded-vec-for-each-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.for_each(|value| { *acc_ref += value; });\n // docs:end:bounded-vec-for-each-example\n assert_eq(acc, 6);\n }\n\n #[test]\n fn applies_function_correctly() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_each_map(vec, |value| value * 2);\n let expected = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_each_map(vec, |value| (value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = for_each_map(vec, |value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn for_each_on_empty_vector() {\n let vec: BoundedVec = BoundedVec::new();\n let mut count = 0;\n let count_ref = &mut count;\n vec.for_each(|_| { *count_ref += 1; });\n assert_eq(count, 0);\n }\n\n #[test]\n fn for_each_with_side_effects() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n let mut seen = BoundedVec::::new();\n let seen_ref = &mut seen;\n vec.for_each(|x| seen_ref.push(x));\n assert_eq(seen, vec);\n }\n }\n\n mod for_eachi {\n use crate::collections::bounded_vec::BoundedVec;\n\n // mapi in terms of for_eachi\n fn for_eachi_mapi(\n input: BoundedVec,\n f: fn[Env](u32, T) -> U,\n ) -> BoundedVec {\n let mut output = BoundedVec::::new();\n let output_ref = &mut output;\n input.for_eachi(|i, x| output_ref.push(f(i, x)));\n output\n }\n\n #[test]\n fn smoke_test() {\n let mut acc = 0;\n let acc_ref = &mut acc;\n // docs:start:bounded-vec-for-eachi-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.for_eachi(|i, value| { *acc_ref += i * value; });\n // docs:end:bounded-vec-for-eachi-example\n\n // 0 * 1 + 1 * 2 + 2 * 3\n assert_eq(acc, 8);\n }\n\n #[test]\n fn applies_function_correctly() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_eachi_mapi(vec, |i, value| i + value * 2);\n let expected = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_eachi_mapi(vec, |i, value| (i + value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = for_eachi_mapi(vec, |_, value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn for_eachi_on_empty_vector() {\n let vec: BoundedVec = BoundedVec::new();\n let mut count = 0;\n let count_ref = &mut count;\n vec.for_eachi(|_, _| { *count_ref += 1; });\n assert_eq(count, 0);\n }\n\n #[test]\n fn for_eachi_with_index_tracking() {\n let vec: BoundedVec = BoundedVec::from_array([10, 20, 30]);\n let mut indices = BoundedVec::::new();\n let indices_ref = &mut indices;\n vec.for_eachi(|i, _| indices_ref.push(i));\n\n let expected = BoundedVec::from_array([0, 1, 2]);\n assert_eq(indices, expected);\n }\n\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.get(0), 1);\n assert_eq(bounded_vec.get(1), 2);\n assert_eq(bounded_vec.get(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 #[test]\n fn from_array_preserves_order() {\n let array = [5, 3, 1, 4, 2];\n let vec: BoundedVec = BoundedVec::from_array(array);\n for i in 0..array.len() {\n assert_eq(vec.get(i), array[i]);\n }\n }\n\n #[test]\n fn from_array_with_different_types() {\n let bool_array = [true, false, true];\n let bool_vec: BoundedVec = BoundedVec::from_array(bool_array);\n assert_eq(bool_vec.len(), 3);\n assert_eq(bool_vec.get(0), true);\n assert_eq(bool_vec.get(1), false);\n }\n }\n\n mod trait_from {\n use crate::collections::bounded_vec::BoundedVec;\n use crate::convert::From;\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.get(0), 1);\n assert_eq(bounded_vec.get(1), 2);\n }\n }\n\n mod trait_eq {\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\n mod from_parts {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn from_parts() {\n // docs:start:from-parts\n let vec: BoundedVec = BoundedVec::from_parts([1, 2, 3, 0], 3);\n assert_eq(vec.len(), 3);\n\n // Any elements past the given length are zeroed out, so these\n // two BoundedVecs will be completely equal\n let vec1: BoundedVec = BoundedVec::from_parts([1, 2, 3, 1], 3);\n let vec2: BoundedVec = BoundedVec::from_parts([1, 2, 3, 2], 3);\n assert_eq(vec1, vec2);\n // docs:end:from-parts\n }\n\n #[test]\n fn from_parts_unchecked() {\n // docs:start:from-parts-unchecked\n let vec: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 0], 3);\n assert_eq(vec.len(), 3);\n\n // invalid use!\n let vec1: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 1], 3);\n let vec2: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 2], 3);\n\n // both vecs have length 3 so we'd expect them to be equal, but this\n // fails because elements past the length are still checked in eq\n assert(vec1 != vec2);\n // docs:end:from-parts-unchecked\n }\n }\n\n mod push_pop {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn push_and_pop_operations() {\n let mut vec: BoundedVec = BoundedVec::new();\n\n assert_eq(vec.len(), 0);\n\n vec.push(1);\n assert_eq(vec.len(), 1);\n assert_eq(vec.get(0), 1);\n\n vec.push(2);\n assert_eq(vec.len(), 2);\n assert_eq(vec.get(1), 2);\n\n let popped = vec.pop();\n assert_eq(popped, 2);\n assert_eq(vec.len(), 1);\n\n let popped2 = vec.pop();\n assert_eq(popped2, 1);\n assert_eq(vec.len(), 0);\n }\n\n #[test(should_fail_with = \"push out of bounds\")]\n fn push_to_full_vector() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n vec.push(3); // should panic\n }\n\n #[test(should_fail_with = \"cannot pop from an empty vector\")]\n fn pop_from_empty_vector() {\n let mut vec: BoundedVec = BoundedVec::new();\n let _ = vec.pop(); // should panic\n }\n\n #[test]\n fn push_pop_cycle() {\n let mut vec: BoundedVec = BoundedVec::new();\n\n // push to full\n vec.push(1);\n vec.push(2);\n vec.push(3);\n assert_eq(vec.len(), 3);\n\n // pop all\n assert_eq(vec.pop(), 3);\n assert_eq(vec.pop(), 2);\n assert_eq(vec.pop(), 1);\n assert_eq(vec.len(), 0);\n\n // push again\n vec.push(4);\n assert_eq(vec.len(), 1);\n assert_eq(vec.get(0), 4);\n }\n }\n\n mod extend {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn extend_from_array() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_array([2, 3]);\n\n assert_eq(vec.len(), 3);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 3);\n }\n\n #[test]\n fn extend_from_slice() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_slice(&[2, 3]);\n\n assert_eq(vec.len(), 3);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 3);\n }\n\n #[test]\n fn extend_from_bounded_vec() {\n let mut vec1: BoundedVec = BoundedVec::new();\n let mut vec2: BoundedVec = BoundedVec::new();\n\n vec1.push(1);\n vec2.push(2);\n vec2.push(3);\n\n vec1.extend_from_bounded_vec(vec2);\n\n assert_eq(vec1.len(), 3);\n assert_eq(vec1.get(0), 1);\n assert_eq(vec1.get(1), 2);\n assert_eq(vec1.get(2), 3);\n }\n\n #[test(should_fail_with = \"extend_from_array out of bounds\")]\n fn extend_array_beyond_max_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_array([2, 3, 4]); // should panic\n }\n\n #[test(should_fail_with = \"extend_from_slice out of bounds\")]\n fn extend_slice_beyond_max_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_slice(&[2, 3, 4]); // S]should panic\n }\n\n #[test(should_fail_with = \"extend_from_bounded_vec out of bounds\")]\n fn extend_bounded_vec_beyond_max_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n let other: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n vec.extend_from_bounded_vec(other); // should panic\n }\n\n #[test]\n fn extend_with_empty_collections() {\n let mut vec: BoundedVec = BoundedVec::new();\n let original_len = vec.len();\n\n vec.extend_from_array([]);\n assert_eq(vec.len(), original_len);\n\n vec.extend_from_slice(&[]);\n assert_eq(vec.len(), original_len);\n\n let empty: BoundedVec = BoundedVec::new();\n vec.extend_from_bounded_vec(empty);\n assert_eq(vec.len(), original_len);\n }\n }\n\n mod storage {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn storage_consistency() {\n let mut vec: BoundedVec = BoundedVec::new();\n\n // test initial storage state\n assert_eq(vec.storage(), [0, 0, 0, 0, 0]);\n\n vec.push(1);\n vec.push(2);\n\n // test storage after modifications\n assert_eq(vec.storage(), [1, 2, 0, 0, 0]);\n\n // storage doesn't change length\n assert_eq(vec.len(), 2);\n assert_eq(vec.max_len(), 5);\n }\n\n #[test]\n fn storage_after_pop() {\n let mut vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n\n let _ = vec.pop();\n // after pop, the last element should be zeroed\n assert_eq(vec.storage(), [1, 2, 0]);\n assert_eq(vec.len(), 2);\n }\n\n #[test]\n fn vector_immutable() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n let storage = vec.storage();\n\n assert_eq(storage, [1, 2, 3]);\n\n // Verify that the original vector is unchanged\n assert_eq(vec.len(), 3);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 3);\n }\n }\n}\n" + }, + "60": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/capsules/mod.nr", + "source": "use crate::oracle::capsules;\nuse protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}};\n\n/// A dynamically sized array backed by PXE's non-volatile database (called capsules). Values are persisted until\n/// deleted, so they can be e.g. stored during simulation of a transaction and later retrieved during witness\n/// generation. All values are scoped per contract address, so external contracts cannot access them.\npub struct CapsuleArray {\n contract_address: AztecAddress,\n /// The base slot is where the array length is stored in capsules. Array elements are stored in consecutive slots\n /// after the base slot. For example, with base slot 5: the length is at slot 5, the first element (index 0) is at\n /// slot 6, the second element (index 1) is at slot 7, and so on.\n base_slot: Field,\n}\n\nimpl CapsuleArray {\n /// Returns a CapsuleArray connected to a contract's capsules at a base slot. Array elements are stored in\n /// contiguous slots following the base slot, so there should be sufficient space between array base slots to\n /// accommodate elements. A reasonable strategy is to make the base slot a hash of a unique value.\n pub unconstrained fn at(contract_address: AztecAddress, base_slot: Field) -> Self {\n Self { contract_address, base_slot }\n }\n\n /// Returns the number of elements stored in the array.\n pub unconstrained fn len(self) -> u32 {\n // An uninitialized array defaults to a length of 0.\n capsules::load(self.contract_address, self.base_slot).unwrap_or(0) as u32\n }\n\n /// Stores a value at the end of the array.\n pub unconstrained fn push(self, value: T)\n where\n T: Serialize,\n {\n let current_length = self.len();\n\n // The slot corresponding to the index `current_length` is the first slot immediately after the end of the\n // array, which is where we want to place the new value.\n capsules::store(self.contract_address, self.slot_at(current_length), value);\n\n // Then we simply update the length.\n let new_length = current_length + 1;\n capsules::store(self.contract_address, self.base_slot, new_length);\n }\n\n /// Retrieves the value stored in the array at `index`. Throws if the index is out of bounds.\n pub unconstrained fn get(self, index: u32) -> T\n where\n T: Deserialize,\n {\n assert(index < self.len(), \"Attempted to read past the length of a CapsuleArray\");\n\n capsules::load(self.contract_address, self.slot_at(index)).unwrap()\n }\n\n /// Deletes the value stored in the array at `index`. Throws if the index is out of bounds.\n pub unconstrained fn remove(self, index: u32) {\n let current_length = self.len();\n assert(index < current_length, \"Attempted to delete past the length of a CapsuleArray\");\n\n // In order to be able to remove elements at arbitrary indices, we need to shift the entire contents of the\n // array past the removed element one slot backward so that we don't end up with a gap and preserve the\n // contiguous slots. We can skip this when deleting the last element however.\n if index != current_length - 1 {\n // The source and destination regions overlap, but `copy` supports this.\n capsules::copy(\n self.contract_address,\n self.slot_at(index + 1),\n self.slot_at(index),\n current_length - index - 1,\n );\n }\n\n // We can now delete the last element (which has either been copied to the slot immediately before it, or was\n // the element we meant to delete in the first place) and update the length.\n capsules::delete(self.contract_address, self.slot_at(current_length - 1));\n capsules::store(self.contract_address, self.base_slot, current_length - 1);\n }\n\n /// Iterates over the entire array, calling the callback with all values and their array index. The order in which\n /// values are processed is arbitrary.\n ///\n /// It is safe to delete the current element (and only the current element) from inside the callback via `remove`:\n /// ```noir\n /// array.for_each(|index, value| {\n /// if some_condition(value) {\n /// array.remove(index); // safe only for this index\n /// }\n /// }\n /// ```\n ///\n /// If all elements in the array need to iterated over and then removed, then using `for_each` results in optimal\n /// efficiency.\n ///\n /// It is **not** safe to push new elements into the array from inside the callback.\n pub unconstrained fn for_each(self, f: unconstrained fn[Env](u32, T) -> ())\n where\n T: Deserialize,\n {\n // Iterating over all elements is simple, but we want to do it in such a way that a) deleting the current\n // element is safe to do, and b) deleting *all* elements is optimally efficient. This is because CapsuleArrays\n // are typically used to hold pending tasks, so iterating them while clearing completed tasks (sometimes\n // unconditionally, resulting in a full clear) is a very common access pattern.\n //\n // The way we achieve this is by iterating backwards: each element can always be deleted since it won't change\n // any preceding (lower) indices, and if every element is deleted then every element will (in turn) be the last\n // element. This results in an optimal full clear since `remove` will be able to skip the `capsules::copy` call\n // to shift any elements past the deleted one (because there will be none).\n let mut i = self.len();\n while i > 0 {\n i -= 1;\n f(i, self.get(i));\n }\n }\n\n unconstrained fn slot_at(self, index: u32) -> Field {\n // Elements are stored immediately after the base slot, so we add 1 to it to compute the slot for the first\n // element.\n self.base_slot + 1 + index as Field\n }\n}\n\nmod test {\n use crate::test::helpers::test_environment::TestEnvironment;\n use super::CapsuleArray;\n\n global SLOT: Field = 1230;\n\n #[test]\n unconstrained fn empty_array() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array: CapsuleArray = CapsuleArray::at(contract_address, SLOT);\n assert_eq(array.len(), 0);\n });\n }\n\n #[test(should_fail_with = \"Attempted to read past the length of a CapsuleArray\")]\n unconstrained fn empty_array_read() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n let _: Field = array.get(0);\n });\n }\n\n #[test]\n unconstrained fn array_push() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n array.push(5);\n\n assert_eq(array.len(), 1);\n assert_eq(array.get(0), 5);\n });\n }\n\n #[test(should_fail_with = \"Attempted to read past the length of a CapsuleArray\")]\n unconstrained fn read_past_len() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n array.push(5);\n\n let _ = array.get(1);\n });\n }\n\n #[test]\n unconstrained fn array_remove_last() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(5);\n array.remove(0);\n\n assert_eq(array.len(), 0);\n });\n }\n\n #[test]\n unconstrained fn array_remove_some() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(7);\n array.push(8);\n array.push(9);\n\n assert_eq(array.len(), 3);\n assert_eq(array.get(0), 7);\n assert_eq(array.get(1), 8);\n assert_eq(array.get(2), 9);\n\n array.remove(1);\n\n assert_eq(array.len(), 2);\n assert_eq(array.get(0), 7);\n assert_eq(array.get(1), 9);\n });\n }\n\n #[test]\n unconstrained fn array_remove_all() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(7);\n array.push(8);\n array.push(9);\n\n array.remove(1);\n array.remove(1);\n array.remove(0);\n\n assert_eq(array.len(), 0);\n });\n }\n\n #[test]\n unconstrained fn for_each_called_with_all_elements() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n // We store all values that we were called with and check that all (value, index) tuples are present. Note that\n // we do not care about the order in which each tuple was passed to the closure.\n let called_with = &mut BoundedVec::<(u32, Field), 3>::new();\n array.for_each(|index, value| { called_with.push((index, value)); });\n\n assert_eq(called_with.len(), 3);\n assert(called_with.any(|(index, value)| (index == 0) & (value == 4)));\n assert(called_with.any(|(index, value)| (index == 1) & (value == 5)));\n assert(called_with.any(|(index, value)| (index == 2) & (value == 6)));\n });\n }\n\n #[test]\n unconstrained fn for_each_remove_some() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n array.for_each(|index, _| {\n if index == 1 {\n array.remove(index);\n }\n });\n\n assert_eq(array.len(), 2);\n assert_eq(array.get(0), 4);\n assert_eq(array.get(1), 6);\n });\n }\n\n #[test]\n unconstrained fn for_each_remove_all() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n array.for_each(|index, _| { array.remove(index); });\n\n assert_eq(array.len(), 0);\n });\n }\n\n #[test]\n unconstrained fn for_each_remove_all_no_copy() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n // We test that the utilityCopyCapsule was never called, which is the expensive operation we want to avoid.\n let mock = std::test::OracleMock::mock(\"utilityCopyCapsule\");\n\n array.for_each(|index, _| { array.remove(index); });\n\n assert_eq(mock.times_called(), 0);\n });\n }\n}\n" + }, + "61": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr", + "source": "use dep::protocol_types::{\n abis::function_selector::FunctionSelector,\n address::AztecAddress,\n traits::{Deserialize, ToField},\n};\n\nuse crate::context::{gas::GasOpts, private_context::PrivateContext, public_context::PublicContext};\nuse crate::hash::{hash_args, hash_calldata};\nuse crate::oracle::execution_cache;\n\npub trait CallInterface {\n fn get_args(self) -> [Field];\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\n// PrivateCallInterface\n\npub struct PrivateCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n return_type: T,\n is_static: bool,\n}\n\nimpl PrivateCallInterface\nwhere\n T: Deserialize,\n{\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n is_static: bool,\n ) -> Self {\n let args_hash = hash_args(args);\n Self {\n target_contract,\n selector,\n name,\n args_hash,\n args,\n return_type: std::mem::zeroed(),\n is_static,\n }\n }\n\n /// Makes the call to this private function.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n /// This enables contracts to interact with each other while maintaining\n /// privacy. This \"composability\" of private contract functions is a key\n /// feature of the Aztec network.\n ///\n /// If a user's transaction includes multiple private function calls, then\n /// by the design of Aztec, the following information will remain private[1]:\n /// - The function selectors and contract addresses of all private function\n /// calls will remain private, so an observer of the public mempool will\n /// not be able to look at a tx and deduce which private functions have\n /// been executed.\n /// - The arguments and return values of all private function calls will\n /// remain private.\n /// - The person who initiated the tx will remain private.\n /// - The notes and nullifiers and private logs that are emitted by all\n /// private function calls will (if designed well) not leak any user\n /// secrets, nor leak which functions have been executed.\n ///\n /// [1] Caveats: Some of these privacy guarantees depend on how app\n /// developers design their smart contracts. Some actions _can_ leak\n /// information, such as:\n /// - Calling an internal public function.\n /// - Calling a public function and not setting msg_sender to Option::none\n /// (see https://github.com/AztecProtocol/aztec-packages/pull/16433)\n /// - Calling any public function will always leak details about the nature\n /// of the transaction, so devs should be careful in their contract\n /// designs. If it can be done in a private function, then that will give\n /// the best privacy.\n /// - Not padding the side-effects of a tx to some standardised, uniform\n /// size. The kernel circuits can take hints to pad side-effects, so a\n /// wallet should be able to request for a particular amount of padding.\n /// Wallets should ideally agree on some standard.\n /// - Padding should include:\n /// - Padding the lengths of note & nullifier arrays\n /// - Padding private logs with random fields, up to some standardised\n /// size.\n /// See also: https://docs.aztec.network/developers/reference/considerations/privacy_considerations\n ///\n /// # Advanced\n /// * The call is added to the private call stack and executed by kernel\n /// circuits after this function completes\n /// * The called function can modify its own contract's private state\n /// * Side effects from the called function are included in this transaction\n /// * The call inherits the current transaction's context and gas limits\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n pub fn call(self, context: &mut PrivateContext) -> T {\n execution_cache::store(self.args, self.args_hash);\n let returns_hash = context.call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n false,\n );\n\n // If T is () (i.e. if the function does not return anything) then `get_preimage` will constrain that the\n // returns hash is empty as per the protocol rules.\n returns_hash.get_preimage()\n }\n\n /// Makes a _read-only_ call to this private function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state, emit L2->L1 messages, nor emit events. Any nested\n /// calls are constrained to also be staticcalls.\n ///\n /// See `call` for more general info on private function calls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n pub fn view(self, context: &mut PrivateContext) -> T {\n execution_cache::store(self.args, self.args_hash);\n let returns_hash = context.call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n true,\n );\n // If T is () (i.e. if the function does not return anything) then `get_preimage` will constrain that the\n // returns hash is empty as per the protocol rules.\n returns_hash.get_preimage()\n }\n}\n\nimpl CallInterface for PrivateCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// PrivateStaticCallInterface\n\npub struct PrivateStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n return_type: T,\n is_static: bool,\n}\n\nimpl PrivateStaticCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n ) -> Self {\n let args_hash = hash_args(args);\n Self {\n target_contract,\n selector,\n name,\n args_hash,\n args,\n return_type: std::mem::zeroed(),\n is_static: true,\n }\n }\n\n /// Makes a read-only call to this private function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state, emit L2->L1 messages, nor emit events. Any nested\n /// calls are constrained to also be staticcalls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n pub fn view(self, context: &mut PrivateContext) -> T\n where\n T: Deserialize,\n {\n execution_cache::store(self.args, self.args_hash);\n let returns = context.call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n true,\n );\n returns.get_preimage()\n }\n}\n\nimpl CallInterface for PrivateStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// PublicCallInterface\n\npub struct PublicCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n return_type: T,\n is_static: bool,\n}\n\nimpl PublicCallInterface\nwhere\n T: Deserialize,\n{\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n is_static: bool,\n ) -> Self {\n Self {\n target_contract,\n selector,\n name,\n args,\n gas_opts: GasOpts::default(),\n return_type: std::mem::zeroed(),\n is_static,\n }\n }\n\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n /// Makes the call to this public function.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `context` - The PublicContext -- made magically available to the body\n /// of every #[public] function as `context`, through the\n /// #[public] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n pub unconstrained fn call(self, context: &mut PublicContext) -> T {\n let returns = context.call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n // If T is () (i.e. if the function does not return anything) then `as_array` will constrain that `returns` has\n // a length of 0 (since that is ()'s deserialization length).\n Deserialize::deserialize(returns.as_array())\n }\n\n /// Makes a read-only call to this public function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state or emit events. Any nested calls are constrained to\n /// also be staticcalls.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `context` - The PublicContext -- made magically available to the body\n /// of every #[public] function as `context`, through the\n /// #[public] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n pub unconstrained fn view(self, context: &mut PublicContext) -> T {\n let returns = context.static_call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n // If T is () (i.e. if the function does not return anything) then `as_array` will constrain that `returns` has\n // a length of 0 (since that is ()'s deserialization length).\n Deserialize::deserialize(returns.as_array())\n }\n\n /// Enqueues a call to this public function, to be executed later.\n ///\n /// Unlike private functions which execute immediately on the user's device,\n /// public function calls are \"enqueued\" and executed some time later by a\n /// block proposer.\n ///\n /// This means a public function cannot return any values back to a private\n /// function, because by the time the public function is being executed,\n /// the private function which called it has already completed execution.\n /// (In fact, the private function has been executed and proven, along with\n /// all other private function calls of the user's tx. A single proof of the\n /// tx has been submitted to the Aztec network, and some time later a\n /// proposer has picked the tx up from the mempool and begun executing all\n /// of the enqueued public functions).\n ///\n /// # Privacy warning\n /// Enqueueing a public function call is an inherently leaky action.\n /// Many interesting applications will require some interaction with public\n /// state, but smart contract developers should try to use public function\n /// calls sparingly, and carefully.\n /// _Internal_ public function calls are especially leaky, because they\n /// completely leak which private contract made the call.\n /// See also: https://docs.aztec.network/developers/reference/considerations/privacy_considerations\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n pub fn enqueue(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n false,\n )\n }\n\n /// Enqueues a read-only call to this public function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state, emit L2->L1 messages, nor emit events. Any nested\n /// calls are constrained to also be staticcalls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n true,\n )\n }\n\n /// Enqueues a call to this public function, and designates it to be the\n /// teardown function for this tx. Only one teardown function call can be\n /// made by a tx.\n ///\n /// Niche function: Only wallet developers and paymaster contract developers\n /// (aka Fee-payment contracts) will need to make use of this function.\n ///\n /// Aztec supports a three-phase execution model: setup, app logic, teardown.\n /// The phases exist to enable a fee payer to take on the risk of paying\n /// a transaction fee, safe in the knowledge that their payment (in whatever\n /// token or method the user chooses) will succeed, regardless of whether\n /// the app logic will succeed. The \"setup\" phase ensures the fee payer\n /// has sufficient balance to pay the proposer their fees.\n /// The teardown phase is primarily intended to: calculate exactly\n /// how much the user owes, based on gas consumption, and refund the user\n /// any change.\n ///\n /// Note: in some cases, the cost of refunding the user (i.e. DA costs of\n /// tx side-effects) might exceed the refund amount. For app logic with\n /// fairly stable and predictable gas consumption, a material refund amount\n /// is unlikely. For app logic with unpredictable gas consumption, a\n /// refund might be important to the user (e.g. if a hefty function reverts\n /// very early). Wallet/FPC/Paymaster developers should be mindful of this.\n ///\n /// See `enqueue` for more information about enqueuing public function calls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n pub fn set_as_teardown(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.set_public_teardown_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n false,\n )\n }\n}\n\nimpl CallInterface for PublicCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// PublicStaticCallInterface\n\npub struct PublicStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n return_type: T,\n is_static: bool,\n gas_opts: GasOpts,\n}\n\nimpl PublicStaticCallInterface\nwhere\n T: Deserialize,\n{\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n ) -> Self {\n Self {\n target_contract,\n selector,\n name,\n args,\n return_type: std::mem::zeroed(),\n is_static: true,\n gas_opts: GasOpts::default(),\n }\n }\n\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n /// Makes the read-only call to this public function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state or emit events. Any nested calls are constrained to\n /// also be staticcalls.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `context` - The PublicContext -- made magically available to the body\n /// of every #[public] function as `context`, through the\n /// #[public] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n pub unconstrained fn view(self, context: &mut PublicContext) -> T {\n let returns = context.static_call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n Deserialize::deserialize(returns.as_array())\n }\n\n /// Enqueues a read-only call to this public function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state, emit L2->L1 messages, nor emit events. Any nested\n /// calls are constrained to also be staticcalls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n true,\n )\n }\n}\n\nimpl CallInterface for PublicStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// UtilityCallInterface\n\npub struct UtilityCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n return_type: T,\n}\n\nimpl CallInterface for UtilityCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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 false\n }\n}\n\nimpl UtilityCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n ) -> Self {\n let args_hash = hash_args(args);\n Self { target_contract, selector, name, args_hash, args, return_type: std::mem::zeroed() }\n }\n\n pub fn get_args(self) -> [Field] {\n self.args\n }\n\n pub fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n pub fn get_name(self) -> str {\n self.name\n }\n\n pub fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n}\n" + }, + "68": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/context/private_context.nr", + "source": "use crate::{\n context::{inputs::PrivateContextInputs, returns_hash::ReturnsHash},\n hash::{ArgsHasher, hash_args_array, hash_calldata_array},\n keys::constants::{NULLIFIER_INDEX, NUM_KEY_TYPES, OUTGOING_INDEX, sk_generators},\n messaging::process_l1_to_l2_message,\n oracle::{\n block_header::get_block_header_at,\n call_private_function::call_private_function_internal,\n enqueue_public_function_call::{\n notify_enqueued_public_function_call, notify_set_min_revertible_side_effect_counter,\n notify_set_public_teardown_function_call,\n },\n execution_cache,\n key_validation_request::get_key_validation_request,\n logs::notify_created_contract_class_log,\n notes::{notify_created_nullifier, notify_nullified_note},\n },\n};\nuse dep::protocol_types::{\n abis::{\n block_header::BlockHeader,\n call_context::CallContext,\n function_selector::FunctionSelector,\n gas_settings::GasSettings,\n log_hash::LogHash,\n note_hash::NoteHash,\n nullifier::Nullifier,\n private_call_request::PrivateCallRequest,\n private_circuit_public_inputs::PrivateCircuitPublicInputs,\n private_log::{PrivateLog, PrivateLogData},\n public_call_request::PublicCallRequest,\n read_request::ReadRequest,\n side_effect::Counted,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n },\n address::{AztecAddress, EthAddress},\n constants::{\n CONTRACT_CLASS_LOG_SIZE_IN_FIELDS, MAX_CONTRACT_CLASS_LOGS_PER_CALL,\n MAX_ENQUEUED_CALLS_PER_CALL, MAX_INCLUDE_BY_TIMESTAMP_DURATION,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASHES_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PRIVATE_LOGS_PER_CALL,\n PRIVATE_LOG_SIZE_IN_FIELDS,\n },\n hash::poseidon2_hash,\n messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Empty, Hash, ToField},\n utils::arrays::{ClaimedLengthArray, trimmed_array_length_hint},\n};\n\n/// # PrivateContext\n///\n/// The **main interface** between a #[private] function and the Aztec blockchain.\n///\n/// An instance of the PrivateContext is initialized automatically at the outset\n/// of every private function, within the #[private] macro, so you'll never\n/// need to consciously instantiate this yourself.\n///\n/// The instance is always named `context`, and it is always be available within\n/// the body of every #[private] function in your smart contract.\n///\n/// > For those used to \"vanilla\" Noir, it might be jarring to have access to\n/// > `context` without seeing a declaration `let context = PrivateContext::new(...)`\n/// > within the body of your function. This is just a consequence of using\n/// > macros to tidy-up verbose boilerplate. You can use `nargo expand` to\n/// > expand all macros, if you dare.\n///\n/// Typical usage for a smart contract developer will be to call getter\n/// methods of the PrivateContext.\n///\n/// _Pushing_ data and requests to the context is mostly handled within\n/// aztec-nr's own functions, so typically a smart contract developer won't\n/// need to call any setter methods directly.\n///\n/// > Advanced users might occasionally wish to push data to the context\n/// > directly for lower-level control. If you find yourself doing this, please\n/// > open an issue on GitHub to describe your use case: it might be that\n/// > new functionality should be added to aztec-nr.\n///\n/// ## Responsibilities\n/// - Exposes contextual data to a private function:\n/// - Data relating to how this private function was called.\n/// - msg_sender\n/// - this_address - (the contract address of the private function being\n/// executed)\n/// - See `CallContext` for more data.\n/// - Data relating to the transaction in which this private function is\n/// being executed.\n/// - chain_id\n/// - version\n/// - gas_settings\n/// - Provides state access:\n/// - Access to the \"Anchor block\" header.\n/// Recall, a private function cannot read from the \"current\" block header,\n/// but must read from some historical block header, because as soon as\n/// private function execution begins (asynchronously, on a user's device),\n/// the public state of the chain (the \"current state\") will have progressed\n/// forward. We call this reference the \"Anchor block\".\n/// See `BlockHeader`.\n/// - Enables consumption of L1->L2 messages.\n/// - Enables calls to functions of other smart contracts:\n/// - Private function calls\n/// - Enqueueing of public function call requests\n/// (Since public functions are executed at a later time, by a block\n/// proposer, we say they are \"enqueued\").\n/// - Writes data to the blockchain:\n/// - New notes\n/// - New nullifiers\n/// - Private logs (for sending encrypted note contents or encrypted events)\n/// - New L2->L1 messages.\n/// - Provides args to the private function (handled by the #[private] macro).\n/// - Returns the return values of this private function (handled by the\n/// #[private] macro).\n/// - Makes Key Validation Requests.\n/// - Private functions are not allowed to see master secret keys, because we\n/// do not trust them. They are instead given \"app-siloed\" secret keys with\n/// a claim that they relate to a master public key. They can then request\n/// validation of this claim, by making a \"key validation request\" to the\n/// protocol's kernel circuits (which _are_ allowed to see certain master\n/// secret keys).\n///\n/// ## Advanced Responsibilities\n///\n/// - Ultimately, the PrivateContext is responsible for constructing the\n/// PrivateCircuitPublicInputs of the private function being executed.\n/// All private functions on Aztec must have public inputs which adhere\n/// to the rigid layout of the PrivateCircuitPublicInputs, in order to be\n/// compatible with the protocol's kernel circuits.\n/// A well-known misnomer:\n/// - \"public inputs\" contain both inputs and outputs of this function.\n/// - By \"outputs\" we mean a lot more side-effects than just the\n/// \"return values\" of the function.\n/// - Most of the so-called \"public inputs\" are kept _private_, and never leak\n/// to the outside world, because they are 'swallowed' by the protocol's\n/// kernel circuits before the tx is sent to the network. Only the\n/// following are exposed to the outside world:\n/// - New note_hashes\n/// - New nullifiers\n/// - New private logs\n/// - New L2->L1 messages\n/// - New enqueued public function call requests\n/// All the above-listed arrays of side-effects can be padded by the\n/// user's wallet (through instructions to the kernel circuits, via the\n/// PXE) to obscure their true lengths.\n///\n/// ## Syntax Justification\n///\n/// Both user-defined functions _and_ most functions in aztec-nr need access to\n/// the PrivateContext instance to read/write data. This is why you'll see the\n/// arguably-ugly pervasiveness of the \"context\" throughout your smart contract\n/// and the aztec-nr library.\n/// For example, `&mut context` is prevalent. In some languages, you can access\n/// and mutate a global variable (such as a PrivateContext instance) from a\n/// function without polluting the function's parameters. With Noir, a function\n/// must explicitly pass control of a mutable variable to another function, by\n/// reference. Since many functions in aztec-nr need to be able to push new data\n/// to the PrivateContext, they need to be handed a mutable reference _to_ the\n/// context as a parameter.\n/// For example, `Context` is prevalent as a generic parameter, to give better\n/// type safety at compile time. Many `aztec-nr` functions don't make sense if\n/// they're called in a particular runtime (private, public or utility), and so\n/// are intentionally only implemented over certain\n/// [Private|Public|Utility]Context structs. This gives smart contract\n/// developers a much faster feedback loop if they're making a mistake, as an\n/// error will be thrown by the LSP or when they compile their contract.\n///\n#[derive(Eq)]\npub struct PrivateContext {\n // docs:start:private-context\n pub inputs: PrivateContextInputs,\n pub side_effect_counter: u32,\n\n pub min_revertible_side_effect_counter: u32,\n pub is_fee_payer: bool,\n\n pub args_hash: Field,\n pub return_hash: Field,\n\n pub include_by_timestamp: u64,\n\n pub note_hash_read_requests: BoundedVec,\n pub nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n pub note_hashes: BoundedVec,\n pub nullifiers: BoundedVec,\n\n pub private_call_requests: BoundedVec,\n pub public_call_requests: BoundedVec, MAX_ENQUEUED_CALLS_PER_CALL>,\n pub public_teardown_call_request: PublicCallRequest,\n pub l2_to_l1_msgs: BoundedVec, MAX_L2_TO_L1_MSGS_PER_CALL>,\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 pub historical_header: BlockHeader,\n\n pub private_logs: BoundedVec,\n pub contract_class_logs_hashes: BoundedVec, MAX_CONTRACT_CLASS_LOGS_PER_CALL>,\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 pub last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n let max_allowed_include_by_timestamp =\n inputs.historical_header.global_variables.timestamp + MAX_INCLUDE_BY_TIMESTAMP_DURATION;\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 include_by_timestamp: max_allowed_include_by_timestamp,\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n note_hashes: BoundedVec::new(),\n nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_requests: BoundedVec::new(),\n public_teardown_call_request: PublicCallRequest::empty(),\n l2_to_l1_msgs: BoundedVec::new(),\n private_logs: BoundedVec::new(),\n contract_class_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES],\n }\n }\n\n /// Returns the contract address that initiated this function call.\n ///\n /// This is similar to `msg.sender` in Solidity (hence the name).\n ///\n /// Important Note: Since Aztec doesn't have a concept of an EoA (\n /// Externally-owned Account), the msg_sender is \"undefined\" for the first\n /// function call of every transaction. A value of `-1` is returned in such\n /// cases.\n /// The first function call of a tx is likely to be a call to the user's\n /// account contract, so this quirk will most often be handled by account\n /// contract developers.\n ///\n /// TODO(https://github.com/AztecProtocol/aztec-packages/issues/14025) - we\n /// are considering making msg_sender: Option, since\n /// a returned value of `Option:none` will be clearer to developers.\n ///\n /// # Returns\n /// * `AztecAddress` - The address of the smart contract that called\n /// this function (be it an app contract or a user's account contract).\n /// Returns `-1` for the first function call of the tx.\n ///\n pub fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n /// Returns the contract address of the current function being executed.\n ///\n /// This is equivalent to `address(this)` in Solidity (hence the name).\n /// Use this to identify the current contract's address, commonly needed for\n /// access control or when interacting with other contracts.\n ///\n /// # Returns\n /// * `AztecAddress` - The contract address of the current function being\n /// executed.\n ///\n pub fn this_address(self) -> AztecAddress {\n self.inputs.call_context.contract_address\n }\n\n /// Returns the chain ID of the current network.\n ///\n /// This is similar to `block.chainid` in Solidity. Returns the unique\n /// identifier for the blockchain network this transaction is executing on.\n ///\n /// Helps prevent cross-chain replay attacks. Useful if implementing\n /// multi-chain contract logic.\n ///\n /// # Returns\n /// * `Field` - The chain ID as a field element\n ///\n pub fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n /// Returns the Aztec protocol version that this transaction is executing\n /// under. Different versions may have different rules, opcodes, or\n /// cryptographic primitives.\n ///\n /// This is similar to how Ethereum has different EVM versions.\n ///\n /// Useful for forward/backward compatibility checks\n ///\n /// Not to be confused with contract versions; this is the protocol version.\n ///\n /// # Returns\n /// * `Field` - The protocol version as a field element\n ///\n pub fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n /// Returns the gas settings for the current transaction.\n ///\n /// This provides information about gas limits and pricing for the\n /// transaction, similar to `tx.gasprice` and gas limits in Ethereum.\n /// However, Aztec has a more sophisticated gas model with separate\n /// accounting for L2 computation and data availability (DA) costs.\n ///\n /// # Returns\n /// * `GasSettings` - Struct containing gas limits and fee information\n ///\n pub fn gas_settings(self) -> GasSettings {\n self.inputs.tx_context.gas_settings\n }\n\n /// Returns the function selector of the currently executing function.\n ///\n /// Low-level function: Ordinarily, smart contract developers will not need\n /// to access this.\n ///\n /// This is similar to `msg.sig` in Solidity, which returns the first 4\n /// bytes of the function signature. In Aztec, the selector uniquely\n /// identifies which function within the contract is being called.\n ///\n /// # Returns\n /// * `FunctionSelector` - The 4-byte function identifier\n ///\n /// # Advanced\n /// Only #[private] functions have a function selector as a protocol-\n /// enshrined concept. The function selectors of private functions are\n /// baked into the preimage of the contract address, and are used by the\n /// protocol's kernel circuits to identify each private function and ensure\n /// the correct one is being executed.\n ///\n /// Used internally for function dispatch and call verification.\n ///\n pub fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n /// Returns the hash of the arguments passed to the current function.\n ///\n /// Very low-level function: You shouldn't need to call this. The #[private]\n /// macro calls this, and it makes the arguments neatly available to the\n /// body of your private function.\n ///\n /// # Returns\n /// * `Field` - Hash of the function arguments\n ///\n /// # Advanced\n /// * Arguments are hashed to reduce proof size and verification time\n /// * Enables efficient argument passing in recursive function calls\n /// * The hash can be used to retrieve the original arguments from the PXE.\n ///\n pub fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n /// Pushes a new note_hash to the Aztec blockchain's global Note Hash Tree\n /// (a state tree).\n ///\n /// A note_hash is a commitment to a piece of private state.\n ///\n /// Low-level function: Ordinarily, smart contract developers will not need\n /// to manually call this. Aztec-nr's state variables (see `../state_vars/`)\n /// are designed to understand when to create and push new note hashes.\n ///\n /// # Arguments\n /// * `note_hash` - The new note_hash.\n ///\n /// # Advanced\n /// From here, the protocol's kernel circuits will take over and insert the\n /// note_hash into the protocol's \"note hash tree\" (in the Base Rollup\n /// circuit).\n /// Before insertion, the protocol will:\n /// - \"Silo\" the `note_hash` with the contract address of this function,\n /// to yield a `siloed_note_hash`. This prevents state collisions\n /// between different smart contracts.\n /// - Ensure uniqueness of the `siloed_note_hash`, to prevent Faerie-Gold\n /// attacks, by hashing the `siloed_note_hash` with a unique value, to\n /// yield a `unique_siloed_note_hash` (see the protocol spec for more).\n ///\n /// In addition to calling this function, aztec-nr provides the contents\n /// of the newly-created note to the PXE, via the `notify_created_note`\n /// oracle.\n ///\n /// > Advanced users might occasionally wish to push data to the context\n /// > directly for lower-level control. If you find yourself doing this,\n /// > please open an issue on GitHub to describe your use case: it might be\n /// > that new functionality should be added to aztec-nr.\n ///\n pub fn push_note_hash(&mut self, note_hash: Field) {\n self.note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n /// Pushes a new nullifier to the Aztec blockchain's global Nullifier Tree\n /// (a state tree).\n ///\n /// See also: `push_nullifier_for_note_hash`.\n ///\n /// Low-level function: Ordinarily, smart contract developers will not need\n /// to manually call this. Aztec-nr's state variables (see `../state_vars/`)\n /// are designed to understand when to create and push new nullifiers.\n ///\n /// A nullifier can only be emitted once. Duplicate nullifier insertions are\n /// rejected by the protocol.\n ///\n /// Generally, a nullifier is emitted to prevent an action from happening\n /// more than once, in such a way that the action cannot be linked (by an\n /// observer of the blockchain) to any earlier transactions.\n ///\n /// I.e. a nullifier is a random-looking, but deterministic record of a\n /// private, one-time action, which does not leak what action has been\n /// taken, and which preserves the property of \"tx unlinkability\".\n ///\n /// Usually, a nullifier will be emitted to \"spend\" a note (a piece of\n /// private state), without revealing which specific note is being spent.\n ///\n /// (Important: in such cases, use the below `push_nullifier_for_note_hash`).\n ///\n /// Sometimes, a nullifier might be emitted completely unrelated to any\n /// notes. Examples include initialization of a new contract; initialization\n /// of a PrivateMutable, or signalling in Semaphore-like applications.\n /// This `push_nullifier` function serves such use cases.\n ///\n /// # Arguments\n /// * `nullifier`\n ///\n /// # Advanced\n /// From here, the protocol's kernel circuits will take over and insert the\n /// nullifier into the protocol's \"nullifier tree\" (in the Base Rollup\n /// circuit).\n /// Before insertion, the protocol will:\n /// - \"Silo\" the `nullifier` with the contract address of this function,\n /// to yield a `siloed_nullifier`. This prevents state collisions\n /// between different smart contracts.\n /// - Ensure the `siloed_nullifier` is unique (the nullifier tree is an\n /// indexed merkle tree which supports efficient non-membership proofs).\n ///\n pub fn push_nullifier(&mut self, nullifier: Field) {\n notify_created_nullifier(nullifier);\n self.nullifiers.push(\n Nullifier { value: nullifier, note_hash: 0, counter: self.next_counter() },\n );\n }\n\n /// Pushes a nullifier that corresponds to a specific note hash.\n ///\n /// Low-level function: Ordinarily, smart contract developers will not need\n /// to manually call this. Aztec-nr's state variables (see `../state_vars/`)\n /// are designed to understand when to create and push new nullifiers.\n ///\n /// This is a specialized version of `push_nullifier` that links a nullifier\n /// to the specific note hash it's nullifying. This is the most common\n /// usage pattern for nullifiers.\n /// See `push_nullifier` for more explanation on nullifiers.\n ///\n /// # Arguments\n /// * `nullifier`\n /// * `nullified_note_hash` - The note hash of the note being nullified\n ///\n /// # Advanced\n /// Important: usage of this function doesn't mean that the world will _see_\n /// that this nullifier relates to the given nullified_note_hash (as that\n /// would violate \"tx unlinkability\"); it simply informs the user's PXE\n /// about the relationship (via `notify_nullified_note`). The PXE can then\n /// use this information to feed hints to the kernel circuits for\n /// \"squashing\" purposes: If a note is nullified during the same tx which\n /// created it, we can \"squash\" (delete) the note and nullifier (and any\n /// private logs associated with the note), to save on data emission costs.\n ///\n pub fn push_nullifier_for_note_hash(&mut self, nullifier: Field, nullified_note_hash: Field) {\n let nullifier_counter = self.next_counter();\n notify_nullified_note(nullifier, nullified_note_hash, nullifier_counter);\n self.nullifiers.push(\n Nullifier {\n value: nullifier,\n note_hash: nullified_note_hash,\n counter: nullifier_counter,\n },\n );\n }\n\n /// Returns the anchor block header - the historical block header that this\n /// private function is reading from.\n ///\n /// A private function CANNOT read from the \"current\" block header,\n /// but must read from some historical block header, because as soon as\n /// private function execution begins (asynchronously, on a user's device),\n /// the public state of the chain (the \"current state\") will have progressed\n /// forward.\n ///\n /// # Returns\n /// * `BlockHeader` - The anchor block header.\n ///\n /// # Advanced\n /// * All private functions of a tx read from the same anchor block header.\n /// * The protocol asserts that the `include_by_timestamp` of every tx\n /// is at most 24 hours beyond the timestamp of the tx's chosen anchor\n /// block header. This enables the network's nodes to safely prune old txs\n /// from the mempool. Therefore, the chosen block header _must_ be one\n /// from within the last 24 hours.\n ///\n pub fn get_block_header(self) -> BlockHeader {\n self.historical_header\n }\n\n /// Returns the header of any historical block at or before the anchor\n /// block.\n ///\n /// This enables private contracts to access information from even older\n /// blocks than the anchor block header.\n ///\n /// Useful for time-based contract logic that needs to compare against\n /// multiple historical points.\n ///\n /// # Arguments\n /// * `block_number` - The block number to retrieve (must be <= anchor\n /// block number)\n ///\n /// # Returns\n /// * `BlockHeader` - The header of the requested historical block\n ///\n /// # Advanced\n /// This function uses an oracle to fetch block header data from the user's\n /// PXE. Depending on how much blockchain data the user's PXE has been set\n /// up to store, this might require a query from the PXE to another Aztec\n /// node to get the data.\n /// > This is generally true of all oracle getters (see `../oracle`).\n ///\n /// Each block header gets hashed and stored as a leaf in the protocol's\n /// Archive Tree. In fact, the i-th block header gets stored at the i-th\n /// leaf index of the Archive Tree. Behind the scenes, this\n /// `get_block_header_at` function will add Archive Tree merkle-membership\n /// constraints (~3k) to your smart contract function's circuit, to prove\n /// existence of the block header in the Archive Tree.\n ///\n /// Note: we don't do any caching, so avoid making duplicate calls for the\n /// same block header, because each call will add duplicate constraints.\n ///\n /// Calling this function is more expensive (constraint-wise) than getting\n /// the anchor block header (via `get_block_header`). This is because the\n /// anchor block's merkle membership proof is handled by Aztec's protocol\n /// circuits, and is only performed once for the entire tx because all\n /// private functions of a tx share a common anchor block header. Therefore,\n /// the cost (constraint-wise) of calling `get_block_header` is effectively\n /// free.\n ///\n pub fn get_block_header_at(self, block_number: u32) -> BlockHeader {\n get_block_header_at(block_number, self)\n }\n\n /// Sets the hash of the return values for this private function.\n ///\n /// Very low-level function: this is called by the #[private] macro.\n ///\n /// # Arguments\n /// * `returns_hasher` - A hasher containing the return values to hash\n ///\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n self.return_hash = returns_hasher.hash();\n execution_cache::store(returns_hasher.fields, self.return_hash);\n }\n\n /// Builds the PrivateCircuitPublicInputs for this private function, to\n /// ensure compatibility with the protocol's kernel circuits.\n ///\n /// Very low-level function: This function is automatically called by the\n /// #[private] macro.\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 include_by_timestamp: self.include_by_timestamp,\n note_hash_read_requests: ClaimedLengthArray::from_bounded_vec(\n self.note_hash_read_requests,\n ),\n nullifier_read_requests: ClaimedLengthArray::from_bounded_vec(\n self.nullifier_read_requests,\n ),\n key_validation_requests_and_generators: ClaimedLengthArray::from_bounded_vec(\n self.key_validation_requests_and_generators,\n ),\n note_hashes: ClaimedLengthArray::from_bounded_vec(self.note_hashes),\n nullifiers: ClaimedLengthArray::from_bounded_vec(self.nullifiers),\n private_call_requests: ClaimedLengthArray::from_bounded_vec(self.private_call_requests),\n public_call_requests: ClaimedLengthArray::from_bounded_vec(self.public_call_requests),\n public_teardown_call_request: self.public_teardown_call_request,\n l2_to_l1_msgs: ClaimedLengthArray::from_bounded_vec(self.l2_to_l1_msgs),\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n private_logs: ClaimedLengthArray::from_bounded_vec(self.private_logs),\n contract_class_logs_hashes: ClaimedLengthArray::from_bounded_vec(\n self.contract_class_logs_hashes,\n ),\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context,\n }\n }\n\n /// Designates this contract as the fee payer for the transaction.\n ///\n /// Unlike Ethereum, where the transaction sender always pays fees, Aztec\n /// allows any contract to voluntarily pay transaction fees. This enables\n /// patterns like sponsored transactions or fee abstraction where users\n /// don't need to hold fee-juice themselves. (Fee juice is a fee-paying\n /// asset for Aztec).\n ///\n /// Only one contract per transaction can declare itself as the fee payer,\n /// and it must have sufficient fee-juice balance (>= the gas limits\n /// specified in the TxContext) by the time we reach the public setup phase\n /// of the tx.\n ///\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\n \"Setting {0} as fee payer\",\n [self.this_address().to_field()],\n );\n self.is_fee_payer = true;\n }\n\n /// Declares the end of the \"setup phase\" of this tx.\n ///\n /// Only one function per tx can declare the end of the setup phase.\n ///\n /// Niche function: Only wallet developers and paymaster contract developers\n /// (aka Fee-payment contracts) will need to make use of this function.\n ///\n /// Aztec supports a three-phase execution model: setup, app logic, teardown.\n /// The phases exist to enable a fee payer to take on the risk of paying\n /// a transaction fee, safe in the knowledge that their payment (in whatever\n /// token or method the user chooses) will succeed, regardless of whether\n /// the app logic will succeed. The \"setup\" phase enables such a payment to\n /// be made, because the setup phase _cannot revert_: a reverting function\n /// within the setup phase would result in an invalid block which cannot\n /// be proven. Any side-effects generated during that phase are guaranteed\n /// to be inserted into Aztec's state trees (except for squashed notes &\n /// nullifiers, of course).\n ///\n /// Even though the end of the setup phase is declared within a private\n /// function, you might have noticed that _public_ functions can also\n /// execute within the setup phase. This is because any public function\n /// calls which were enqueued _within the setup phase_ by a private\n /// function are considered part of the setup phase.\n ///\n /// # Advanced\n /// * Sets the minimum revertible side effect counter of this tx to be the\n /// PrivateContext's _current_ side effect counter.\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 notify_set_min_revertible_side_effect_counter(self.min_revertible_side_effect_counter);\n }\n\n /// Sets a deadline (an \"include-by timestamp\") for when this transaction\n /// must be included in a block.\n ///\n /// Other functions in this tx might call this setter with differing\n /// values for the include-by timestamp. To ensure that all functions'\n /// deadlines are met, the _minimum_ of all these include-by timestamps will\n /// be exposed when this tx is submitted to the network.\n ///\n /// If the transaction is not included in a block by its include-by\n /// timestamp, it becomes invalid and it will never be included.\n ///\n /// This expiry timestamp is publicly visible. See the \"Advanced\" section\n /// for privacy concerns.\n ///\n /// # Arguments\n /// * `include_by_timestamp` - Unix timestamp (seconds) deadline for inclusion.\n /// The include-by timestamp of this tx will be\n /// _at most_ the timestamp specified.\n ///\n /// # Advanced\n /// * If multiple functions set differing `include_by_timestamp`s, the\n /// kernel circuits will set it to be the _minimum_ of the two. This\n /// ensures the tx expiry requirements of all functions in the tx are met.\n /// * Rollup circuits will reject expired txs.\n /// * The protocol enforces that all transactions must be included within\n /// 24 hours of their chosen anchor block's timestamp, to enable safe\n /// mempool pruning.\n /// * The DelayedPublicMutable design makes heavy use of this functionality,\n /// to enable private functions to read public state.\n /// * A sophisticated Wallet should cleverly set an include-by timestamp\n /// to improve the privacy of the user and the network as a whole.\n /// For example, if a contract interaction sets include-by to some\n /// publicly-known value (e.g. the time when a contract upgrades), then\n /// the wallet might wish to set an even lower one to avoid revealing that\n /// this tx is interacting with said contract.\n /// Ideally, all wallets should standardise on an approach in order to\n /// provide users with a large anonymity set -- although the exact apprach\n /// will need to be discussed. Wallets that deviate from a standard might\n /// accidentally reveal which wallet each transaction originates from.\n ///\n // docs:start:include-by-timestamp\n pub fn set_include_by_timestamp(&mut self, include_by_timestamp: u64) {\n // docs:end:include-by-timestamp\n self.include_by_timestamp = std::cmp::min(self.include_by_timestamp, include_by_timestamp);\n }\n\n /// Makes a request to the protocol's kernel circuit to ensure a note_hash\n /// actually exists.\n ///\n /// \"Read requests\" are used to prove that a note hash exists without\n /// revealing which specific note was read.\n ///\n /// This can be used to prove existence of both settled notes (created in\n /// prior transactions) and transient notes (created in the current\n /// transaction).\n /// If you need to prove existence of a settled note _at a specific block\n /// number_, use `note_inclusion::prove_note_inclusion`.\n ///\n /// Low-level function. Ordinarily, smart contract developers will not need\n /// to call this directly. Aztec-nr's state variables (see `../state_vars/`)\n /// are designed to understand when to create and push new note_hash read\n /// requests.\n ///\n /// # Arguments\n /// * `note_hash` - The note hash to read and verify\n ///\n /// # Advanced\n /// In \"traditional\" circuits for non-Aztec privacy applications, the merkle\n /// membership proofs to check existence of a note are performed _within_\n /// the application circuit.\n ///\n /// All Aztec private functions have access to the following constraint\n /// optimisation:\n /// In cases where the note being read was created earlier in the same tx,\n /// the note wouldn't yet exist in the Note Hash Tree, so a hard-coded\n /// merkle membership check which then gets ignored would be a waste of\n /// constraints.\n /// Instead, we can send read requests for all notes to the protocol's\n /// kernel circuits, where we can conditionally assess which notes actually\n /// need merkle membership proofs, and select an appropriately-sized\n /// kernel circuit.\n ///\n /// For \"settled notes\" (which already existed in the Note Hash Tree of the\n /// anchor block (i.e. before the tx began)), the kernel does a merkle\n /// membership check.\n ///\n /// For \"pending notes\" (which were created earlier in _this_ tx), the\n /// kernel will check that the note existed _before_ this read request was\n /// made, by checking the side-effect counters of the note_hash and this\n /// read request.\n ///\n /// This approach improves latency between writes and reads:\n /// a function can read a note which was created earlier in the tx (rather\n /// than performing the read in a later tx, after waiting for the earlier tx\n /// to be included, to ensure the note is included in the tree).\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 /// Requests to read a specific nullifier from the nullifier tree.\n ///\n /// Nullifier read requests are used to prove that a nullifier exists without\n /// revealing which specific nullifier preimage was read.\n ///\n /// This can be used to prove existence of both settled nullifiers (created in\n /// prior transactions) and transient nullifiers (created in the current\n /// transaction).\n /// If you need to prove existence of a settled nullifier _at a specific block\n /// number_, use `nullifier_inclusion::prove_nullifier_inclusion`.\n ///\n /// Low-level function. Ordinarily, smart contract developers will not need\n /// to call this directly. Aztec-nr's state variables (see `../state_vars/`)\n /// are designed to understand when to create and push new nullifier read\n /// requests.\n ///\n /// # Arguments\n /// * `nullifier` - The nullifier to read and verify\n ///\n /// # Advanced\n /// This approach improves latency between writes and reads:\n /// a function can read a nullifier which was created earlier in the tx\n /// (rather than performing the read in a later tx, after waiting for the\n /// earlier tx to be included, to ensure the note is included in the tree).\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 /// Requests the app-siloed nullifier secret key (nsk_app) for the given\n /// (hashed) master nullifier public key (npk_m), from the user's PXE.\n ///\n /// Advanced function: Only needed if you're designing your own notes and/or\n /// nullifiers.\n ///\n /// Contracts are not allowed to compute nullifiers for other contracts, as\n /// that would let them read parts of their private state. Because of this,\n /// a contract is only given an \"app-siloed secret key\", which is\n /// constructed by hashing the user's master nullifier secret key with the\n /// contract's address.\n /// However, because contracts cannot be trusted with a user's master\n /// nullifier secret key (because we don't know which contracts are honest\n /// or malicious), the PXE refuses to provide any master secret keys to\n /// any app smart contract function. This means app functions are unable to\n /// prove that the derivation of an app-siloed nullifier secret key has been\n /// computed correctly. Instead, an app function can request to the kernel\n /// (via `request_nsk_app`) that it validates the siloed derivation, since\n /// the kernel has been vetted to not leak any master secret keys.\n ///\n /// A common nullification scheme is to inject a nullifier secret key into\n /// the preimage of a nullifier, to make the nullifier deterministic but\n /// random-looking. This function enables that flow.\n ///\n /// # Arguments\n /// * `npk_m_hash` - A hash of the master nullifier public key of the user\n /// whose PXE is executing this function.\n ///\n /// # Returns\n /// * The app-siloed nullifier secret key that corresponds to the given\n /// `npk_m_hash`.\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 /// Requests the app-siloed nullifier secret key (nsk_app) for the given\n /// (hashed) master nullifier public key (npk_m), from the user's PXE.\n ///\n /// See `request_nsk_app` and `request_sk_app` for more info.\n ///\n /// The intention of the \"outgoing\" keypair is to provide a second secret\n /// key for all of a user's outgoing activity (i.e. for notes that a user\n /// creates, as opposed to notes that a user receives from others). The\n /// separation of incoming and outgoing data was a distinction made by\n /// zcash, with the intention of enabling a user to optionally share with a\n /// 3rd party a controlled view of only incoming or outgoing notes.\n /// Similar functionality of sharing select data can be achieved with\n /// offchain zero-knowledge proofs. It is up to an app developer whether\n /// they choose to make use of a user's outgoing keypair within their\n /// application logic, or instead simply use the same keypair (the address\n /// keypair (which is effectively the same as the \"incooming\" keypair)) for\n /// all incoming & outgoing messages to a user.\n ///\n /// Currently, all of the exposed encryption functions in aztec-nr ignore\n /// the outgoing viewing keys, and instead encrypt all note logs and event\n /// logs to a user's address public key.\n ///\n /// # Arguments\n /// * `ovpk_m_hash` - Hash of the outgoing viewing public key master\n ///\n /// # Returns\n /// * The application-specific outgoing viewing secret key\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 /// Pushes a Key Validation Request to the kernel.\n ///\n /// Private functions are not allowed to see a user's master secret keys,\n /// because we do not trust them. They are instead given \"app-siloed\" secret\n /// keys with a claim that they relate to a master public key.\n /// They can then request validation of this claim, by making a \"key\n /// validation request\" to the protocol's kernel circuits (which _are_\n /// allowed to see certain master secret keys).\n ///\n /// When a Key Validation Request tuple of (sk_app, Pk_m, app_address) is\n /// submitted to the kernel, it will perform the following derivations\n /// to validate the relationship between the claimed sk_app and the user's\n /// Pk_m:\n ///\n /// (sk_m) ----> * G ----> Pk_m\n /// | |\n /// v We use the kernel to prove this\n /// h(sk_m, app_address) | sk_app-Pk_m relationship, because app\n /// | circuits must not be trusted to see sk_m.\n /// v |\n /// sk_app - - - - - - - - -\n ///\n /// The function is named \"request_\" instead of \"get_\" to remind the user\n /// that a Key Validation Request will be emitted to the kernel.\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 as u32].unwrap_or(\n KeyValidationRequest::empty(),\n );\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\n // Typically we'd validate keys by showing that they are the preimage of `pk_m_hash`, but that'd require\n // the oracle returning the master secret keys, which could cause malicious contracts to leak it or learn\n // about secrets from other contracts. We therefore silo secret keys, and rely on the private kernel to\n // validate that we siloed secret key corresponds to correct siloing of the master secret key that hashes\n // to `pk_m_hash`.\n\n // Safety: Kernels verify that the key validation request is valid and below we verify that a request\n // for the correct public key has been received.\n let request = unsafe { get_key_validation_request(pk_m_hash, key_index) };\n assert_eq(request.pk_m.hash(), pk_m_hash, \"Obtained invalid key validation request\");\n\n self.key_validation_requests_and_generators.push(\n KeyValidationRequestAndGenerator {\n request,\n sk_app_generator: sk_generators[key_index as u32],\n },\n );\n self.last_key_validation_requests[key_index as u32] = Option::some(request);\n request.sk_app\n }\n }\n\n /// Sends an \"L2 -> L1 message\" from this function (Aztec, L2) to a smart\n /// contract on Ethereum (L1). L1 contracts which are designed to\n /// send/receive messages to/from Aztec are called \"Portal Contracts\".\n ///\n /// Common use cases include withdrawals, cross-chain asset transfers, and\n /// triggering L1 actions based on L2 state changes.\n ///\n /// The message will be inserted into an Aztec \"Outbox\" contract on L1,\n /// when this transaction's block is proposed to L1.\n /// Sending the message will not result in any immediate state changes in\n /// the target portal contract. The message will need to be manually\n /// consumed from the Outbox through a separate Ethereum transaction: a user\n /// will need to call a function of the portal contract -- a function\n /// specifically designed to make a call to the Outbox to consume the\n /// message.\n /// The message will only be available for consumption once the _epoch_\n /// proof has been submitted. Given that there are multiple Aztec blocks\n /// within an epoch, it might take some time for this epoch proof to be\n /// submitted -- especially if the block was near the start of an epoch.\n ///\n /// # Arguments\n /// * `recipient` - Ethereum address that will receive the message\n /// * `content` - Message content (32 bytes as a Field element).\n /// This content has a very specific layout.\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 };\n self.l2_to_l1_msgs.push(message.count(self.next_counter()));\n }\n\n /// Consumes a message sent from Ethereum (L1) to Aztec (L2).\n ///\n /// Common use cases include token bridging, cross-chain governance, and\n /// triggering L2 actions based on L1 events.\n ///\n /// Use this function if you only want the message to ever be \"referred to\"\n /// once. Once consumed using this method, the message cannot be consumed\n /// again, because a nullifier is emitted.\n /// If your use case wants for the message to be read unlimited times, then\n /// you can always read any historic message from the L1-to-L2 messages tree;\n /// messages never technically get deleted from that tree.\n ///\n /// The message will first be inserted into an Aztec \"Inbox\" smart contract\n /// on L1.\n /// Sending the message will not result in any immediate state changes in\n /// the target L2 contract. The message will need to be manually\n /// consumed by the target contract through a separate Aztec transaction.\n /// The message will not be available for consumption immediately. Messages\n /// get copied over from the L1 Inbox to L2 by the next Proposer in batches.\n /// So you will need to wait until the messages are copied before you can\n /// consume them.\n ///\n /// # Arguments\n /// * `content` - The message content that was sent from L1\n /// * `secret` - Secret value used for message privacy (if needed)\n /// * `sender` - Ethereum address that sent the message\n /// * `leaf_index` - Index of the message in the L1-to-L2 message tree\n ///\n /// # Advanced\n /// Validates message existence in the L1-to-L2 message tree and nullifies\n /// the message to prevent double-consumption.\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(\n &mut self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field,\n ) {\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 leaf_index,\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_nullifier(nullifier)\n }\n // docs:end:consume_l1_to_l2_message\n\n /// Emits a private log (an array of Fields) that will be published to an\n /// Ethereum blob.\n ///\n /// Private logs are intended for the broadcasting of ciphertexts: that is,\n /// encrypted events or encrypted note contents.\n /// Since the data in the logs is meant to be _encrypted_, private_logs are\n /// broadcast to publicly-visible Ethereum blobs.\n /// The intended recipients of such encrypted messages can then discover and\n /// decrypt these encrypted logs using their viewing secret key.\n /// (See `../messages/discovery` for more details).\n ///\n /// Important note: This function DOES NOT _do_ any encryption of the input\n /// `log` fields. This function blindly publishes whatever input `log` data\n /// is fed into it, so the caller of this function should have already\n /// performed the encryption, and the `log` should be the result of that\n /// encryption.\n ///\n /// The protocol does not dictate what encryption scheme should be used:\n /// a smart contract developer can choose whatever encryption scheme they\n /// like.\n /// Aztec-nr includes some off-the-shelf encryption libraries that\n /// developers might wish to use, for convenience. These libraries not only\n /// encrypt a plaintext (to produce a ciphertext); they also prepend the\n /// ciphertext with a `tag` and `ephemeral public key` for easier message\n /// discovery. This is a very dense topic, and we will be writing more\n /// libraries and docs soon.\n ///\n /// > Currently, AES128 CBC encryption is the main scheme included in\n /// > aztec.nr.\n /// > We are currently making significant changes to the interfaces of the\n /// > encryption library.\n ///\n /// In some niche use cases, an app might be tempted to publish\n /// _un-encrypted_ data via a private log, because _public logs_ are not\n /// available to private functions. Be warned that emitting public data via\n /// private logs is strongly discouraged, and is considered a \"privacy\n /// anti-pattern\", because it reveals identifiable information about _which_\n /// function has been executed. A tx which leaks such information does not\n /// contribute to the privacy set of the network.\n ///\n /// * Unlike `emit_raw_note_log`, this log is not tied to any specific note\n ///\n /// # Arguments\n /// * `log` - The log data that will be publicly broadcast (so make sure\n /// it's already been encrypted before you call this function).\n /// Private logs are bounded in size (PRIVATE_LOG_SIZE_IN_FIELDS), to\n /// encourage all logs from all smart contracts look identical.\n /// * `length` - The actual length of the `log` (measured in number of\n /// Fields). Although the input log has a max size of\n /// PRIVATE_LOG_SIZE_IN_FIELDS, the latter values of the array might all\n /// be 0's for small logs. This `length` should reflect the trimmed length\n /// of the array. The protocol's kernel circuits can then append random\n /// fields as \"padding\" after the `length`, so that the logs of this\n /// smart contract look indistinguishable from (the same length as) the\n /// logs of all other applications. It's up to wallets how much padding\n /// to apply, so ideally all wallets should agree on standards for this.\n ///\n /// # Advanced\n ///\n pub fn emit_private_log(&mut self, log: [Field; PRIVATE_LOG_SIZE_IN_FIELDS], length: u32) {\n let counter = self.next_counter();\n let private_log =\n PrivateLogData { log: PrivateLog::new(log, length), note_hash_counter: 0, counter };\n self.private_logs.push(private_log);\n }\n\n // TODO: rename.\n /// Emits a private log that is explicitly tied to a newly-emitted note_hash,\n /// to convey to the kernel: \"this log relates to this note\".\n ///\n /// This linkage is important in case the note gets squashed (due to being\n /// read later in this same tx), since we can then squash the log as well.\n ///\n /// See `emit_private_log` for more info about private log emission.\n ///\n /// # Arguments\n /// * `log` - The log data as an array of Field elements\n /// * `length` - The actual length of the `log` (measured in number of\n /// Fields).\n /// * `note_hash_counter` - The side-effect counter that was assigned to the\n /// new note_hash when it was pushed to this\n // `PrivateContext`.\n ///\n /// Important: If your application logic requires the log to always be\n /// emitted regardless of note squashing, consider using `emit_private_log`\n /// instead, or emitting additional events.\n ///\n pub fn emit_raw_note_log(\n &mut self,\n log: [Field; PRIVATE_LOG_SIZE_IN_FIELDS],\n length: u32,\n note_hash_counter: u32,\n ) {\n let counter = self.next_counter();\n let private_log =\n PrivateLogData { log: PrivateLog::new(log, length), note_hash_counter, counter };\n self.private_logs.push(private_log);\n }\n\n pub fn emit_contract_class_log(&mut self, log: [Field; N]) {\n let contract_address = self.this_address();\n let counter = self.next_counter();\n\n let log_to_emit: [Field; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS] =\n log.concat([0; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS - N]);\n // Note: the length is not always N, it is the number of fields we want to broadcast, omitting trailing zeros to save blob space.\n // Safety: The below length is constrained in the base rollup, which will make sure that all the fields beyond length are zero.\n let length = unsafe { trimmed_array_length_hint(log_to_emit) };\n // We hash the entire padded log to ensure a user cannot pass a shorter length and so emit incorrect shorter bytecode.\n let log_hash = poseidon2_hash(log_to_emit);\n // Safety: the below only exists to broadcast the raw log, so we can provide it to the base rollup later to be constrained.\n unsafe {\n notify_created_contract_class_log(contract_address, log_to_emit, length, counter);\n }\n\n self.contract_class_logs_hashes.push(LogHash { value: log_hash, length: length }.count(\n counter,\n ));\n }\n\n /// Calls a private function on another contract (or the same contract).\n ///\n /// Very low-level function.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n /// * `args` - Array of arguments to pass to the called function\n ///\n /// # Returns\n /// * `ReturnsHash` - Hash of the called function's return values. Use\n /// `.get_preimage()` to extract the actual return values.\n ///\n /// This enables contracts to interact with each other while maintaining\n /// privacy. This \"composability\" of private contract functions is a key\n /// feature of the Aztec network.\n ///\n /// If a user's transaction includes multiple private function calls, then\n /// by the design of Aztec, the following information will remain private[1]:\n /// - The function selectors and contract addresses of all private function\n /// calls will remain private, so an observer of the public mempool will\n /// not be able to look at a tx and deduce which private functions have\n /// been executed.\n /// - The arguments and return values of all private function calls will\n /// remain private.\n /// - The person who initiated the tx will remain private.\n /// - The notes and nullifiers and private logs that are emitted by all\n /// private function calls will (if designed well) not leak any user\n /// secrets, nor leak which functions have been executed.\n ///\n /// [1] Caveats: Some of these privacy guarantees depend on how app\n /// developers design their smart contracts. Some actions _can_ leak\n /// information, such as:\n /// - Calling an internal public function.\n /// - Calling a public function and not setting msg_sender to Option::none\n /// (feature not built yet - see github).\n /// - Calling any public function will always leak details about the nature\n /// of the transaction, so devs should be careful in their contract\n /// designs. If it can be done in a private function, then that will give\n /// the best privacy.\n /// - Not padding the side-effects of a tx to some standardised, uniform\n /// size. The kernel circuits can take hints to pad side-effects, so a\n /// wallet should be able to request for a particular amount of padding.\n /// Wallets should ideally agree on some standard.\n /// - Padding should include:\n /// - Padding the lengths of note & nullifier arrays\n /// - Padding private logs with random fields, up to some standardised\n /// size.\n /// See also: https://docs.aztec.network/developers/reference/considerations/privacy_considerations\n ///\n /// # Advanced\n /// * The call is added to the private call stack and executed by kernel\n /// circuits after this function completes\n /// * The called function can modify its own contract's private state\n /// * Side effects from the called function are included in this transaction\n /// * The call inherits the current transaction's context and gas limits\n ///\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ArgsCount],\n ) -> ReturnsHash {\n let args_hash = hash_args_array(args);\n execution_cache::store(args, args_hash);\n self.call_private_function_with_args_hash(\n contract_address,\n function_selector,\n args_hash,\n false,\n )\n }\n\n /// Makes a read-only call to a private function on another contract.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state or emit events. Any nested calls are constrained to\n /// also be staticcalls.\n ///\n /// See `call_private_function` for more general info on private function\n /// calls.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract to call\n /// * `function_selector` - 4-byte identifier of the function to call\n /// * `args` - Array of arguments to pass to the called function\n ///\n /// # Returns\n /// * `ReturnsHash` - Hash of the called function's return values. Use\n /// `.get_preimage()` to extract the actual return values.\n ///\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ArgsCount],\n ) -> ReturnsHash {\n let args_hash = hash_args_array(args);\n execution_cache::store(args, args_hash);\n self.call_private_function_with_args_hash(\n contract_address,\n function_selector,\n args_hash,\n true,\n )\n }\n\n /// Calls a private function that takes no arguments.\n ///\n /// This is a convenience function for calling private functions that don't\n /// require any input parameters. It's equivalent to `call_private_function`\n /// but slightly more efficient to use when no arguments are needed.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n ///\n /// # Returns\n /// * `ReturnsHash` - Hash of the called function's return values. Use\n /// `.get_preimage()` to extract the actual return values.\n ///\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n ) -> ReturnsHash {\n self.call_private_function_with_args_hash(contract_address, function_selector, 0, false)\n }\n\n /// Makes a read-only call to a private function which takes no arguments.\n ///\n /// This combines the optimisation of `call_private_function_no_args` with\n /// the safety of `static_call_private_function`.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n ///\n /// # Returns\n /// * `ReturnsHash` - Hash of the called function's return values. Use\n /// `.get_preimage()` to extract the actual return values.\n ///\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n ) -> ReturnsHash {\n self.call_private_function_with_args_hash(contract_address, function_selector, 0, true)\n }\n\n /// Low-level private function call.\n ///\n /// This is the underlying implementation used by all other private function\n /// call methods. Instead of taking raw arguments, it accepts a\n /// hash of the arguments.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n /// * `args_hash` - Pre-computed hash of the function arguments\n /// * `is_static_call` - Whether this should be a read-only call\n ///\n /// # Returns\n /// * `ReturnsHash` - Hash of the called function's return values\n ///\n pub fn call_private_function_with_args_hash(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n ) -> ReturnsHash {\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\n // Safety: The oracle simulates the private call and returns the value of the side effects counter after\n // execution of the call (which means that end_side_effect_counter - start_side_effect_counter is\n // the number of side effects that took place), along with the hash of the return values. We validate these\n // by requesting a private kernel iteration in which the return values are constrained to hash\n // to `returns_hash` and the side effects counter to increment from start to end.\n let (end_side_effect_counter, returns_hash) = unsafe {\n call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n )\n };\n\n self.private_call_requests.push(\n PrivateCallRequest {\n call_context: CallContext {\n msg_sender: self.this_address(),\n contract_address,\n function_selector,\n is_static_call,\n },\n args_hash,\n returns_hash,\n start_side_effect_counter,\n end_side_effect_counter,\n },\n );\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 // 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 self.side_effect_counter = end_side_effect_counter + 1; // TODO: call `next_counter` instead, for consistency\n ReturnsHash::new(returns_hash)\n }\n\n /// Enqueues a call to a public function to be executed later.\n ///\n /// Unlike private functions which execute immediately on the user's device,\n /// public function calls are \"enqueued\" and executed some time later by a\n /// block proposer.\n ///\n /// This means a public function cannot return any values back to a private\n /// function, because by the time the public function is being executed,\n /// the private function which called it has already completed execution.\n /// (In fact, the private function has been executed and proven, along with\n /// all other private function calls of the user's tx. A single proof of the\n /// tx has been submitted to the Aztec network, and some time later a\n /// proposer has picked the tx up from the mempool and begun executing all\n /// of the enqueued public functions).\n ///\n /// # Privacy warning\n /// Enqueueing a public function call is an inherently leaky action.\n /// Many interesting applications will require some interaction with public\n /// state, but smart contract developers should try to use public function\n /// calls sparingly, and carefully.\n /// _Internal_ public function calls are especially leaky, because they\n /// completely leak which private contract made the call.\n /// See also: https://docs.aztec.network/developers/reference/considerations/privacy_considerations\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n /// * `args` - Array of arguments to pass to the public function\n ///\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ArgsCount],\n ) {\n let calldata = [function_selector.to_field()].concat(args);\n let calldata_hash = hash_calldata_array(calldata);\n execution_cache::store(calldata, calldata_hash);\n self.call_public_function_with_calldata_hash(contract_address, calldata_hash, false)\n }\n\n /// Enqueues a read-only call to a public function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state or emit events. Any nested calls are constrained to\n /// also be staticcalls.\n ///\n /// See also `call_public_function` for more important information about\n /// making private -> public function calls.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n /// * `args` - Array of arguments to pass to the public function\n ///\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ArgsCount],\n ) {\n let calldata = [function_selector.to_field()].concat(args);\n let calldata_hash = hash_calldata_array(calldata);\n execution_cache::store(calldata, calldata_hash);\n self.call_public_function_with_calldata_hash(contract_address, calldata_hash, true)\n }\n\n /// Enqueues a call to a public function that takes no arguments.\n ///\n /// This is an optimisation for calling public functions that don't\n /// take any input parameters. It's otherwise equivalent to\n /// `call_public_function`.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n ///\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n ) {\n let calldata_hash = hash_calldata_array([function_selector.to_field()]);\n self.call_public_function_with_calldata_hash(contract_address, calldata_hash, false)\n }\n\n /// Enqueues a read-only call to a public function with no arguments.\n ///\n /// This combines the optimisation of `call_public_function_no_args` with\n /// the safety of `static_call_public_function`.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n ///\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n ) {\n let calldata_hash = hash_calldata_array([function_selector.to_field()]);\n self.call_public_function_with_calldata_hash(contract_address, calldata_hash, true)\n }\n\n /// Low-level public function call.\n ///\n /// This is the underlying implementation used by all other public function\n /// call methods. Instead of taking raw arguments, it accepts a\n /// hash of the arguments.\n ///\n /// Advanced function: Most developers should use `call_public_function`\n /// or `static_call_public_function` instead. This function is exposed for\n /// performance optimization and advanced use cases.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `calldata_hash` - Hash of the function calldata\n /// * `is_static_call` - Whether this should be a read-only call\n ///\n pub fn call_public_function_with_calldata_hash(\n &mut self,\n contract_address: AztecAddress,\n calldata_hash: Field,\n is_static_call: bool,\n ) {\n let counter = self.next_counter();\n\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n\n notify_enqueued_public_function_call(\n contract_address,\n calldata_hash,\n counter,\n is_static_call,\n );\n\n let call_request = PublicCallRequest {\n msg_sender: self.this_address(),\n contract_address,\n is_static_call,\n calldata_hash,\n };\n\n self.public_call_requests.push(Counted::new(call_request, counter));\n }\n\n /// Enqueues a public function call, and designates it to be the teardown\n /// function for this tx. Only one teardown function call can be made by a\n /// tx.\n ///\n /// Niche function: Only wallet developers and paymaster contract developers\n /// (aka Fee-payment contracts) will need to make use of this function.\n ///\n /// Aztec supports a three-phase execution model: setup, app logic, teardown.\n /// The phases exist to enable a fee payer to take on the risk of paying\n /// a transaction fee, safe in the knowledge that their payment (in whatever\n /// token or method the user chooses) will succeed, regardless of whether\n /// the app logic will succeed. The \"setup\" phase ensures the fee payer\n /// has sufficient balance to pay the proposer their fees.\n /// The teardown phase is primarily intended to: calculate exactly\n /// how much the user owes, based on gas consumption, and refund the user\n /// any change.\n ///\n /// Note: in some cases, the cost of refunding the user (i.e. DA costs of\n /// tx side-effects) might exceed the refund amount. For app logic with\n /// fairly stable and predictable gas consumption, a material refund amount\n /// is unlikely. For app logic with unpredictable gas consumption, a\n /// refund might be important to the user (e.g. if a heft function reverts\n /// very early). Wallet/FPC/Paymaster developers should be mindful of this.\n ///\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ArgsCount],\n ) {\n let calldata = [function_selector.to_field()].concat(args);\n let calldata_hash = hash_calldata_array(calldata);\n execution_cache::store(calldata, calldata_hash);\n self.set_public_teardown_function_with_calldata_hash(contract_address, calldata_hash, false)\n }\n\n /// Low-level function to set the public teardown function.\n ///\n /// This is the underlying implementation for setting the teardown function\n /// call that will execute at the end of the transaction. Instead of taking\n /// raw arguments, it accepts a hash of the arguments.\n ///\n /// Advanced function: Most developers should use\n /// `set_public_teardown_function` instead.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the teardown\n /// function\n /// * `calldata_hash` - Hash of the function calldata\n /// * `is_static_call` - Whether this should be a read-only call\n ///\n pub fn set_public_teardown_function_with_calldata_hash(\n &mut self,\n contract_address: AztecAddress,\n calldata_hash: Field,\n is_static_call: bool,\n ) {\n let counter = self.next_counter();\n\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n\n notify_set_public_teardown_function_call(\n contract_address,\n calldata_hash,\n counter,\n is_static_call,\n );\n\n self.public_teardown_call_request = PublicCallRequest {\n msg_sender: self.this_address(),\n contract_address,\n is_static_call,\n calldata_hash,\n };\n }\n\n /// Increments the side-effect counter.\n ///\n /// Very low-level function.\n ///\n /// # Advanced\n ///\n /// Every side-effect of a private function is given a \"side-effect counter\",\n /// based on when it is created. This PrivateContext is in charge of\n /// assigning the counters.\n ///\n /// The reason we have side-effect counters is complicated. Consider this\n /// illustrative pseudocode of inter-contract function calls:\n /// ```\n /// contract A {\n /// let x = 5; // pseudocode for storage var x.\n /// fn a1 {\n /// read x; // value: 5, counter: 1.\n /// x = x + 1;\n /// write x; // value: 6, counter: 2.\n ///\n /// B.b(); // start_counter: 2, end_counter: 4\n ///\n /// read x; // value: 36, counter: 5.\n /// x = x + 1;\n /// write x; // value: 37, counter: 6.\n /// }\n ///\n /// fn a2 {\n /// read x; // value: 6, counter: 3.\n /// x = x * x;\n /// write x; // value: 36, counter: 4.\n /// }\n /// }\n ///\n /// contract B {\n /// fn b() {\n /// A.a2();\n /// }\n /// }\n /// ```\n ///\n /// Suppose a1 is the first function called. The comments show the execution\n /// counter of each side-effect, and what the new value of `x` is.\n ///\n /// These (private) functions are processed by Aztec's kernel circuits in an\n /// order that is different from execution order:\n /// All of A.a1 is proven before B.b is proven, before A.a2 is proven.\n /// So when we're in the 2nd execution frame of A.a1 (after the call to\n /// B.b), the circuit needs to justify why x went from being `6` to `36`.\n /// But the circuit doesn't know why, and given the order of proving, the\n /// kernel hasn't _seen_ a value of 36 get written yet.\n /// The kernel needs to track big arrays of all side-effects of all\n /// private functions in a tx. Then, as it recurses and processes B.b(), it\n /// will eventually see a value of 36 get written.\n ///\n /// Suppose side-effect counters weren't exposed:\n /// The kernel would only see this ordering (in order of proof verification):\n /// [ A.a1.read, A.a1.write, A.a1.read, A.a1.write, A.a2.read, A.a2.write ]\n /// [ 5, 6, 36, 37, 6, 36 ]\n /// The kernel wouldn't know _when_ B.b() was called within A.a1(), because\n /// it can't see what's going on within an app circuit. So the kernel\n /// wouldn't know that the ordering of reads and writes should actually be:\n /// [ A.a1.read, A.a1.write, A.a2.read, A.a2.write, A.a1.read, A.a1.write ]\n /// [ 5, 6, 6, 36, 36, 37 ]\n ///\n /// And so, we introduced side-effect counters: every private function must\n /// assign side-effect counters alongside every side-effect that it emits,\n /// and also expose to the kernel the counters that it started and ended\n /// with.\n /// This gives the kernel enough information to arrange all side-effects in\n /// the correct order.\n /// It can then catch (for example) if a function tries to read state\n /// before it has been written (e.g. if A.a2() maliciously tried to read\n /// a value of x=37) (e.g. if A.a1() maliciously tried to read x=6).\n ///\n /// If a malicious app contract _lies_ and does not count correctly:\n /// - It cannot lie about its start and end counters because the kernel\n /// will catch this.\n /// - It _could_ lie about its intermediate counters:\n /// - 1. It could not increment its side-effects correctly\n /// - 2. It could label its side-effects with counters outside of its\n /// start and end counters' range.\n /// The kernel will catch 2.\n /// The kernel will not catch 1., but this would only cause corruption\n /// to the private state of the malicious contract, and not any other\n /// contracts (because a contract can only modify its own state). If\n /// a \"good\" contract is given _read access_ to a maliciously-counting\n /// contract (via an external getter function, or by reading historic\n /// state from the archive tree directly), and they then make state\n /// changes to their _own_ state accordingly, that could be dangerous.\n /// Developers should be mindful not to trust the claimed innards of\n /// external contracts unless they have audited/vetted the contracts\n /// including vetting the side-effect counter incrementation.\n /// This is a similar paradigm to Ethereum smart contract development:\n /// you must vet external contracts that your contract relies upon, and\n /// you must not make any presumptions about their claimed behaviour.\n /// (Hopefully if a contract imports a version of aztec-nr, we will get\n /// contract verification tooling that can validate the authenticity\n /// of the imported aztec-nr package, and hence infer that the side-\n /// effect counting will be correct, without having to re-audit such logic\n /// for every contract).\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 include_by_timestamp: 0,\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n note_hashes: BoundedVec::new(),\n nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_requests: BoundedVec::new(),\n public_teardown_call_request: PublicCallRequest::empty(),\n l2_to_l1_msgs: BoundedVec::new(),\n historical_header: BlockHeader::empty(),\n private_logs: BoundedVec::new(),\n contract_class_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES],\n }\n }\n}\n" + }, + "69": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/context/public_context.nr", + "source": "use crate::context::gas::GasOpts;\nuse crate::hash::{\n compute_l1_to_l2_message_hash, compute_l1_to_l2_message_nullifier, compute_secret_hash,\n};\nuse dep::protocol_types::abis::function_selector::FunctionSelector;\nuse dep::protocol_types::address::{AztecAddress, EthAddress};\nuse dep::protocol_types::constants::MAX_U32_VALUE;\nuse dep::protocol_types::traits::{Empty, FromField, Packable, Serialize, ToField};\n\n/// # PublicContext\n///\n/// The **main interface** between a #[public] function and the Aztec blockchain.\n///\n/// An instance of the PublicContext is initialized automatically at the outset\n/// of every public function, within the #[public] macro, so you'll never\n/// need to consciously instantiate this yourself.\n///\n/// The instance is always named `context`, and it will always be available\n/// within the body of every #[public] function in your smart contract.\n///\n/// Typical usage for a smart contract developer will be to call getter\n/// methods of the PublicContext.\n///\n/// _Pushing_ data and requests to the context is mostly handled within\n/// aztec-nr's own functions, so typically a smart contract developer won't\n/// need to call any setter methods directly.\n///\n/// ## Responsibilities\n/// - Exposes contextual data to a public function:\n/// - Data relating to how this public function was called:\n/// - msg_sender, this_address\n/// - Data relating to the current blockchain state:\n/// - timestamp, block_number, chain_id, version\n/// - Gas and fee information\n/// - Provides state access:\n/// - Read/write public storage (key-value mapping)\n/// - Check existence of notes and nullifiers\n/// (Some patterns use notes & nullifiers to store public (not private)\n/// information)\n/// - Enables consumption of L1->L2 messages.\n/// - Enables calls to other public smart contract functions:\n/// - Writes data to the blockchain:\n/// - Updates to public state variables\n/// - New public logs (for events)\n/// - New L2->L1 messages\n/// - New notes & nullifiers\n/// (E.g. pushing public info to notes/nullifiers, or for completing\n/// \"partial notes\")\n///\n/// ## Key Differences from Private Execution\n///\n/// Unlike private functions -- which are executed on the user's device and which\n/// can only reference historic state -- public functions are executed by a block\n/// proposer and are executed \"live\" on the _current_ tip of the chain.\n/// This means public functions can:\n/// - Read and write _current_ public state\n/// - Immediately see the effects of earlier transactions in the same block\n///\n/// Also, public functions are executed within a zkVM (the \"AVM\"), so that they\n/// can _revert_ whilst still ensuring payment to the proposer and prover.\n/// (Private functions cannot revert: they either succeed, or they cannot be\n/// included).\n///\n/// ## Optimising Public Functions\n///\n/// Using the AVM to execute public functions means they compile down to \"AVM\n/// bytecode\" instead of the ACIR that private functions (standalone circuits)\n/// compile to. Therefore the approach to optimising a public function is\n/// fundamentally different from optimising a public function.\n///\npub struct PublicContext {\n pub args_hash: Option,\n pub compute_args_hash: fn() -> Field,\n}\n\nimpl Eq for PublicContext {\n fn eq(self, other: Self) -> bool {\n (self.args_hash == other.args_hash)\n // Can't compare the function compute_args_hash\n }\n}\n\nimpl PublicContext {\n /// Creates a new PublicContext instance.\n ///\n /// Low-level function: This is called automatically by the #[public]\n /// macro, so you shouldn't need to be called directly by smart contract\n /// developers.\n ///\n /// # Arguments\n /// * `compute_args_hash` - Function to compute the args_hash\n ///\n /// # Returns\n /// * A new PublicContext instance\n ///\n pub fn new(compute_args_hash: fn() -> Field) -> Self {\n PublicContext { args_hash: Option::none(), compute_args_hash }\n }\n\n /// Emits a _public_ log that will be visible onchain to everyone.\n ///\n /// # Arguments\n /// * `log` - The data to log, must implement Serialize trait\n ///\n pub fn emit_public_log(_self: &mut Self, log: T)\n where\n T: Serialize,\n {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { emit_public_log(Serialize::serialize(log).as_slice()) };\n }\n\n /// Checks if a given note hash exists in the note hash tree at a particular\n /// leaf_index.\n ///\n /// # Arguments\n /// * `note_hash` - The note hash to check for existence\n /// * `leaf_index` - The index where the note hash should be located\n ///\n /// # Returns\n /// * `bool` - True if the note hash exists at the specified index\n ///\n pub fn note_hash_exists(_self: Self, note_hash: Field, leaf_index: u64) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { note_hash_exists(note_hash, leaf_index) } == 1\n }\n\n /// Checks if a specific L1-to-L2 message exists in the L1-to-L2 message\n /// tree at a particular leaf index.\n ///\n /// Common use cases include token bridging, cross-chain governance, and\n /// triggering L2 actions based on L1 events.\n ///\n /// This function should be called before attempting to consume an L1-to-L2\n /// message.\n ///\n /// # Arguments\n /// * `msg_hash` - Hash of the L1-to-L2 message to check\n /// * `msg_leaf_index` - The index where the message should be located\n ///\n /// # Returns\n /// * `bool` - True if the message exists at the specified index\n ///\n /// # Advanced\n /// * Uses the AVM l1_to_l2_msg_exists opcode for tree lookup\n /// * Messages are copied from L1 Inbox to L2 by block proposers\n ///\n pub fn l1_to_l2_msg_exists(_self: Self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n // TODO(alvaro): Make l1l2msg leaf index a u64 upstream\n unsafe { l1_to_l2_msg_exists(msg_hash, msg_leaf_index as u64) } == 1\n }\n\n /// Checks if a specific nullifier has been emitted by a given contract.\n ///\n /// Whilst nullifiers are primarily intended as a _privacy-preserving_\n /// record of a one-time action, they can also be used to efficiently\n /// record _public_ one-time actions too. An example is to check\n /// whether a contract has been published: we emit a nullifier that is\n /// deterministic, but whose preimage is _not_ private. This is more\n /// efficient than using mutable storage, and can be done directly\n /// from a private function.\n ///\n /// Nullifiers can be tested for non-existence in public, which is not the\n /// case in private. Because private functions do not have access to\n /// the tip of the blockchain (but only the anchor block they are built\n /// at) they can only prove nullifier non-existence in the past. But between\n /// an anchor block and the block in which a tx is included, the nullifier\n /// might have been inserted into the nullifier tree by some other\n /// transaction.\n /// Public functions _do_ have access to the tip of the state, and so\n /// this pattern is safe.\n ///\n /// # Arguments\n /// * `unsiloed_nullifier` - The raw nullifier value (before siloing with\n /// the contract address that emitted it).\n /// * `address` - The claimed contract address that emitted the nullifier\n ///\n /// # Returns\n /// * `bool` - True if the nullifier has been emitted by the specified contract\n ///\n pub fn nullifier_exists(_self: Self, unsiloed_nullifier: Field, address: AztecAddress) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { nullifier_exists(unsiloed_nullifier, address.to_field()) } == 1\n }\n\n /// Consumes a message sent from Ethereum (L1) to Aztec (L2) -- effectively\n /// marking it as \"read\".\n ///\n /// Use this function if you only want the message to ever be \"referred to\"\n /// once. Once consumed using this method, the message cannot be consumed\n /// again, because a nullifier is emitted.\n /// If your use case wants for the message to be read unlimited times, then\n /// you can always read any historic message from the L1-to-L2 messages tree,\n /// using the `l1_to_l2_msg_exists` method. Messages never technically get\n /// deleted from that tree.\n ///\n /// The message will first be inserted into an Aztec \"Inbox\" smart contract\n /// on L1. It will not be available for consumption immediately. Messages\n /// get copied-over from the L1 Inbox to L2 by the next Proposer in batches.\n /// So you will need to wait until the messages are copied before you can\n /// consume them.\n ///\n /// # Arguments\n /// * `content` - The message content that was sent from L1\n /// * `secret` - Secret value used for message privacy (if needed)\n /// * `sender` - Ethereum address that sent the message\n /// * `leaf_index` - Index of the message in the L1-to-L2 message tree\n ///\n /// # Advanced\n /// * Validates message existence in the L1-to-L2 message tree\n /// * Prevents double-consumption by emitting a nullifier\n /// * Message hash is computed from all parameters + chain context\n /// * Will revert if message doesn't exist or was already consumed\n ///\n pub 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_l1_to_l2_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/\n self.this_address(),\n self.version(),\n content,\n secret_hash,\n leaf_index,\n );\n let nullifier = compute_l1_to_l2_message_nullifier(message_hash, secret);\n\n assert(\n !self.nullifier_exists(nullifier, self.this_address()),\n \"L1-to-L2 message is already nullified\",\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index),\n \"Tried to consume nonexistent L1-to-L2 message\",\n );\n\n self.push_nullifier(nullifier);\n }\n\n /// Sends an \"L2 -> L1 message\" from this function (Aztec, L2) to a smart\n /// contract on Ethereum (L1). L1 contracts which are designed to\n /// send/receive messages to/from Aztec are called \"Portal Contracts\".\n ///\n /// Common use cases include withdrawals, cross-chain asset transfers, and\n /// triggering L1 actions based on L2 state changes.\n ///\n /// The message will be inserted into an Aztec \"Outbox\" contract on L1,\n /// when this transaction's block is proposed to L1.\n /// Sending the message will not result in any immediate state changes in\n /// the target portal contract. The message will need to be manually\n /// consumed from the Outbox through a separate Ethereum transaction: a user\n /// will need to call a function of the portal contract -- a function\n /// specifically designed to make a call to the Outbox to consume the\n /// message.\n /// The message will only be available for consumption once the _epoch_\n /// proof has been submitted. Given that there are multiple Aztec blocks\n /// within an epoch, it might take some time for this epoch proof to be\n /// submitted -- especially if the block was near the start of an epoch.\n ///\n /// # Arguments\n /// * `recipient` - Ethereum address that will receive the message\n /// * `content` - Message content (32 bytes as a Field element)\n ///\n pub fn message_portal(_self: &mut Self, recipient: EthAddress, content: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { send_l2_to_l1_msg(recipient, content) };\n }\n\n /// Calls a public function on another contract.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract to call\n /// * `function_selector` - Function to call on the target contract\n /// * `args` - Arguments to pass to the function\n /// * `gas_opts` - An optional allocation of gas to the called function.\n ///\n /// # Returns\n /// * `[Field]` - Return data from the called function\n ///\n pub unconstrained fn call_public_function(\n _self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = args.push_front(function_selector.to_field());\n\n call(\n gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_U32_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = success_copy();\n\n let result_data = returndata_copy(0, returndata_size());\n if !success {\n // Rethrow the revert data.\n avm_revert(result_data);\n }\n result_data\n }\n\n /// Makes a read-only call to a public function on another contract.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state or emit events. Any nested calls are constrained to\n /// also be staticcalls.\n ///\n /// Useful for querying data from other contracts safely.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract to call\n /// * `function_selector` - Function to call on the target contract\n /// * `args` - Array of arguments to pass to the called function\n /// * `gas_opts` - An optional allocation of gas to the called function.\n ///\n /// # Returns\n /// * `[Field]` - Return data from the called function\n ///\n pub unconstrained fn static_call_public_function(\n _self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = args.push_front(function_selector.to_field());\n\n call_static(\n gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_U32_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = success_copy();\n\n let result_data = returndata_copy(0, returndata_size());\n if !success {\n // Rethrow the revert data.\n avm_revert(result_data);\n }\n result_data\n }\n\n /// Adds a new note hash to the Aztec blockchain's global Note Hash Tree.\n ///\n /// Notes are ordinarily constructed and emitted by _private_ functions, to\n /// ensure that both the content of the note, and the contract that emitted\n /// the note, stay private.\n ///\n /// There are however some useful patterns whereby a note needs to contain\n /// _public_ data. The ability to push a new note_hash from a _public_\n /// function means that notes can be injected with public data immediately\n /// -- as soon as the public value is known. The slower alternative would\n /// be to submit a follow-up transaction so that a private function can\n /// inject the data. Both are possible on Aztec.\n ///\n /// Search \"Partial Note\" for a very common pattern which enables a note\n /// to be \"partially\" populated with some data in a _private_ function, and\n /// then later \"completed\" with some data in a public function.\n ///\n /// # Arguments\n /// * `note_hash` - The hash of the note to add to the tree\n ///\n /// # Advanced\n /// * The note hash will be siloed with the contract address by the protocol\n ///\n pub fn push_note_hash(_self: &mut Self, note_hash: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { emit_note_hash(note_hash) };\n }\n\n /// Adds a new nullifier to the Aztec blockchain's global Nullifier Tree.\n ///\n /// Whilst nullifiers are primarily intended as a _privacy-preserving_\n /// record of a one-time action, they can also be used to efficiently\n /// record _public_ one-time actions too. Hence why you're seeing this\n /// function within the PublicContext.\n /// An example is to check whether a contract has been published: we emit\n /// a nullifier that is deterministic, but whose preimage is _not_ private.\n ///\n /// # Arguments\n /// * `nullifier` - A unique field element that represents the consumed\n /// state\n ///\n /// # Advanced\n /// * Nullifier is immediately added to the global nullifier tree\n /// * Emitted nullifiers are immediately visible to all\n /// subsequent transactions in the same block\n /// * Automatically siloed with the contract address by the protocol\n /// * Used for preventing double-spending and ensuring one-time actions\n ///\n pub fn push_nullifier(_self: &mut Self, nullifier: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { emit_nullifier(nullifier) };\n }\n\n /// Returns the address of the current contract being executed.\n ///\n /// This is equivalent to `address(this)` in Solidity (hence the name).\n /// Use this to identify the current contract's address, commonly needed for\n /// access control or when interacting with other contracts.\n ///\n /// # Returns\n /// * `AztecAddress` - The contract address of the current function being\n /// executed.\n ///\n pub fn this_address(_self: Self) -> AztecAddress {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n address()\n }\n }\n\n /// Returns the contract address that initiated this function call.\n ///\n /// This is similar to `msg.sender` in Solidity (hence the name).\n ///\n /// Important Note: Since Aztec doesn't have a concept of an EoA (\n /// Externally-owned Account), the msg_sender is \"undefined\" for the first\n /// function call of every transaction. A value of `-1` is returned in such\n /// cases, and is enforced by the protocol's kernel circuits.\n /// The first function call of a tx is likely to be a call to the user's\n /// account contract, so this quirk will most often be handled by account\n /// contract developers.\n ///\n /// # Returns\n /// * `AztecAddress` - The address of the account or contract that called\n /// this function\n ///\n /// # Examples\n /// ```rust\n /// #[aztec(public)]\n /// fn transfer(context: &mut PublicContext, to: AztecAddress, amount: u64) {\n /// let sender = context.msg_sender();\n /// // Only the sender can transfer their own tokens\n /// assert(sender == get_token_owner(), \"Unauthorized\");\n /// }\n /// ```\n ///\n /// # Advanced\n /// * Value is provided by the AVM sender opcode\n /// * In nested calls, this is the immediate caller, not the original\n /// transaction sender\n /// * Globally visible unlike private execution where it's contract-local\n pub fn msg_sender(_self: Self) -> AztecAddress {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n sender()\n }\n }\n\n /// Returns the function selector of the currently-executing function.\n ///\n /// This is similar to `msg.sig` in Solidity, returning the first 4\n /// bytes of the function signature.\n ///\n /// # Returns\n /// * `FunctionSelector` - The 4-byte function identifier\n ///\n /// # Advanced\n /// * Extracted from the first element of calldata\n /// * Used internally for function dispatch in the AVM\n ///\n pub fn selector(_self: Self) -> FunctionSelector {\n // The selector is the first element of the calldata when calling a public function through dispatch.\n // Safety: AVM opcodes are constrained by the AVM itself\n let raw_selector: [Field; 1] = unsafe { calldata_copy(0, 1) };\n FunctionSelector::from_field(raw_selector[0])\n }\n\n /// Returns the hash of the arguments passed to the current function.\n ///\n /// Very low-level function: The #[public] macro uses this internally.\n /// Smart contract developers typically won't need to access this\n /// directly as arguments are automatically made available.\n ///\n /// # Returns\n /// * `Field` - Hash of the function arguments\n ///\n pub fn get_args_hash(mut self) -> Field {\n if !self.args_hash.is_some() {\n self.args_hash = Option::some((self.compute_args_hash)());\n }\n\n self.args_hash.unwrap_unchecked()\n }\n\n /// Returns the \"transaction fee\" for the current transaction.\n /// This is the final tx fee that will be deducted from the fee_payer's\n /// \"fee-juice\" balance (in the protocol's Base Rollup circuit).\n ///\n /// # Returns\n /// * `Field` - The actual, final cost of the transaction, taking into account:\n /// the actual gas used during the setup and app-logic phases,\n /// and the fixed amount of gas that's been allocated by the user\n /// for the teardown phase.\n /// I.e. effectiveL2FeePerGas * l2GasUsed + effectiveDAFeePerGas * daGasUsed\n ///\n /// This will return `0` during the \"setup\" and \"app-logic\" phases of\n /// tx execution (because the final tx fee is not known at that time).\n /// This will only return a nonzero value during the \"teardown\" phase of\n /// execution, where the final tx fee can actually be computed.\n ///\n /// Regardless of _when_ this function is called during the teardown phase,\n /// it will always return the same final tx fee value. The teardown phase\n /// does not consume a variable amount of gas: it always consumes a\n /// pre-allocated amount of gas, as specified by the user when they generate\n /// their tx.\n ///\n pub fn transaction_fee(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n transaction_fee()\n }\n }\n\n /// Returns the chain ID of the current network.\n ///\n /// This is similar to `block.chainid` in Solidity. Returns the unique\n /// identifier for the blockchain network this transaction is executing on.\n ///\n /// Helps prevent cross-chain replay attacks. Useful if implementing\n /// multi-chain contract logic.\n ///\n /// # Returns\n /// * `Field` - The chain ID as a field element\n ///\n pub fn chain_id(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n chain_id()\n }\n }\n\n /// Returns the Aztec protocol version that this transaction is executing\n /// under. Different versions may have different rules, opcodes, or\n /// cryptographic primitives.\n ///\n /// This is similar to how Ethereum has different EVM versions.\n ///\n /// Useful for forward/backward compatibility checks\n ///\n /// Not to be confused with contract versions; this is the protocol version.\n ///\n /// # Returns\n /// * `Field` - The protocol version as a field element\n ///\n pub fn version(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n version()\n }\n }\n /// Returns the current block number.\n ///\n /// This is similar to `block.number` in Solidity.\n ///\n /// Note: the current block number is only available within a public function\n /// (as opposed to a private function).\n ///\n /// Note: the time intervals between blocks should not be relied upon as\n /// being consistent:\n /// - Timestamps of blocks fall within a range, rather than at exact regular\n /// intervals.\n /// - Slots can be missed.\n /// - Protocol upgrades can completely change the intervals between blocks\n /// (and indeed the current roadmap plans to reduce the time between\n /// blocks, eventually).\n /// Use `context.timestamp()` for more-reliable time-based logic.\n ///\n /// # Returns\n /// * `u32` - The current block number\n ///\n pub fn block_number(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n block_number()\n }\n }\n\n /// Returns the timestamp of the current block.\n ///\n /// This is similar to `block.timestamp` in Solidity.\n ///\n /// All functions of all transactions in a block share the exact same\n /// timestamp (even though technically each transaction is executed\n /// one-after-the-other).\n ///\n /// Important note: Timestamps of Aztec blocks are not at reliably-fixed\n /// intervals. The proposer of the block has some flexibility to choose a\n /// timestamp which is in a valid _range_: Obviously the timestamp of this\n /// block must be strictly greater than that of the previous block, and must\n /// must be less than the timestamp of whichever ethereum block the aztec\n /// block is proposed to. Furthermore, if the timestamp is not deemed close\n /// enough to the actual current time, the committee of validators will not\n /// attest to the block.\n ///\n /// # Returns\n /// * `u64` - Unix timestamp in seconds\n ///\n pub fn timestamp(_self: Self) -> u64 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n timestamp()\n }\n }\n\n /// Returns the fee per unit of L2 gas for this transaction (aka the \"L2 gas\n /// price\"), as chosen by the user.\n ///\n /// L2 gas covers the cost of executing public functions and handling\n /// side-effects within the AVM.\n ///\n /// # Returns\n /// * `u128` - Fee per unit of L2 gas\n ///\n /// Wallet developers should be mindful that the choice of gas price (which\n /// is publicly visible) can leak information about the user, e.g.:\n /// - which wallet software the user is using;\n /// - the amount of time which has elapsed from the time the user's wallet\n /// chose a gas price (at the going rate), to the time of tx submission.\n /// This can give clues about the proving time, and hence the nature of\n /// the tx.\n /// - the urgency of the transaction (which is kind of unavoidable, if the\n /// tx is indeed urgent).\n /// - the wealth of the user.\n /// - the exact user (if the gas price is explicitly chosen by the user to\n /// be some unique number like 0.123456789, or their favourite number).\n /// Wallet devs might wish to consider fuzzing the choice of gas price.\n ///\n pub fn base_fee_per_l2_gas(_self: Self) -> u128 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n base_fee_per_l2_gas()\n }\n }\n\n /// Returns the fee per unit of DA (Data Availability) gas (aka the \"DA gas\n /// price\").\n ///\n /// DA gas covers the cost of making transaction data available on L1.\n ///\n /// See the warning in `fee_pre_l2_gas` for how gas prices can be leaky.\n ///\n /// # Returns\n /// * `u128` - Fee per unit of DA gas\n ///\n pub fn base_fee_per_da_gas(_self: Self) -> u128 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n base_fee_per_da_gas()\n }\n }\n\n /// Returns the remaining L2 gas available for this transaction.\n ///\n /// Different AVM opcodes consume different amounts of gas.\n ///\n /// # Returns\n /// * `u32` - Remaining L2 gas units\n ///\n pub fn l2_gas_left(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n l2_gas_left()\n }\n }\n\n /// Returns the remaining DA (Data Availability) gas available for this\n /// transaction.\n ///\n /// DA gas is consumed when emitting data that needs to be made available\n /// on L1, such as public logs or state updates.\n /// All of the side-effects from the private part of the tx also consume\n /// DA gas before execution of any public functions even begins.\n ///\n /// # Returns\n /// * `u32` - Remaining DA gas units\n ///\n pub fn da_gas_left(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n da_gas_left()\n }\n }\n\n /// Checks if the current execution is within a staticcall context, where\n /// no state changes or logs are allowed to be emitted (by this function\n /// or any nested function calls).\n ///\n /// # Returns\n /// * `bool` - True if in staticcall context, false otherwise\n ///\n pub fn is_static_call(_self: Self) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { is_static_call() } == 1\n }\n\n /// Reads raw field values from public storage.\n /// Reads N consecutive storage slots starting from the given slot.\n ///\n /// Very low-level function. Users should typically use the public state\n /// variable abstractions to perform reads: PublicMutable & PublicImmutable.\n ///\n /// # Arguments\n /// * `storage_slot` - The starting storage slot to read from\n ///\n /// # Returns\n /// * `[Field; N]` - Array of N field values from consecutive storage slots\n ///\n /// # Generic Parameters\n /// * `N` - the number of consecutive slots to return, starting from the\n /// `storage_slot`.\n ///\n pub fn raw_storage_read(_self: Self, storage_slot: Field) -> [Field; N] {\n let mut out = [0; N];\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n out[i] = unsafe { storage_read(storage_slot + i as Field) };\n }\n out\n }\n\n /// Reads a typed value from public storage.\n ///\n /// Low-level function. Users should typically use the public state\n /// variable abstractions to perform reads: PublicMutable & PublicImmutable.\n ///\n /// # Arguments\n /// * `storage_slot` - The storage slot to read from\n ///\n /// # Returns\n /// * `T` - The deserialized value from storage\n ///\n /// # Generic Parameters\n /// * `T` - The type that the caller expects to read from the `storage_slot`.\n ///\n pub fn storage_read(self, storage_slot: Field) -> T\n where\n T: Packable,\n {\n T::unpack(self.raw_storage_read(storage_slot))\n }\n\n /// Writes raw field values to public storage.\n /// Writes to N consecutive storage slots starting from the given slot.\n ///\n /// Very low-level function. Users should typically use the public state\n /// variable abstractions to perform writes: PublicMutable & PublicImmutable.\n ///\n /// Public storage writes take effect immediately.\n ///\n /// # Arguments\n /// * `storage_slot` - The starting storage slot to write to\n /// * `values` - Array of N Fields to write to storage\n ///\n pub fn raw_storage_write(_self: Self, storage_slot: Field, values: [Field; N]) {\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { storage_write(storage_slot + i as Field, values[i]) };\n }\n }\n\n /// Writes a typed value to public storage.\n ///\n /// Low-level function. Users should typically use the public state\n /// variable abstractions to perform writes: PublicMutable & PublicImmutable.\n ///\n /// # Arguments\n /// * `storage_slot` - The storage slot to write to\n /// * `value` - The typed value to write to storage\n ///\n /// # Generic Parameters\n /// * `T` - The type to write to storage.\n ///\n pub fn storage_write(self, storage_slot: Field, value: T)\n where\n T: Packable,\n {\n self.raw_storage_write(storage_slot, value.pack());\n }\n}\n\n// TODO: consider putting this oracle code in its own file.\n// Unconstrained opcode wrappers (do not use directly).\nunconstrained fn address() -> AztecAddress {\n address_opcode()\n}\nunconstrained fn sender() -> AztecAddress {\n sender_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() -> u32 {\n block_number_opcode()\n}\nunconstrained fn timestamp() -> u64 {\n timestamp_opcode()\n}\nunconstrained fn base_fee_per_l2_gas() -> u128 {\n base_fee_per_l2_gas_opcode()\n}\nunconstrained fn base_fee_per_da_gas() -> u128 {\n base_fee_per_da_gas_opcode()\n}\nunconstrained fn l2_gas_left() -> u32 {\n l2_gas_left_opcode()\n}\nunconstrained fn da_gas_left() -> u32 {\n da_gas_left_opcode()\n}\nunconstrained fn is_static_call() -> u1 {\n is_static_call_opcode()\n}\nunconstrained fn note_hash_exists(note_hash: Field, leaf_index: u64) -> u1 {\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) -> u1 {\n nullifier_exists_opcode(nullifier, address)\n}\nunconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\nunconstrained fn emit_public_log(message: [Field]) {\n emit_public_log_opcode(message)\n}\nunconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: u64) -> u1 {\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}\n\nunconstrained fn call(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field],\n) {\n call_opcode(l2_gas_allocation, da_gas_allocation, address, args)\n}\n\nunconstrained fn call_static(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field],\n) {\n call_static_opcode(l2_gas_allocation, da_gas_allocation, address, args)\n}\n\npub unconstrained fn calldata_copy(cdoffset: u32, copy_size: u32) -> [Field; N] {\n calldata_copy_opcode(cdoffset, copy_size)\n}\n\n// `success_copy` is placed immediately after the CALL opcode to get the success value\nunconstrained fn success_copy() -> bool {\n success_copy_opcode()\n}\n\nunconstrained fn returndata_size() -> u32 {\n returndata_size_opcode()\n}\n\nunconstrained fn returndata_copy(rdoffset: u32, copy_size: u32) -> [Field] {\n returndata_copy_opcode(rdoffset, copy_size)\n}\n\npub unconstrained fn avm_return(returndata: [Field]) {\n return_opcode(returndata)\n}\n\n// This opcode reverts using the exact data given. In general it should only be used\n// to do rethrows, where the revert data is the same as the original revert data.\n// For normal reverts, use Noir's `assert` which, on top of reverting, will also add\n// an error selector to the revert data.\nunconstrained fn avm_revert(revertdata: [Field]) {\n revert_opcode(revertdata)\n}\n\nunconstrained fn storage_read(storage_slot: Field) -> Field {\n storage_read_opcode(storage_slot)\n}\n\nunconstrained fn storage_write(storage_slot: Field, value: Field) {\n storage_write_opcode(storage_slot, value);\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(|| 0)\n }\n}\n\n// TODO: consider putting this oracle code in its own file.\n// AVM oracles (opcodes) follow, do not use directly.\n#[oracle(avmOpcodeAddress)]\nunconstrained fn address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeSender)]\nunconstrained fn sender_opcode() -> AztecAddress {}\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() -> u32 {}\n\n#[oracle(avmOpcodeTimestamp)]\nunconstrained fn timestamp_opcode() -> u64 {}\n\n#[oracle(avmOpcodeBaseFeePerL2Gas)]\nunconstrained fn base_fee_per_l2_gas_opcode() -> u128 {}\n\n#[oracle(avmOpcodeBaseFeePerDaGas)]\nunconstrained fn base_fee_per_da_gas_opcode() -> u128 {}\n\n#[oracle(avmOpcodeL2GasLeft)]\nunconstrained fn l2_gas_left_opcode() -> u32 {}\n\n#[oracle(avmOpcodeDaGasLeft)]\nunconstrained fn da_gas_left_opcode() -> u32 {}\n\n#[oracle(avmOpcodeIsStaticCall)]\nunconstrained fn is_static_call_opcode() -> u1 {}\n\n#[oracle(avmOpcodeNoteHashExists)]\nunconstrained fn note_hash_exists_opcode(note_hash: Field, leaf_index: u64) -> u1 {}\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) -> u1 {}\n\n#[oracle(avmOpcodeEmitNullifier)]\nunconstrained fn emit_nullifier_opcode(nullifier: Field) {}\n\n// TODO(#11124): rename unencrypted to public in avm\n#[oracle(avmOpcodeEmitUnencryptedLog)]\nunconstrained fn emit_public_log_opcode(message: [Field]) {}\n\n#[oracle(avmOpcodeL1ToL2MsgExists)]\nunconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: u64) -> u1 {}\n\n#[oracle(avmOpcodeSendL2ToL1Msg)]\nunconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(avmOpcodeCalldataCopy)]\nunconstrained fn calldata_copy_opcode(cdoffset: u32, copy_size: u32) -> [Field; N] {}\n\n#[oracle(avmOpcodeReturndataSize)]\nunconstrained fn returndata_size_opcode() -> u32 {}\n\n#[oracle(avmOpcodeReturndataCopy)]\nunconstrained fn returndata_copy_opcode(rdoffset: u32, copy_size: u32) -> [Field] {}\n\n#[oracle(avmOpcodeReturn)]\nunconstrained fn return_opcode(returndata: [Field]) {}\n\n// This opcode reverts using the exact data given. In general it should only be used\n// to do rethrows, where the revert data is the same as the original revert data.\n// For normal reverts, use Noir's `assert` which, on top of reverting, will also add\n// an error selector to the revert data.\n#[oracle(avmOpcodeRevert)]\nunconstrained fn revert_opcode(revertdata: [Field]) {}\n\n#[oracle(avmOpcodeCall)]\nunconstrained fn call_opcode(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field],\n) {}\n\n#[oracle(avmOpcodeStaticCall)]\nunconstrained fn call_static_opcode(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field],\n) {}\n\n#[oracle(avmOpcodeSuccessCopy)]\nunconstrained fn success_copy_opcode() -> bool {}\n\n#[oracle(avmOpcodeStorageRead)]\nunconstrained fn storage_read_opcode(storage_slot: Field) -> Field {}\n\n#[oracle(avmOpcodeStorageWrite)]\nunconstrained fn storage_write_opcode(storage_slot: Field, value: Field) {}\n" + }, + "71": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/context/utility_context.nr", + "source": "use crate::oracle::{\n execution::{get_block_number, get_chain_id, get_contract_address, get_timestamp, get_version},\n storage::storage_read,\n};\nuse dep::protocol_types::{address::AztecAddress, traits::Packable};\n\npub struct UtilityContext {\n block_number: u32,\n timestamp: u64,\n contract_address: AztecAddress,\n version: Field,\n chain_id: Field,\n}\n\nimpl UtilityContext {\n pub unconstrained 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 a UtilityContext in an environment in which these oracles are not\n // available.\n let block_number = get_block_number();\n let timestamp = get_timestamp();\n let contract_address = get_contract_address();\n let version = get_version();\n let chain_id = get_chain_id();\n Self { block_number, timestamp, contract_address, version, chain_id }\n }\n\n pub unconstrained fn at(contract_address: AztecAddress) -> Self {\n let block_number = get_block_number();\n let timestamp = get_timestamp();\n let chain_id = get_chain_id();\n let version = get_version();\n Self { block_number, timestamp, contract_address, version, chain_id }\n }\n\n pub unconstrained fn at_historical(contract_address: AztecAddress, block_number: u32) -> Self {\n let timestamp = get_timestamp();\n let chain_id = get_chain_id();\n let version = get_version();\n Self { block_number, timestamp, contract_address, version, chain_id }\n }\n\n pub fn block_number(self) -> u32 {\n self.block_number\n }\n\n pub fn timestamp(self) -> u64 {\n self.timestamp\n }\n\n pub fn this_address(self) -> AztecAddress {\n self.contract_address\n }\n\n pub fn version(self) -> Field {\n self.version\n }\n\n pub fn chain_id(self) -> Field {\n self.chain_id\n }\n\n pub unconstrained fn raw_storage_read(\n self: Self,\n storage_slot: Field,\n ) -> [Field; N] {\n storage_read(self.this_address(), storage_slot, self.block_number())\n }\n\n pub unconstrained fn storage_read(self, storage_slot: Field) -> T\n where\n T: Packable,\n {\n T::unpack(self.raw_storage_read(storage_slot))\n }\n}\n" + }, + "73": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/event/event_selector.nr", + "source": "use dep::protocol_types::{\n hash::poseidon2_hash_bytes,\n traits::{Deserialize, Empty, FromField, Serialize, ToField},\n};\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct EventSelector {\n // 1st 4-bytes (big-endian leftmost) of abi-encoding of an event.\n inner: u32,\n}\n\nimpl FromField for EventSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for EventSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for EventSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl EventSelector {\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 = poseidon2_hash_bytes(bytes);\n\n // `hash` is automatically truncated to fit within 32 bits.\n EventSelector::from_field(hash)\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n" + }, + "75": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/hash.nr", + "source": "use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__FUNCTION_ARGS, GENERATOR_INDEX__MESSAGE_NULLIFIER,\n GENERATOR_INDEX__PUBLIC_BYTECODE, GENERATOR_INDEX__PUBLIC_CALLDATA,\n GENERATOR_INDEX__SECRET_HASH, MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS,\n },\n hash::{\n poseidon2_hash_subarray, poseidon2_hash_with_separator, poseidon2_hash_with_separator_slice,\n sha256_to_field,\n },\n point::Point,\n traits::{Hash, ToField},\n};\n\npub use dep::protocol_types::hash::{compute_siloed_nullifier, pedersen_hash};\n\npub fn pedersen_commitment(inputs: [Field; N], hash_index: u32) -> Point {\n std::hash::pedersen_commitment_with_separator(inputs, hash_index)\n}\n\npub fn compute_secret_hash(secret: Field) -> Field {\n poseidon2_hash_with_separator([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_l1_to_l2_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field,\n leaf_index: Field,\n) -> Field {\n let mut hash_bytes = [0 as u8; 224];\n let sender_bytes: [u8; 32] = sender.to_field().to_be_bytes();\n let chain_id_bytes: [u8; 32] = chain_id.to_be_bytes();\n let recipient_bytes: [u8; 32] = recipient.to_field().to_be_bytes();\n let version_bytes: [u8; 32] = version.to_be_bytes();\n let content_bytes: [u8; 32] = content.to_be_bytes();\n let secret_hash_bytes: [u8; 32] = secret_hash.to_be_bytes();\n let leaf_index_bytes: [u8; 32] = leaf_index.to_be_bytes();\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 hash_bytes[i + 192] = leaf_index_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\npub fn compute_l1_to_l2_message_nullifier(message_hash: Field, secret: Field) -> Field {\n poseidon2_hash_with_separator([message_hash, secret], GENERATOR_INDEX__MESSAGE_NULLIFIER)\n}\n\npub struct ArgsHasher {\n pub 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\n// Computes the hash of input arguments or return values for private functions, or for authwit creation.\npub fn hash_args_array(args: [Field; N]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n poseidon2_hash_with_separator(args, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n// Same as `hash_args_array`, but takes a slice instead of an array.\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n poseidon2_hash_with_separator_slice(args, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n// Computes the hash of calldata for public functions.\npub fn hash_calldata_array(calldata: [Field; N]) -> Field {\n if calldata.len() == 0 {\n 0\n } else {\n poseidon2_hash_with_separator(calldata, GENERATOR_INDEX__PUBLIC_CALLDATA)\n }\n}\n\n// Same as `hash_calldata_array`, but takes a slice instead of an array.\npub fn hash_calldata(calldata: [Field]) -> Field {\n if calldata.len() == 0 {\n 0\n } else {\n poseidon2_hash_with_separator_slice(calldata, GENERATOR_INDEX__PUBLIC_CALLDATA)\n }\n}\n\n/**\n * Computes the public bytecode commitment for a contract class.\n * The commitment is `hash([separator, ...bytecode])` where bytecode omits the length prefix present\n * in `packed_bytecode`.\n *\n * @param packed_bytecode - The packed bytecode of the contract class. 0th word is the length in bytes.\n * packed_bytecode is mutable so that we can avoid copying the array to construct one starting with\n * separator instead of length.\n * @returns The public bytecode commitment.\n */\npub fn compute_public_bytecode_commitment(\n mut packed_public_bytecode: [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS],\n) -> Field {\n // First field element contains the length of the bytecode\n let bytecode_length_in_bytes: u32 = packed_public_bytecode[0] as u32;\n let bytecode_length_in_fields: u32 =\n (bytecode_length_in_bytes / 31) + (bytecode_length_in_bytes % 31 != 0) as u32;\n // Don't allow empty public bytecode.\n // AVM doesn't handle execution of contracts that exist with empty bytecode.\n assert(bytecode_length_in_fields != 0);\n assert(bytecode_length_in_fields < MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS);\n\n // Packed_bytecode's 0th entry is the length. Replace it with separator before hashing.\n let separator = GENERATOR_INDEX__PUBLIC_BYTECODE.to_field();\n packed_public_bytecode[0] = separator;\n // +1 to length to account for the separator\n let nonzero_length = bytecode_length_in_fields + 1;\n\n poseidon2_hash_subarray(packed_public_bytecode, nonzero_length)\n // NOTE: we use poseidon2_hash_subarray here because we want to hash the bytecode only up to\n // its nonzero length. We do NOT want to include a `1` at the end to indicate \"variable length\",\n // and we want to enforce that all trailing elements are zero.\n}\n\n#[test]\nunconstrained fn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..100 {\n input.add(i as Field);\n }\n let hash = input.hash();\n dep::std::println(hash);\n assert(hash == 0x19b0d74feb06ebde19edd85a28986c97063e84b3b351a8b666c7cac963ce655f);\n}\n" + }, + "92": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/keys/getters/mod.nr", + "source": "use crate::{\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX},\n oracle::{\n key_validation_request::get_key_validation_request,\n keys::get_public_keys_and_partial_address,\n },\n};\nuse dep::protocol_types::{address::AztecAddress, public_keys::PublicKeys};\n\npub unconstrained fn get_nsk_app(npk_m_hash: Field) -> Field {\n get_key_validation_request(npk_m_hash, NULLIFIER_INDEX).sk_app\n}\n\n// A helper function that gets app-siloed outgoing viewing key for a given `ovpk_m_hash`. This function is used\n// in unconstrained contexts only - when computing unconstrained note logs. The safe alternative is `request_ovsk_app`\n// function defined on `PrivateContext`.\npub unconstrained fn get_ovsk_app(ovpk_m_hash: Field) -> Field {\n get_key_validation_request(ovpk_m_hash, OUTGOING_INDEX).sk_app\n}\n\n// Returns all public keys for a given account, applying proper constraints to the context. We read all\n// keys at once since the constraints for reading them all are actually fewer than if we read them one at a time - any\n// read keys that are not required by the caller can simply be discarded.\npub fn get_public_keys(account: AztecAddress) -> PublicKeys {\n // Safety: Public keys are constrained by showing their inclusion in the address's preimage.\n let (public_keys, partial_address) = unsafe { get_public_keys_and_partial_address(account) };\n assert_eq(\n account,\n AztecAddress::compute(public_keys, partial_address),\n \"Invalid public keys hint for address\",\n );\n\n public_keys\n}\n\nmod test {\n use super::get_public_keys;\n\n use crate::test::helpers::test_environment::TestEnvironment;\n use protocol_types::traits::Serialize;\n use std::test::OracleMock;\n\n global KEY_ORACLE_RESPONSE_LENGTH: u32 = 13; // 12 fields for the keys, one field for the partial address\n\n #[test(should_fail_with = \"Invalid public keys hint for address\")]\n unconstrained fn get_public_keys_fails_with_bad_hint() {\n let mut env = TestEnvironment::new();\n let account = env.create_light_account();\n\n // Instead of querying for some unknown account, which would result in the oracle erroring out, we mock a bad oracle\n // response to check that the circuit properly checks the address derivation.\n let mut random_keys_and_partial_address = [0; KEY_ORACLE_RESPONSE_LENGTH];\n // We use randomly generated points on the curve, and a random partial address to ensure that\n // this combination does not derive the address and we should see the assertion fail.\n // npk_m\n random_keys_and_partial_address[0] =\n 0x292364b852c6c6f01472951e76a39cbcf074591fd0e063a81965e7b51ad868a5;\n random_keys_and_partial_address[1] =\n 0x0a687b46cdc9238f1c311f126aaaa4acbd7a737bff2efd7aeabdb8d805843a27;\n random_keys_and_partial_address[2] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // ivpk_m\n random_keys_and_partial_address[3] =\n 0x173c5229a00c5425255680dd6edc27e278c48883991f348fe6985de43b4ec25f;\n random_keys_and_partial_address[4] =\n 0x1698608e23b5f6c2f43c49a559108bb64e2247b8fc2da842296a416817f40b7f;\n random_keys_and_partial_address[5] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // ovpk_m\n random_keys_and_partial_address[6] =\n 0x1bad2f7d1ad960a1bd0fe4d2c8d17f5ab4a86ef8b103e0a9e7f67ec0d3b4795e;\n random_keys_and_partial_address[7] =\n 0x206db87110abbecc9fbaef2c865189d94ef2c106202f734ee4eba9257fd28bf1;\n random_keys_and_partial_address[8] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // tpk_m\n random_keys_and_partial_address[9] =\n 0x05e3bd9cfe6b47daa139613619cf7d7fd8bb0112b6f2908caa6d9b536ed948ed;\n random_keys_and_partial_address[10] =\n 0x051066f877c9df47552d02e7dc32127ff4edefc8498e813bca1cbd3f5d1be429;\n random_keys_and_partial_address[11] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // partial address\n random_keys_and_partial_address[12] =\n 0x236703e2cb00a182e024e98e9f759231b556d25ff19f98896cebb69e9e678cc9;\n\n let _ = OracleMock::mock(\"utilityGetPublicKeysAndPartialAddress\").returns(\n random_keys_and_partial_address.serialize(),\n );\n let _ = get_public_keys(account);\n }\n}\n" + }, + "96": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/macros/aztec.nr", + "source": "use crate::macros::{\n dispatch::generate_public_dispatch,\n functions::{stub_registry, utils::check_each_fn_macroified},\n notes::NOTES,\n storage::STORAGE_LAYOUT_NAME,\n utils::{get_trait_impl_method, module_has_storage},\n};\n\n/// Marks a contract as an Aztec contract, generating the interfaces for its functions and notes, as well as injecting\n/// the `sync_private_state` utility function.\n/// Note: This is a module annotation, so the returned quote gets injected inside the module (contract) itself.\npub comptime fn aztec(m: Module) -> Quoted {\n let interface = generate_contract_interface(m);\n\n // Functions that don't have #[private], #[public], #[utility], #[contract_library_method], or #[test] are not\n // allowed in contracts.\n check_each_fn_macroified(m);\n\n // We generate `_compute_note_hash_and_nullifier`, `sync_private_state` and `process_message`\n // functions only if they are not already implemented. If they are implemented we just insert empty\n // quotes.\n let contract_library_method_compute_note_hash_and_nullifier = if !m.functions().any(|f| {\n f.name() == quote { _compute_note_hash_and_nullifier }\n }) {\n generate_contract_library_method_compute_note_hash_and_nullifier()\n } else {\n quote {}\n };\n let sync_private_state = if !m.functions().any(|f| f.name() == quote { sync_private_state }) {\n generate_sync_private_state()\n } else {\n quote {}\n };\n let process_message = if !m.functions().any(|f| f.name() == quote { process_message }) {\n generate_process_message()\n } else {\n quote {}\n };\n let public_dispatch = generate_public_dispatch(m);\n\n quote {\n $interface\n $contract_library_method_compute_note_hash_and_nullifier\n $public_dispatch\n $sync_private_state\n $process_message\n }\n}\n\ncomptime fn generate_contract_interface(m: Module) -> Quoted {\n let module_name = m.name();\n let contract_stubs = stub_registry::get(m);\n let fn_stubs_quote = if contract_stubs.is_some() {\n contract_stubs.unwrap().join(quote {})\n } else {\n quote {}\n };\n\n let has_storage_layout = module_has_storage(m) & STORAGE_LAYOUT_NAME.get(m).is_some();\n let storage_layout_getter = if has_storage_layout {\n let storage_layout_name = STORAGE_LAYOUT_NAME.get(m).unwrap();\n quote {\n pub fn storage_layout() -> StorageLayoutFields {\n $storage_layout_name.fields\n }\n }\n } else {\n quote {}\n };\n\n let library_storage_layout_getter = if has_storage_layout {\n quote {\n #[contract_library_method]\n $storage_layout_getter\n }\n } else {\n quote {}\n };\n\n quote {\n pub struct $module_name {\n pub target_contract: dep::aztec::protocol_types::address::AztecAddress\n }\n\n impl $module_name {\n $fn_stubs_quote\n\n pub fn at(\n addr: aztec::protocol_types::address::AztecAddress\n ) -> Self {\n Self { target_contract: addr }\n }\n\n pub fn interface() -> Self {\n Self { target_contract: aztec::protocol_types::address::AztecAddress::zero() }\n }\n\n $storage_layout_getter\n }\n\n #[contract_library_method]\n pub fn at(\n addr: aztec::protocol_types::address::AztecAddress\n ) -> $module_name {\n $module_name { target_contract: addr }\n }\n\n #[contract_library_method]\n pub fn interface() -> $module_name {\n $module_name { target_contract: aztec::protocol_types::address::AztecAddress::zero() }\n }\n\n $library_storage_layout_getter\n\n }\n}\n\n/// Generates a contract library method called `_compute_note_hash_and_nullifier` which is used for note\n/// discovery (to create the `aztec::messages::discovery::ComputeNoteHashAndNullifier` function) and to implement the\n/// `compute_note_hash_and_nullifier` unconstrained contract function.\ncomptime fn generate_contract_library_method_compute_note_hash_and_nullifier() -> Quoted {\n if NOTES.len() > 0 {\n // Contracts that do define notes produce an if-else chain where `note_type_id` is matched against the\n // `get_note_type_id()` function of each note type that we know of, in order to identify the note type. Once we\n // know it we call we correct `unpack` method from the `Packable` trait to obtain the underlying note type, and\n // compute the note hash (non-siloed) and inner nullifier (also non-siloed).\n\n let mut if_note_type_id_match_statements_list = &[];\n for i in 0..NOTES.len() {\n let typ = NOTES.get(i);\n\n let get_note_type_id = get_trait_impl_method(\n typ,\n quote { crate::note::note_interface::NoteType },\n quote { get_id },\n );\n let unpack = get_trait_impl_method(\n typ,\n quote { crate::protocol_types::traits::Packable },\n quote { unpack },\n );\n\n let compute_note_hash = get_trait_impl_method(\n typ,\n quote { crate::note::note_interface::NoteHash },\n quote { compute_note_hash },\n );\n\n let compute_nullifier_unconstrained = get_trait_impl_method(\n typ,\n quote { crate::note::note_interface::NoteHash },\n quote { compute_nullifier_unconstrained },\n );\n\n let if_or_else_if = if i == 0 {\n quote { if }\n } else {\n quote { else if }\n };\n\n if_note_type_id_match_statements_list = if_note_type_id_match_statements_list.push_back(\n quote {\n $if_or_else_if note_type_id == $get_note_type_id() {\n // As an extra safety check we make sure that the packed_note BoundedVec has the expected\n // length, since we're about to interpret its raw storage as a fixed-size array by calling the\n // unpack function on it.\n let expected_len = <$typ as $crate::protocol_types::traits::Packable>::N;\n let actual_len = packed_note.len();\n assert(\n actual_len == expected_len,\n f\"Expected packed note of length {expected_len} but got {actual_len} for note type id {note_type_id}\"\n );\n\n let note = $unpack(aztec::utils::array::subarray(packed_note.storage(), 0));\n\n let note_hash = $compute_note_hash(note, storage_slot);\n \n // The message discovery process finds settled notes, that is, notes that were created in prior\n // transactions and are therefore already part of the note hash tree. We therefore compute the\n // nullification note hash by treating the note as a settled note with the provided note nonce.\n let note_hash_for_nullify = aztec::note::utils::compute_note_hash_for_nullify(\n aztec::note::retrieved_note::RetrievedNote{ \n note, \n contract_address, \n metadata: aztec::note::note_metadata::SettledNoteMetadata::new(note_nonce).into()\n }, \n storage_slot,\n );\n\n let inner_nullifier = $compute_nullifier_unconstrained(note, note_hash_for_nullify);\n\n Option::some(\n aztec::messages::discovery::NoteHashAndNullifier {\n note_hash, inner_nullifier\n }\n )\n }\n },\n );\n }\n\n let if_note_type_id_match_statements = if_note_type_id_match_statements_list.join(quote {});\n\n quote {\n /// Unpacks an array into a note corresponding to `note_type_id` and then computes its note hash\n /// (non-siloed) and inner nullifier (non-siloed) assuming the note has been inserted into the note hash\n /// tree with `note_nonce`.\n ///\n /// The signature of this function notably matches the `aztec::messages::discovery::ComputeNoteHashAndNullifier` type,\n /// and so it can be used to call functions from that module such as `discover_new_messages`, \n /// `do_process_log` and `attempt_note_discovery`.\n ///\n /// This function is automatically injected by the `#[aztec]` macro.\n #[contract_library_method]\n unconstrained fn _compute_note_hash_and_nullifier(\n packed_note: BoundedVec,\n storage_slot: Field,\n note_type_id: Field,\n contract_address: aztec::protocol_types::address::AztecAddress,\n note_nonce: Field,\n ) -> Option {\n $if_note_type_id_match_statements\n else {\n Option::none()\n }\n }\n }\n } else {\n // Contracts with no notes still implement this function to avoid having special-casing, the implementation\n // simply throws immediately.\n quote {\n /// This contract does not use private notes, so this function should never be called as it will\n /// unconditionally fail.\n ///\n /// This function is automatically injected by the `#[aztec]` macro.\n #[contract_library_method]\n unconstrained fn _compute_note_hash_and_nullifier(\n _packed_note: BoundedVec,\n _storage_slot: Field,\n _note_type_id: Field,\n _contract_address: aztec::protocol_types::address::AztecAddress,\n _nonce: Field,\n ) -> Option {\n panic(f\"This contract does not use private notes\")\n }\n }\n }\n}\n\ncomptime fn generate_sync_private_state() -> Quoted {\n // We obtain the `utility` function on the next line instead of directly doing\n // `#[aztec::macros::functions::utility]` in the returned quote because the latter would result in the function\n // attribute having the full path in the ABI. This is undesirable because we use the information in the ABI only\n // to determine whether a function is `private`, `public`, or `utility`.\n let utility = crate::macros::functions::utility;\n\n // All we need to do here is trigger message discovery, but this is already done by the #[utility] macro - we don't\n // need to do anything extra.\n quote {\n #[$utility]\n unconstrained fn sync_private_state() {\n }\n }\n}\n\ncomptime fn generate_process_message() -> Quoted {\n // We obtain the `utility` function on the next line instead of directly doing\n // `#[aztec::macros::functions::utility]` in the returned quote because the latter would result in the function\n // attribute having the full path in the ABI. This is undesirable because we use the information in the ABI only\n // to determine whether a function is `private`, `public`, or `utility`.\n let utility = crate::macros::functions::utility;\n\n // TODO(#15012): Here we use PRIVATE_LOG_CIPHERTEXT_LEN for message ciphertext length. Fix message vs log naming.\n quote {\n #[$utility]\n unconstrained fn process_message(\n message_ciphertext: BoundedVec,\n message_context: aztec::messages::processing::message_context::MessageContext,\n ) {\n aztec::messages::discovery::process_message::do_process_message(\n context.this_address(),\n _compute_note_hash_and_nullifier,\n message_ciphertext,\n message_context,\n );\n }\n }\n}\n" + }, + "97": { + "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/macros/dispatch.nr", + "source": "use super::utils::{compute_fn_selector, size_in_fields};\nuse poseidon::poseidon2::Poseidon2Hasher;\nuse std::{collections::umap::UHashMap, hash::BuildHasherDefault, panic};\n\n/// Returns an `fn public_dispatch(...)` function for the given module that's assumed to be an Aztec contract.\npub comptime fn generate_public_dispatch(m: Module) -> Quoted {\n let functions = m.functions();\n let functions =\n functions.filter(|function: FunctionDefinition| function.has_named_attribute(\"public\"));\n\n let unit = get_type::<()>();\n\n let seen_selectors =\n &mut UHashMap::>::default();\n\n let ifs = functions.map(|function: FunctionDefinition| {\n let parameters = function.parameters();\n let return_type = function.return_type();\n\n let selector: Field = compute_fn_selector(function);\n let fn_name = function.name();\n\n // Since function selectors are computed as the first 4 bytes of the hash of the function signature,\n // it's possible to have collisions. With the following check, we ensure it doesn't happen within\n // the same contract.\n if seen_selectors.contains_key(selector) {\n let existing_fn = seen_selectors.get(selector).unwrap();\n panic(\n f\"Public function selector collision detected between functions '{fn_name}' and '{existing_fn}'\",\n );\n }\n seen_selectors.insert(selector, fn_name);\n\n let mut parameters_size = 0;\n for param in parameters {\n parameters_size += size_in_fields(param.1);\n }\n\n let initial_read = if parameters.len() == 0 {\n quote {}\n } else {\n // The initial calldata_copy offset is 1 to skip the Field selector\n // The expected calldata is the serialization of\n // - FunctionSelector: the selector of the function intended to dispatch\n // - Parameters: the parameters of the function intended to dispatch\n // That is, exactly what is expected for a call to the target function,\n // but with a selector added at the beginning.\n quote {\n let input_calldata: [Field; $parameters_size] = dep::aztec::context::public_context::calldata_copy(1, $parameters_size);\n let mut reader = dep::aztec::protocol_types::utils::reader::Reader::new(input_calldata);\n }\n };\n\n let parameter_index: &mut u32 = &mut 0;\n let reads = parameters.map(|param: (Quoted, Type)| {\n let parameter_index_value = *parameter_index;\n let param_name = f\"arg{parameter_index_value}\".quoted_contents();\n let param_type = param.1;\n let read = quote {\n let $param_name: $param_type = reader.read_struct(dep::aztec::protocol_types::traits::Deserialize::deserialize);\n };\n *parameter_index += 1;\n quote { $read }\n });\n let read = reads.join(quote { });\n\n let mut args = &[];\n for parameter_index in 0..parameters.len() {\n let param_name = f\"arg{parameter_index}\".quoted_contents();\n args = args.push_back(quote { $param_name });\n }\n\n let args = args.join(quote { , });\n // name of the function is assigned just before the call so debug metadata doesn't span most of this macro when figuring out where the call comes from.\n let name = function.name();\n let call = quote { $name($args) };\n\n let return_code = if return_type == unit {\n quote {\n $call;\n // Force early return.\n dep::aztec::context::public_context::avm_return([]);\n }\n } else {\n quote {\n let return_value = dep::aztec::protocol_types::traits::Serialize::serialize($call);\n dep::aztec::context::public_context::avm_return(return_value.as_slice());\n }\n };\n\n let if_ = quote {\n if selector == $selector {\n $initial_read\n $read\n $return_code\n }\n };\n if_\n });\n\n if ifs.len() == 0 {\n // No dispatch function if there are no public functions\n quote {}\n } else {\n let ifs = ifs.push_back(quote { panic(f\"Unknown selector {selector}\") });\n let dispatch = ifs.join(quote { });\n\n let body = quote {\n // We mark this as public because our whole system depends on public\n // functions having this attribute. However, the public MACRO will\n // handle the public_dispatch function specially and do nothing.\n #[public]\n pub unconstrained fn public_dispatch(selector: Field) {\n $dispatch\n }\n };\n\n body\n }\n}\n\ncomptime fn get_type() -> Type {\n let t: T = std::mem::zeroed();\n std::meta::type_of(t)\n}\n" + } + } +} diff --git a/app/embedded-wallet.ts b/app/embedded-wallet.ts index 2ca9a57..0443ee2 100644 --- a/app/embedded-wallet.ts +++ b/app/embedded-wallet.ts @@ -3,7 +3,7 @@ import { createLogger, createAztecNodeClient, AztecAddress, - getContractInstanceFromDeployParams, + getContractInstanceFromInstantiationParams, ContractFunctionInteraction, SponsoredFeePaymentMethod, type PXE, @@ -16,7 +16,10 @@ import { getEcdsaRAccount } from '@aztec/accounts/ecdsa/lazy'; import { getSchnorrAccount } from '@aztec/accounts/schnorr/lazy'; import { getPXEServiceConfig } from '@aztec/pxe/config'; import { createPXEService } from '@aztec/pxe/client/lazy'; -import { type ContractArtifact, getDefaultInitializer } from '@aztec/stdlib/abi'; +import { + type ContractArtifact, + getDefaultInitializer, +} from '@aztec/stdlib/abi'; import { getInitialTestAccounts } from '@aztec/accounts/testing'; const PROVER_ENABLED = true; @@ -31,7 +34,7 @@ export class EmbeddedWallet { private pxe!: PXE; connectedAccount: AccountWallet | null = null; - constructor(private nodeUrl: string) {} + constructor(private nodeUrl: string) { } async initialize() { // Create Aztec Node Client @@ -41,7 +44,9 @@ export class EmbeddedWallet { const config = getPXEServiceConfig(); config.l1Contracts = await aztecNode.getL1ContractAddresses(); config.proverEnabled = PROVER_ENABLED; - this.pxe = await createPXEService(aztecNode, config); + this.pxe = await createPXEService(aztecNode, config, { + useLogSuffix: true, + }); // Register Sponsored FPC Contract with PXE await this.pxe.registerContract({ @@ -56,7 +61,7 @@ export class EmbeddedWallet { // Internal method to use the Sponsored FPC Contract for fee payment async #getSponsoredPFCContract() { - const instance = await getContractInstanceFromDeployParams( + const instance = await getContractInstanceFromInstantiationParams( SponsoredFPCContractArtifact, { salt: new Fr(SPONSORED_FPC_SALT), @@ -76,7 +81,12 @@ export class EmbeddedWallet { async connectTestAccount(index: number) { const testAccounts = await getInitialTestAccounts(); const account = testAccounts[index]; - const schnorrAccount = await getSchnorrAccount(this.pxe, account.secret, account.signingKey, account.salt); + const schnorrAccount = await getSchnorrAccount( + this.pxe, + account.secret, + account.signingKey, + account.salt + ); await schnorrAccount.register(); const wallet = await schnorrAccount.getWallet(); @@ -108,6 +118,7 @@ export class EmbeddedWallet { const deployMethod = await ecdsaAccount.getDeployMethod(); const sponsoredPFCContract = await this.#getSponsoredPFCContract(); const deployOpts = { + from: AztecAddress.ZERO, contractAddressSalt: Fr.fromString(ecdsaAccount.salt.toString()), fee: { paymentMethod: await ecdsaAccount.getSelfPaymentMethod( @@ -115,8 +126,8 @@ export class EmbeddedWallet { ), }, universalDeploy: true, - skipClassRegistration: true, - skipPublicDeployment: true, + skipClassPublication: true, + skipInstancePublication: true, }; const provenInteraction = await deployMethod.prove(deployOpts); @@ -172,12 +183,15 @@ export class EmbeddedWallet { deploymentSalt: Fr, constructorArgs: any[] ) { - const instance = await getContractInstanceFromDeployParams(artifact, { - constructorArtifact: getDefaultInitializer(artifact), - constructorArgs: constructorArgs, - deployer: deployer, - salt: deploymentSalt, - }); + const instance = await getContractInstanceFromInstantiationParams( + artifact, + { + constructorArtifact: getDefaultInitializer(artifact), + constructorArgs: constructorArgs, + deployer: deployer, + salt: deploymentSalt, + } + ); await this.pxe.registerContract({ instance, @@ -189,6 +203,7 @@ export class EmbeddedWallet { async sendTransaction(interaction: ContractFunctionInteraction) { const sponsoredPFCContract = await this.#getSponsoredPFCContract(); const provenInteraction = await interaction.prove({ + from: this.connectedAccount.getAddress(), fee: { paymentMethod: new SponsoredFeePaymentMethod( sponsoredPFCContract.address @@ -201,7 +216,9 @@ export class EmbeddedWallet { // Simulate a transaction async simulateTransaction(interaction: ContractFunctionInteraction) { - const res = await interaction.simulate(); + const res = await interaction.simulate({ + from: this.connectedAccount.getAddress(), + }); return res; } -} +} \ No newline at end of file diff --git a/app/main.ts b/app/main.ts index 7e77bf3..bfc4f72 100644 --- a/app/main.ts +++ b/app/main.ts @@ -6,7 +6,7 @@ import { type AccountWallet, } from '@aztec/aztec.js'; import { EmbeddedWallet } from './embedded-wallet'; -import { EasyPrivateVotingContract } from './artifacts/EasyPrivateVoting'; +import { PrivateVotingContract } from './artifacts/PrivateVoting'; // DOM Elements const createAccountButton = @@ -45,7 +45,7 @@ document.addEventListener('DOMContentLoaded', async () => { // Register voting contract with wallet/PXE displayStatusMessage('Registering contracts...'); await wallet.registerContract( - EasyPrivateVotingContract.artifact, + PrivateVotingContract.artifact, AztecAddress.fromString(deployerAddress), Fr.fromString(deploymentSalt), [AztecAddress.fromString(deployerAddress)] @@ -145,7 +145,7 @@ voteButton.addEventListener('click', async (e) => { } // Prepare contract interaction - const votingContract = await EasyPrivateVotingContract.at( + const votingContract = await PrivateVotingContract.at( AztecAddress.fromString(contractAddress), connectedAccount ); @@ -177,7 +177,7 @@ async function updateVoteTally(account: Wallet) { displayStatusMessage('Updating vote tally...'); // Prepare contract interaction - const votingContract = await EasyPrivateVotingContract.at( + const votingContract = await PrivateVotingContract.at( AztecAddress.fromString(contractAddress), account ); diff --git a/contracts/Nargo.toml b/contracts/Nargo.toml index 730a874..d7c4edf 100644 --- a/contracts/Nargo.toml +++ b/contracts/Nargo.toml @@ -3,6 +3,6 @@ name = "private_voting" type = "contract" [dependencies] -aztec = { git="https://github.com/AztecProtocol/aztec-packages/", tag="v0.87.4", directory="noir-projects/aztec-nr/aztec" } -value_note = { git="https://github.com/AztecProtocol/aztec-packages/", tag="v0.87.4", directory="noir-projects/aztec-nr/value-note"} -easy_private_state = { git="https://github.com/AztecProtocol/aztec-packages/", tag="v0.87.4", directory="noir-projects/aztec-nr/easy-private-state"} +aztec = { git="https://github.com/AztecProtocol/aztec-packages/", tag="v2.0.2", directory="noir-projects/aztec-nr/aztec" } +value_note = { git="https://github.com/AztecProtocol/aztec-packages/", tag="v2.0.2", directory="noir-projects/aztec-nr/value-note"} +easy_private_state = { git="https://github.com/AztecProtocol/aztec-packages/", tag="v2.0.2", directory="noir-projects/aztec-nr/easy-private-state"} diff --git a/contracts/src/main.nr b/contracts/src/main.nr index e38162c..f99f495 100644 --- a/contracts/src/main.nr +++ b/contracts/src/main.nr @@ -1,14 +1,14 @@ use dep::aztec::macros::aztec; #[aztec] -pub contract EasyPrivateVoting { - use dep::aztec:: macros::{ - functions::{initializer, internal, private, public, utility}, - storage::storage - }; +pub contract PrivateVoting { use dep::aztec::keys::getters::get_public_keys; - use dep::aztec::prelude::{AztecAddress, Map, PublicImmutable, PublicMutable}; - use dep::aztec::protocol_types::traits::{Hash, ToField}; + use dep::aztec::macros::{ + functions::{initializer, internal, private, public, utility}, + storage::storage, + }; + use dep::aztec::protocol_types::{address::AztecAddress, traits::{Hash, ToField}}; + use dep::aztec::state_vars::{Map, PublicImmutable, PublicMutable}; #[storage] struct Storage { @@ -23,7 +23,7 @@ pub contract EasyPrivateVoting { fn constructor(admin: AztecAddress) { storage.admin.write(admin); storage.vote_ended.write(false); - storage.active_at_block.initialize(context.block_number() as u32); + storage.active_at_block.initialize(context.block_number()); } #[private] @@ -33,7 +33,7 @@ pub contract EasyPrivateVoting { let secret = context.request_nsk_app(msg_sender_npk_m_hash); // get secret key of caller of function let nullifier = std::hash::pedersen_hash([context.msg_sender().to_field(), secret]); // derive nullifier from sender and secret context.push_nullifier(nullifier); - EasyPrivateVoting::at(context.this_address()).add_to_tally_public(candidate).enqueue( + PrivateVoting::at(context.this_address()).add_to_tally_public(candidate).enqueue( &mut context, ); } @@ -56,4 +56,4 @@ pub contract EasyPrivateVoting { unconstrained fn get_vote(candidate: Field) -> Field { storage.tally.at(candidate).read() } -} \ No newline at end of file +} diff --git a/package.json b/package.json index dbabc2f..bc41c96 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ }, "scripts": { "clean": "rm -rf app/dist contracts/target contracts/codegenCache.json", - "compile-contracts": "cd contracts && ${AZTEC_NARGO:-aztec-nargo} compile", + "compile-contracts": "cd contracts && ${AZTEC_NARGO:-aztec-nargo} compile && ${AZTEC_POSTPROCESS:-aztec-postprocess-contract}", "codegen-contracts": "cd contracts && ${AZTEC_BUILDER:-aztec} codegen ./target -o ./target", "copy-artifacts": "cp contracts/target/*.json contracts/target/*.ts app/artifacts", "build-contracts": "yarn clean && yarn compile-contracts && yarn codegen-contracts && yarn copy-artifacts", @@ -22,14 +22,14 @@ "lint": "prettier --check ./src" }, "dependencies": { - "@aztec/accounts": "0.87.4", - "@aztec/aztec.js": "0.87.4", - "@aztec/constants": "0.87.4", - "@aztec/foundation": "0.87.4", - "@aztec/kv-store": "0.87.4", - "@aztec/noir-contracts.js": "0.87.4", - "@aztec/pxe": "0.87.4", - "@aztec/stdlib": "0.87.4" + "@aztec/accounts": "2.0.2", + "@aztec/aztec.js": "2.0.2", + "@aztec/constants": "2.0.2", + "@aztec/foundation": "2.0.2", + "@aztec/kv-store": "2.0.2", + "@aztec/noir-contracts.js": "2.0.2", + "@aztec/pxe": "2.0.2", + "@aztec/stdlib": "2.0.2" }, "devDependencies": { "@playwright/test": "1.52.0", diff --git a/scripts/deploy.ts b/scripts/deploy.ts index fef817c..7e2bdc4 100644 --- a/scripts/deploy.ts +++ b/scripts/deploy.ts @@ -5,7 +5,7 @@ import { createAztecNodeClient, DeployMethod, Fr, - getContractInstanceFromDeployParams, + getContractInstanceFromInstantiationParams, PublicKeys, type PXE, SponsoredFeePaymentMethod, @@ -18,7 +18,7 @@ import { getDefaultInitializer } from '@aztec/stdlib/abi'; import { SponsoredFPCContractArtifact } from '@aztec/noir-contracts.js/SponsoredFPC'; import { SPONSORED_FPC_SALT } from '@aztec/constants'; // @ts-ignore -import { EasyPrivateVotingContract } from '../app/artifacts/EasyPrivateVoting.ts'; +import { PrivateVotingContract } from '../app/artifacts/PrivateVoting.ts'; const AZTEC_NODE_URL = process.env.AZTEC_NODE_URL || 'http://localhost:8080'; const PROVER_ENABLED = process.env.PROVER_ENABLED === 'false' ? false : true; @@ -43,19 +43,15 @@ async function setupPXE() { ...config, }; - const pxe = await createPXEService( - aztecNode, - configWithContracts, - { - store, - useLogSuffix: true, - }, - ); + const pxe = await createPXEService(aztecNode, configWithContracts, { + store, + useLogSuffix: true, + }); return pxe; } async function getSponsoredPFCContract() { - const instance = await getContractInstanceFromDeployParams( + const instance = await getContractInstanceFromInstantiationParams( SponsoredFPCContractArtifact, { salt: new Fr(SPONSORED_FPC_SALT), @@ -74,6 +70,7 @@ async function createAccount(pxe: PXE) { const deployMethod = await ecdsaAccount.getDeployMethod(); const sponsoredPFCContract = await getSponsoredPFCContract(); const deployOpts = { + from: AztecAddress.ZERO, contractAddressSalt: Fr.fromString(ecdsaAccount.salt.toString()), fee: { paymentMethod: await ecdsaAccount.getSelfPaymentMethod( @@ -81,8 +78,8 @@ async function createAccount(pxe: PXE) { ), }, universalDeploy: true, - skipClassRegistration: true, - skipPublicDeployment: true, + skipClassPublication: true, + skipInstancePublication: true, }; const provenInteraction = await deployMethod.prove(deployOpts); await provenInteraction.send().wait({ timeout: 120 }); @@ -98,12 +95,12 @@ async function createAccount(pxe: PXE) { async function deployContract(pxe: PXE, deployer: Wallet) { const salt = Fr.random(); - const contract = await getContractInstanceFromDeployParams( - EasyPrivateVotingContract.artifact, + const contract = await getContractInstanceFromInstantiationParams( + PrivateVotingContract.artifact, { publicKeys: PublicKeys.default(), constructorArtifact: getDefaultInitializer( - EasyPrivateVotingContract.artifact + PrivateVotingContract.artifact ), constructorArgs: [deployer.getAddress().toField()], deployer: deployer.getAddress(), @@ -114,16 +111,17 @@ async function deployContract(pxe: PXE, deployer: Wallet) { const deployMethod = new DeployMethod( contract.publicKeys, deployer, - EasyPrivateVotingContract.artifact, + PrivateVotingContract.artifact, (address: AztecAddress, wallet: Wallet) => - EasyPrivateVotingContract.at(address, wallet), + PrivateVotingContract.at(address, wallet), [deployer.getAddress().toField()], - getDefaultInitializer(EasyPrivateVotingContract.artifact)?.name + getDefaultInitializer(PrivateVotingContract.artifact)?.name ); const sponsoredPFCContract = await getSponsoredPFCContract(); const provenInteraction = await deployMethod.prove({ + from: deployer.getAddress(), contractAddressSalt: salt, fee: { paymentMethod: new SponsoredFeePaymentMethod( @@ -134,7 +132,7 @@ async function deployContract(pxe: PXE, deployer: Wallet) { await provenInteraction.send().wait({ timeout: 120 }); await pxe.registerContract({ instance: contract, - artifact: EasyPrivateVotingContract.artifact, + artifact: PrivateVotingContract.artifact, }); return { @@ -175,7 +173,7 @@ async function createAccountAndDeployContract() { }); // Create a new account - const { wallet, /* signingKey */ } = await createAccount(pxe); + const { wallet /* signingKey */ } = await createAccount(pxe); // // Save the wallet info // const walletInfo = { @@ -207,4 +205,4 @@ createAccountAndDeployContract().catch((error) => { process.exit(1); }); -export { createAccountAndDeployContract }; +export { createAccountAndDeployContract }; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index aecf17e..a4f11f6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,59 +7,58 @@ resolved "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz" integrity sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg== -"@aztec/accounts@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/accounts/-/accounts-0.87.4.tgz" - integrity sha512-TyNvw/0pKNy7MRNqMwlDQEihdiNZE7AbQk2eKZJgVw7JACJ4a/t/tgo4PIgBJEO7Mo2Ia+QguNt5BRiMV4Y7mA== - dependencies: - "@aztec/aztec.js" "0.87.4" - "@aztec/entrypoints" "0.87.4" - "@aztec/ethereum" "0.87.4" - "@aztec/foundation" "0.87.4" - "@aztec/stdlib" "0.87.4" +"@aztec/accounts@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/accounts/-/accounts-2.0.2.tgz#37986b54968324bc711211d471b81e006869627d" + integrity sha512-BZFQuRBCAJe+IZtlfASRk7Ae0x8B8decq+EhFvd258ShkVqw9uKoH4AKEQqQ3W1hJnJ/mnXRrpgt9Kdl/D67NA== + dependencies: + "@aztec/aztec.js" "2.0.2" + "@aztec/entrypoints" "2.0.2" + "@aztec/ethereum" "2.0.2" + "@aztec/foundation" "2.0.2" + "@aztec/stdlib" "2.0.2" tslib "^2.4.0" -"@aztec/aztec.js@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/aztec.js/-/aztec.js-0.87.4.tgz" - integrity sha512-fggZAB0kh2sl/zUj0noSstwqGstF/WZPoI2ScF5KfIozujc9+CrsqyhBxp0LDtiXpQWn9RTfW1OMvd7SjWKrXg== - dependencies: - "@aztec/constants" "0.87.4" - "@aztec/entrypoints" "0.87.4" - "@aztec/ethereum" "0.87.4" - "@aztec/foundation" "0.87.4" - "@aztec/l1-artifacts" "0.87.4" - "@aztec/protocol-contracts" "0.87.4" - "@aztec/stdlib" "0.87.4" +"@aztec/aztec.js@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/aztec.js/-/aztec.js-2.0.2.tgz#12428a0b100ea22b06e36c477377631a98683bc1" + integrity sha512-BF6ua53EpERew9EMRONw8zuFRCTgqMk8WYI2rAJs/uMkYaQfkP5VFiZA69X3FYhnhHhYUf60sfGfCNXeNVTHDA== + dependencies: + "@aztec/constants" "2.0.2" + "@aztec/entrypoints" "2.0.2" + "@aztec/ethereum" "2.0.2" + "@aztec/foundation" "2.0.2" + "@aztec/l1-artifacts" "2.0.2" + "@aztec/protocol-contracts" "2.0.2" + "@aztec/stdlib" "2.0.2" axios "^1.8.2" tslib "^2.4.0" viem "2.23.7" -"@aztec/bb-prover@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/bb-prover/-/bb-prover-0.87.4.tgz" - integrity sha512-jvJnv/rR6jelkDwq6MLQFsZcXFwh6gSHrDBJBMekVyBtzBsr3P9gsvi3ndFXy8KX/oFrKf4EDikW682CnEqHDg== - dependencies: - "@aztec/bb.js" "0.87.4" - "@aztec/constants" "0.87.4" - "@aztec/foundation" "0.87.4" - "@aztec/noir-noirc_abi" "0.87.4" - "@aztec/noir-protocol-circuits-types" "0.87.4" - "@aztec/noir-types" "0.87.4" - "@aztec/simulator" "0.87.4" - "@aztec/stdlib" "0.87.4" - "@aztec/telemetry-client" "0.87.4" - "@aztec/world-state" "0.87.4" +"@aztec/bb-prover@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/bb-prover/-/bb-prover-2.0.2.tgz#3ba2c3b561c02218936e5da779c559bd339fd246" + integrity sha512-0pcdOAx6KlbWyRJcmYoz2Z768H3z4Ay18MYNPzvLLGL8gmglGN9dEFS8ZsPxmUVxvi2K3Tw3vmMM/onYuHnLkA== + dependencies: + "@aztec/bb.js" "2.0.2" + "@aztec/constants" "2.0.2" + "@aztec/foundation" "2.0.2" + "@aztec/noir-noirc_abi" "2.0.2" + "@aztec/noir-protocol-circuits-types" "2.0.2" + "@aztec/noir-types" "2.0.2" + "@aztec/simulator" "2.0.2" + "@aztec/stdlib" "2.0.2" + "@aztec/telemetry-client" "2.0.2" + "@aztec/world-state" "2.0.2" commander "^12.1.0" pako "^2.1.0" - pidusage "^4.0.1" source-map-support "^0.5.21" tslib "^2.4.0" -"@aztec/bb.js@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/bb.js/-/bb.js-0.87.4.tgz" - integrity sha512-PFZmgIJFSExzQZkNBa1DLuUx96BlC+Am6bo940ooMnqX9BpHeFoZsC7x+qmJOSc1rlbc56OUkLzf75wFgO+JeA== +"@aztec/bb.js@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/bb.js/-/bb.js-2.0.2.tgz#ffc72a1926437243c45ff75c9c9be96feea094fa" + integrity sha512-pBQLGU3aHKBXRGdbxwIBRUxAoTOR8x5WcVTB+Z4Ea/pE0cxlOsEK2ZeiBODev26ChvY/asQ663ZyBvJJM4JbGw== dependencies: comlink "^4.4.1" commander "^12.1.0" @@ -69,66 +68,69 @@ pino "^9.5.0" tslib "^2.4.0" -"@aztec/blob-lib@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/blob-lib/-/blob-lib-0.87.4.tgz" - integrity sha512-yLuuLFYdWS8DaOHhT0NzkeGNgeLGjeyaGUqCv9vVtJrOX18CHcXcJiyyeNJrxBazVfAzga0VxdH+qvEMkaUKDw== +"@aztec/blob-lib@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/blob-lib/-/blob-lib-2.0.2.tgz#fdd011dfab4de6ff7428166ff858ddf29c08653e" + integrity sha512-v5n2QmsaRDZpIOIhI0zcNF5SxdkzmEiX6EvuW5s2Dal279jAGQ+LzCOhB+Z0/Albc1/7D8fRKaRV4a3uWMSzuA== dependencies: - "@aztec/constants" "0.87.4" - "@aztec/foundation" "0.87.4" + "@aztec/constants" "2.0.2" + "@aztec/foundation" "2.0.2" c-kzg "4.0.0-alpha.1" tslib "^2.4.0" -"@aztec/builder@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/builder/-/builder-0.87.4.tgz" - integrity sha512-jDU5cbO1uB4sTQhLfq6ZtqGaYbWmQMB/EFRB1XdSpzt1iOIdAheafa+7AXkDiSUP4NEMtbWaeMxkX0ur93mb7Q== +"@aztec/builder@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/builder/-/builder-2.0.2.tgz#68a00be8de136c8eaf1dfc4a3f6739c92f13a055" + integrity sha512-92NLorOJ4NyVXJ2d3JzQvVB0PTVPu3yAWOyqkqt0Ybt11rFqGD6wGa/qg3+Yb7mRixrU9FCeTDnnyfU4Yr+TzA== dependencies: - "@aztec/foundation" "0.87.4" - "@aztec/stdlib" "0.87.4" + "@aztec/foundation" "2.0.2" + "@aztec/stdlib" "2.0.2" commander "^12.1.0" -"@aztec/constants@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/constants/-/constants-0.87.4.tgz" - integrity sha512-1XTtFHEBLVqqykk787wjTOitejv+dM3DSKPnvC5t4OrwFng1h/tr/HFcUo3iMNitju54WwZLRTwYqfLLbH3sVA== +"@aztec/constants@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/constants/-/constants-2.0.2.tgz#e7c761d523327b06f5bc97992eeb10408378252f" + integrity sha512-fztICMy/1N9pBkpxAeaExEsX4buC1M03P4PbjSMkuw5UIk4z8fs01sF2kvHdSMngs3LA36AWcsCHXt2wfSJw4A== dependencies: tslib "^2.4.0" -"@aztec/entrypoints@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/entrypoints/-/entrypoints-0.87.4.tgz" - integrity sha512-M5hbOJfbPBa7N+DgCNuKG4plgkiSRwytbDNFjQvTbVqEIgywVPdTZXAlDzWkd/ru3cV9cjoWuhXzI3X7IHOB1g== +"@aztec/entrypoints@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/entrypoints/-/entrypoints-2.0.2.tgz#e196f4283ef5a2fee29766e106bc01247b57c1e8" + integrity sha512-nj9Y94OB/VYBNlOvGGvGFBrXCmBFHtJppwmMg4zEHx9IKzmLZCyX0xQx9CfKFuEoW2dkmgqj5dwngP6cyAmNTw== dependencies: - "@aztec/constants" "0.87.4" - "@aztec/foundation" "0.87.4" - "@aztec/protocol-contracts" "0.87.4" - "@aztec/stdlib" "0.87.4" + "@aztec/constants" "2.0.2" + "@aztec/foundation" "2.0.2" + "@aztec/protocol-contracts" "2.0.2" + "@aztec/stdlib" "2.0.2" tslib "^2.4.0" -"@aztec/ethereum@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/ethereum/-/ethereum-0.87.4.tgz" - integrity sha512-rPiOH9ziHMC06jzhknGglpMZkCcZE4GHTCJp+w/LqvnrfjysbB9ERb5/AWKWwscW5Vm7c9+L1qpS1iZlDkqB3g== +"@aztec/ethereum@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/ethereum/-/ethereum-2.0.2.tgz#05925c9c7d38584b6b6a81d9088a1f09890c50ce" + integrity sha512-3cIs9j+TzCacuJ0yZYaw6Ts8uAztaEEQfiOnwrmcyFdyYZrDYe52eBIWluzUO3MQBES0VBf0POSKFYIACuXhqA== dependencies: - "@aztec/blob-lib" "0.87.4" - "@aztec/foundation" "0.87.4" - "@aztec/l1-artifacts" "0.87.4" + "@aztec/blob-lib" "2.0.2" + "@aztec/constants" "2.0.2" + "@aztec/foundation" "2.0.2" + "@aztec/l1-artifacts" "2.0.2" "@viem/anvil" "^0.0.10" dotenv "^16.0.3" + lodash.chunk "^4.2.0" + lodash.pickby "^4.5.0" tslib "^2.4.0" viem "2.23.7" zod "^3.23.8" -"@aztec/foundation@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/foundation/-/foundation-0.87.4.tgz" - integrity sha512-+a1wPQ8wG+o94LrD4RoukyV0vUegk6DCuGqOrIQhXdQCv/Iheoq2a259JlmP2Co3atymGlO5Ggk3dT/bD/fmYQ== +"@aztec/foundation@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/foundation/-/foundation-2.0.2.tgz#bd606aeadfc03705466be1264d9b829bbd3c9ee5" + integrity sha512-A48UexNylbOdtx71T5st1UmcF0PGR+7DutHBd3cnkxT6zApiuWoCrhJmXtUp4ld7ZdskZMjgcJr4ACtwQPXdhg== dependencies: - "@aztec/bb.js" "0.87.4" + "@aztec/bb.js" "2.0.2" "@koa/cors" "^5.0.0" - "@noble/curves" "^1.2.0" - c-kzg "4.0.0-alpha.1" + "@noble/curves" "=1.7.0" + bn.js "^5.2.1" colorette "^2.0.20" detect-node "^2.1.0" hash.js "^1.1.7" @@ -146,139 +148,140 @@ undici "^5.28.5" zod "^3.23.8" -"@aztec/key-store@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/key-store/-/key-store-0.87.4.tgz" - integrity sha512-fFU7bp8yvTrZKIQZQ5sIZMu8UyA/M5D9vkQ19+Vg9TNN9UMN6Wp7QX5w2oEDKOUswoav5H7gaoTVvM6UT+7nwg== +"@aztec/key-store@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/key-store/-/key-store-2.0.2.tgz#b67ddc71ec504fd5b4169189037a0b1acbbf45b3" + integrity sha512-EFYRn3B9YVtWlwF6/WJ7rCkSOrKm1GcjW+W2Kk6Unof+4MYUuJQAuGlyrp3wWa3lmAFledNB4LltikjMFGp63Q== dependencies: - "@aztec/constants" "0.87.4" - "@aztec/foundation" "0.87.4" - "@aztec/kv-store" "0.87.4" - "@aztec/stdlib" "0.87.4" + "@aztec/constants" "2.0.2" + "@aztec/foundation" "2.0.2" + "@aztec/kv-store" "2.0.2" + "@aztec/stdlib" "2.0.2" tslib "^2.4.0" -"@aztec/kv-store@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/kv-store/-/kv-store-0.87.4.tgz" - integrity sha512-sO3HxD5WWhGSIf8YRGtAOAvqfjkX5oPBvCmXC1qFztKqB/ubZiYCUIfcZJ29EyNLfnF1zUESG0rB6blWZFTHjA== +"@aztec/kv-store@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/kv-store/-/kv-store-2.0.2.tgz#8d60bada461fc96a58b479b8366d1e69ff641384" + integrity sha512-6Yip1dNBKW/fG6tm9VhtMI84nXMJCVNSDm2AAW4QlN2n0seQU9XW2dTgdUAAPGjg7ujdmUzrHbYsGYl0ibXBpQ== dependencies: - "@aztec/ethereum" "0.87.4" - "@aztec/foundation" "0.87.4" - "@aztec/native" "0.87.4" - "@aztec/stdlib" "0.87.4" + "@aztec/ethereum" "2.0.2" + "@aztec/foundation" "2.0.2" + "@aztec/native" "2.0.2" + "@aztec/stdlib" "2.0.2" idb "^8.0.0" lmdb "^3.2.0" msgpackr "^1.11.2" ohash "^2.0.11" ordered-binary "^1.5.3" -"@aztec/l1-artifacts@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/l1-artifacts/-/l1-artifacts-0.87.4.tgz" - integrity sha512-2L4VL+gk4Wa6Qm4UuJ+zskiKTiyKMiHSvc088HmmF8MYsHvJr38Xu8DxgD4DCv/jjT74doS7ALpGBGQ+bg/icw== +"@aztec/l1-artifacts@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/l1-artifacts/-/l1-artifacts-2.0.2.tgz#8598d4d7352d4cc1675e52602a0612fa998da8d7" + integrity sha512-CclFsNxN5kuvQZkY2ZD5ZHjHo+JdzSBvK4c5NuBWrrzSuoUv6D6b03ZXnSbcAI2yO0urE+u4g9jm0/ln7kum3Q== dependencies: tslib "^2.4.0" -"@aztec/merkle-tree@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/merkle-tree/-/merkle-tree-0.87.4.tgz" - integrity sha512-Fl7R7OXIVPps1sSAeYXuibVsJyZWaeYuTUtO2tjraQrbjus8vFIbAjzvAE5/ClDnQs/I6AK3KuFH+jqnhgldHg== +"@aztec/merkle-tree@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/merkle-tree/-/merkle-tree-2.0.2.tgz#19f6a125db574c46870bec2846603fd3c3094ee4" + integrity sha512-USZbIPSbrA+qWHdxh5KiUrgfM6L0QUgGfez4HQhpPiVUZ1lXJ61xZSAM8YdsDFTT3XPWPYOLZD28XFlHr+35xA== dependencies: - "@aztec/foundation" "0.87.4" - "@aztec/kv-store" "0.87.4" - "@aztec/stdlib" "0.87.4" + "@aztec/foundation" "2.0.2" + "@aztec/kv-store" "2.0.2" + "@aztec/stdlib" "2.0.2" sha256 "^0.2.0" tslib "^2.4.0" -"@aztec/native@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/native/-/native-0.87.4.tgz" - integrity sha512-Y1vrRZj5SCpNU2lkoHNhN/PO+M7juSN4RoCfZ0NPpYRf5eibI2K6nkjCrC9wlj/brb3NdCFLNXX4WsE20lJBQA== +"@aztec/native@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/native/-/native-2.0.2.tgz#5cbbdbcddf2de6245e2bd2ca80f7de4090259fad" + integrity sha512-BSSGrbcRiIR25koPBccXF4L54O143VgpNJfMVIyC9swcd1dncPB/27QnhsFCW8le1fXuwOxLbMIj7IlHnjFP8w== dependencies: - "@aztec/foundation" "0.87.4" + "@aztec/foundation" "2.0.2" bindings "^1.5.0" msgpackr "^1.11.2" -"@aztec/noir-acvm_js@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/noir-acvm_js/-/noir-acvm_js-0.87.4.tgz" - integrity sha512-3I0JwyqHBNbkONgrz/RIkIr0ies+uf8Z2gcSRHynOzp3uNn9nvH7Qq1xuG22xmuSyLSOtQCsBu8BOJsd4dgJzg== +"@aztec/noir-acvm_js@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/noir-acvm_js/-/noir-acvm_js-2.0.2.tgz#12a61fd2368e9fd63a35e4e3f5c9fc7f9d745cf4" + integrity sha512-EF9iEYopRS9mKoirj7Pwtcvv2tEOSyQIbbnwNat9pIB+F1uYLnGFU5cAnQQJQ18qCtsU0t9jLptnXFmokfMRdw== -"@aztec/noir-contracts.js@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/noir-contracts.js/-/noir-contracts.js-0.87.4.tgz" - integrity sha512-qT579J8qydcakWTeEBsrCjRR/qrUa20ZLD5C8TOI60yUtXY9b/sSLxb9TeClzZ3jjO/v/RNi10S3YElJpvyXoA== +"@aztec/noir-contracts.js@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/noir-contracts.js/-/noir-contracts.js-2.0.2.tgz#773585a56e707d9ac0c6d1fefd40896cc0f63fc8" + integrity sha512-Lw4IgnCIgQNFbL0pmP52CtEikTXWyIiOJc6Ji5MLCjd405Js54OtEuy/I7hcaVhQmswD7/EeDG63hfP0omepsQ== dependencies: - "@aztec/aztec.js" "0.87.4" + "@aztec/aztec.js" "2.0.2" tslib "^2.4.0" -"@aztec/noir-noir_codegen@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/noir-noir_codegen/-/noir-noir_codegen-0.87.4.tgz" - integrity sha512-8IzW58DaDQtenZWQAipf81+0nRVz2RSK01DbWPd+PtmKQiZtyyvT0h5YpVgSvhgO2LrUJt3HJq31GbZZ4lhY2g== +"@aztec/noir-noir_codegen@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/noir-noir_codegen/-/noir-noir_codegen-2.0.2.tgz#0ef2ac024074092924e40f2fce3321d1657b45e2" + integrity sha512-2FP85t3VlLvsI+edoAbX+1zR+SEnCO9wzbHNv5sbexA2A3FVDZGRbGhyHRIQfciubfQvqj8CNVZnsCeSmVa81A== dependencies: - "@aztec/noir-types" "0.87.4" - glob "^11.0.1" + "@aztec/noir-types" "2.0.2" + glob "^11.0.2" ts-command-line-args "^2.5.1" -"@aztec/noir-noirc_abi@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/noir-noirc_abi/-/noir-noirc_abi-0.87.4.tgz" - integrity sha512-AflhWqi7aGpPegDnQLpA5Oiqm2+6570y5YySFj7ugz00Bn3zPWUA9o9iMoV3q7EJ88Qwr3KvhE0AU2vgTK1n5w== - dependencies: - "@aztec/noir-types" "0.87.4" - -"@aztec/noir-protocol-circuits-types@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/noir-protocol-circuits-types/-/noir-protocol-circuits-types-0.87.4.tgz" - integrity sha512-t/LxvDs5nxwHYZOcl23qDRFExe/IAl/c1zdC7O2piGiSXe7KA7Q2DL+O8yJKSC5QlPSuK37Qivj0bQf0ktyiuA== - dependencies: - "@aztec/blob-lib" "0.87.4" - "@aztec/constants" "0.87.4" - "@aztec/foundation" "0.87.4" - "@aztec/noir-acvm_js" "0.87.4" - "@aztec/noir-noir_codegen" "0.87.4" - "@aztec/noir-noirc_abi" "0.87.4" - "@aztec/noir-types" "0.87.4" - "@aztec/stdlib" "0.87.4" +"@aztec/noir-noirc_abi@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/noir-noirc_abi/-/noir-noirc_abi-2.0.2.tgz#86c7fdf6a920bca87558bb07ee81bcbc17d5a392" + integrity sha512-5WCQyaPGGsGslB35OylhbKUc0SUqpy9WxoVZhyDzpiB/zJ2qbTKsLNP50SQeD1vSth1qZgbIeRP1fjss/knoMQ== + dependencies: + "@aztec/noir-types" "2.0.2" + +"@aztec/noir-protocol-circuits-types@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/noir-protocol-circuits-types/-/noir-protocol-circuits-types-2.0.2.tgz#444b40125489a4ff83d7452fd8f4df24b2dbde8f" + integrity sha512-qtN5B0LckRiWlPLcJwiNChv65CsVZ2LRNtSfIsBYk7GkDdtYPRau8eDydPN5ObzEXc++2Tq4566cLjMbZPnecQ== + dependencies: + "@aztec/blob-lib" "2.0.2" + "@aztec/constants" "2.0.2" + "@aztec/foundation" "2.0.2" + "@aztec/noir-acvm_js" "2.0.2" + "@aztec/noir-noir_codegen" "2.0.2" + "@aztec/noir-noirc_abi" "2.0.2" + "@aztec/noir-types" "2.0.2" + "@aztec/stdlib" "2.0.2" change-case "^5.4.4" tslib "^2.4.0" -"@aztec/noir-types@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/noir-types/-/noir-types-0.87.4.tgz" - integrity sha512-w8A71YYxZUZAB06mgmPaj09WSKYt3QSodgRqoGDyFsknnATNWbEHJxcTlwD6oyfdGyTfPfK79HoO4aQQBus23A== +"@aztec/noir-types@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/noir-types/-/noir-types-2.0.2.tgz#ab997738183dd2aea2a6b4ecc915db85516d858c" + integrity sha512-eZoOaYVAcC34/xb42TglCESdBzBl2+Pc+dh9vQqrhsBsgFeD5CkYiYZ9JhwtWU0pxjdqz7b4fP1Z8QdeWxh/zA== -"@aztec/protocol-contracts@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/protocol-contracts/-/protocol-contracts-0.87.4.tgz" - integrity sha512-WLqCQFKwxOAbGnFUUc7F2Ayw8Y+m4Xnt0TLX8UDwuKnyxQT+zGXtLQiZQxAN9MRPBHVLC0TMfHtpe6fAIiZo2Q== +"@aztec/protocol-contracts@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/protocol-contracts/-/protocol-contracts-2.0.2.tgz#c5ebdbd68b9a54e488710c00f82659960aaffdd6" + integrity sha512-FTwvPLug3Eae9Y+olYB+ssvyzeXe7n247JS1dADjoKEwc3PC/tGlfn9vSzQtPswTrorFXVjE9DdIjMKZokV1Kg== dependencies: - "@aztec/constants" "0.87.4" - "@aztec/foundation" "0.87.4" - "@aztec/stdlib" "0.87.4" + "@aztec/constants" "2.0.2" + "@aztec/foundation" "2.0.2" + "@aztec/stdlib" "2.0.2" lodash.chunk "^4.2.0" lodash.omit "^4.5.0" tslib "^2.4.0" -"@aztec/pxe@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/pxe/-/pxe-0.87.4.tgz" - integrity sha512-zQoB4Bcpd1N2Ae+Jkt+5X0+OpErpRAgZA+6685OjzrCs9Dn3wnQdMJPuAIaCDjT4LRS0izl+qRfFLWnhzKnGRg== - dependencies: - "@aztec/bb-prover" "0.87.4" - "@aztec/bb.js" "0.87.4" - "@aztec/builder" "0.87.4" - "@aztec/constants" "0.87.4" - "@aztec/ethereum" "0.87.4" - "@aztec/foundation" "0.87.4" - "@aztec/key-store" "0.87.4" - "@aztec/kv-store" "0.87.4" - "@aztec/noir-protocol-circuits-types" "0.87.4" - "@aztec/noir-types" "0.87.4" - "@aztec/protocol-contracts" "0.87.4" - "@aztec/simulator" "0.87.4" - "@aztec/stdlib" "0.87.4" +"@aztec/pxe@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/pxe/-/pxe-2.0.2.tgz#7011d36a8e04b9495e51d9816b8f6ff45ecd03f3" + integrity sha512-kcGZHJPAjJqqjRnoATuqMTZLvAW6Ik9L6TvvbhdSIm0emeeSaV2ZYJ6WDMplY1us8BpmPVheFdQaI90WJAF/QQ== + dependencies: + "@aztec/bb-prover" "2.0.2" + "@aztec/bb.js" "2.0.2" + "@aztec/builder" "2.0.2" + "@aztec/constants" "2.0.2" + "@aztec/ethereum" "2.0.2" + "@aztec/foundation" "2.0.2" + "@aztec/key-store" "2.0.2" + "@aztec/kv-store" "2.0.2" + "@aztec/noir-protocol-circuits-types" "2.0.2" + "@aztec/noir-types" "2.0.2" + "@aztec/protocol-contracts" "2.0.2" + "@aztec/simulator" "2.0.2" + "@aztec/stdlib" "2.0.2" + json-stringify-deterministic "1.0.12" koa "^2.16.1" koa-router "^12.0.0" lodash.omit "^4.5.0" @@ -286,36 +289,37 @@ tslib "^2.4.0" viem "2.23.7" -"@aztec/simulator@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/simulator/-/simulator-0.87.4.tgz" - integrity sha512-ufTRjFFX/3UvPQVhPxsfmMFXvUHHf2lyJgq9Grck/Es+0zzQzQl03bUi+w+6+pOgyCqaViiY2UG8dOjW5vEFlg== - dependencies: - "@aztec/constants" "0.87.4" - "@aztec/foundation" "0.87.4" - "@aztec/noir-acvm_js" "0.87.4" - "@aztec/noir-noirc_abi" "0.87.4" - "@aztec/noir-protocol-circuits-types" "0.87.4" - "@aztec/noir-types" "0.87.4" - "@aztec/protocol-contracts" "0.87.4" - "@aztec/stdlib" "0.87.4" - "@aztec/telemetry-client" "0.87.4" - "@aztec/world-state" "0.87.4" +"@aztec/simulator@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/simulator/-/simulator-2.0.2.tgz#2b7a3da2f46189599ac591da843294e3ef5c426b" + integrity sha512-LE01H5ryiEu84C3xYBieji5TXSam9AzU10w9shx+wIKR7+/aJ4426CaXrDssT/zTBiHrCr+BOAIX8FQiT3KCdg== + dependencies: + "@aztec/constants" "2.0.2" + "@aztec/foundation" "2.0.2" + "@aztec/noir-acvm_js" "2.0.2" + "@aztec/noir-noirc_abi" "2.0.2" + "@aztec/noir-protocol-circuits-types" "2.0.2" + "@aztec/noir-types" "2.0.2" + "@aztec/protocol-contracts" "2.0.2" + "@aztec/stdlib" "2.0.2" + "@aztec/telemetry-client" "2.0.2" + "@aztec/world-state" "2.0.2" lodash.clonedeep "^4.5.0" lodash.merge "^4.6.2" tslib "^2.4.0" -"@aztec/stdlib@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/stdlib/-/stdlib-0.87.4.tgz" - integrity sha512-QYBQ61Sx1QloTVF5klnMBdSBaaCwsHqAq4Zhxa9zfPSYx2ML/196GuH2coi+Zwn3+KPbXfAnhJzAlSR01yA4Pg== - dependencies: - "@aztec/bb.js" "0.87.4" - "@aztec/blob-lib" "0.87.4" - "@aztec/constants" "0.87.4" - "@aztec/ethereum" "0.87.4" - "@aztec/foundation" "0.87.4" - "@aztec/noir-noirc_abi" "0.87.4" +"@aztec/stdlib@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/stdlib/-/stdlib-2.0.2.tgz#b3114a0b139e7d0057cb81532e95e9c03695ca69" + integrity sha512-nsOZJwz2v+rzHUrGE2e6a+qRerK5EYaqX8IqJOngi6e5Uq1oTFhsthgYV45H2jM5aNYsf2WgU69zlFKgODXCXQ== + dependencies: + "@aztec/bb.js" "2.0.2" + "@aztec/blob-lib" "2.0.2" + "@aztec/constants" "2.0.2" + "@aztec/ethereum" "2.0.2" + "@aztec/foundation" "2.0.2" + "@aztec/l1-artifacts" "2.0.2" + "@aztec/noir-noirc_abi" "2.0.2" "@google-cloud/storage" "^7.15.0" axios "^1.9.0" json-stringify-deterministic "1.0.12" @@ -329,13 +333,13 @@ viem "2.23.7" zod "^3.23.8" -"@aztec/telemetry-client@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/telemetry-client/-/telemetry-client-0.87.4.tgz" - integrity sha512-bSaZJbp7vjsHj4LjmMWinXXvlqrVrQloTrcET9QZnf10IqroC5XEUbKSuoNmxzRqKHhnuv+AbJSyIL1HccRuLQ== +"@aztec/telemetry-client@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/telemetry-client/-/telemetry-client-2.0.2.tgz#38a5858d7608ade219004489316fdfe4e8254154" + integrity sha512-qvMjCsger+Pd61iyxqeCw3nhRjDTTftPHwWY7up7C433apD3f7OGRx33N/TDOIlvmD976SNi2lIemeRvcrtEiQ== dependencies: - "@aztec/foundation" "0.87.4" - "@aztec/stdlib" "0.87.4" + "@aztec/foundation" "2.0.2" + "@aztec/stdlib" "2.0.2" "@opentelemetry/api" "^1.9.0" "@opentelemetry/api-logs" "^0.55.0" "@opentelemetry/core" "^1.28.0" @@ -353,19 +357,19 @@ prom-client "^15.1.3" viem "2.23.7" -"@aztec/world-state@0.87.4": - version "0.87.4" - resolved "https://registry.npmjs.org/@aztec/world-state/-/world-state-0.87.4.tgz" - integrity sha512-/9gxoxhKSCRle2jQNAyyWucX1Jmlz/DAnhZ5oZl3RiA9w+IcVTuZeMy2vR8WiEuSucWo9moV2I8kZBqWhykMLQ== - dependencies: - "@aztec/constants" "0.87.4" - "@aztec/foundation" "0.87.4" - "@aztec/kv-store" "0.87.4" - "@aztec/merkle-tree" "0.87.4" - "@aztec/native" "0.87.4" - "@aztec/protocol-contracts" "0.87.4" - "@aztec/stdlib" "0.87.4" - "@aztec/telemetry-client" "0.87.4" +"@aztec/world-state@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@aztec/world-state/-/world-state-2.0.2.tgz#c9fe6e92e4ae68eb840d3be7753c5d368dbc7994" + integrity sha512-cIrnRgxCPZ33mlluOkBROrqcGvzXvaP64UEYNCTYyA3KznPZXNRUjLxNXvNNoPpu5p5eeitskaI0I59UpRm2RA== + dependencies: + "@aztec/constants" "2.0.2" + "@aztec/foundation" "2.0.2" + "@aztec/kv-store" "2.0.2" + "@aztec/merkle-tree" "2.0.2" + "@aztec/native" "2.0.2" + "@aztec/protocol-contracts" "2.0.2" + "@aztec/stdlib" "2.0.2" + "@aztec/telemetry-client" "2.0.2" tslib "^2.4.0" zod "^3.23.8" @@ -423,6 +427,18 @@ resolved "https://registry.npmjs.org/@hapi/bourne/-/bourne-3.0.0.tgz" integrity sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w== +"@isaacs/balanced-match@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz#3081dadbc3460661b751e7591d7faea5df39dd29" + integrity sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ== + +"@isaacs/brace-expansion@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz#4b3dabab7d8e75a429414a96bd67bf4c1d13e0f3" + integrity sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA== + dependencies: + "@isaacs/balanced-match" "^4.0.1" + "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz" @@ -579,7 +595,14 @@ dependencies: "@noble/hashes" "1.7.1" -"@noble/curves@^1.2.0", "@noble/curves@^1.6.0", "@noble/curves@~1.9.0": +"@noble/curves@=1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.7.0.tgz#0512360622439256df892f21d25b388f52505e45" + integrity sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw== + dependencies: + "@noble/hashes" "1.6.0" + +"@noble/curves@^1.6.0", "@noble/curves@~1.9.0": version "1.9.1" resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz" integrity sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA== @@ -593,6 +616,11 @@ dependencies: "@noble/hashes" "1.7.2" +"@noble/hashes@1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.0.tgz#d4bfb516ad6e7b5111c216a5cc7075f4cf19e6c5" + integrity sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ== + "@noble/hashes@1.7.1": version "1.7.1" resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz" @@ -1462,11 +1490,6 @@ axios@^1.8.2, axios@^1.9.0: form-data "^4.0.0" proxy-from-env "^1.1.0" -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" @@ -1540,13 +1563,6 @@ boolbase@^1.0.0: resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - braces@^3.0.3, braces@~3.0.2: version "3.0.3" resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" @@ -2601,9 +2617,9 @@ for-each@^0.3.5: dependencies: is-callable "^1.2.7" -foreground-child@^3.1.0: +foreground-child@^3.3.1: version "3.3.1" - resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== dependencies: cross-spawn "^7.0.6" @@ -2721,14 +2737,14 @@ glob-to-regexp@^0.4.1: resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@^11.0.1: - version "11.0.2" - resolved "https://registry.npmjs.org/glob/-/glob-11.0.2.tgz" - integrity sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ== +glob@^11.0.2: + version "11.0.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-11.0.3.tgz#9d8087e6d72ddb3c4707b1d2778f80ea3eaefcd6" + integrity sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA== dependencies: - foreground-child "^3.1.0" - jackspeak "^4.0.1" - minimatch "^10.0.0" + foreground-child "^3.3.1" + jackspeak "^4.1.1" + minimatch "^10.0.3" minipass "^7.1.2" package-json-from-dist "^1.0.0" path-scurry "^2.0.0" @@ -3218,9 +3234,9 @@ isows@1.0.6: resolved "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz" integrity sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw== -jackspeak@^4.0.1: +jackspeak@^4.1.1: version "4.1.1" - resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.1.1.tgz#96876030f450502047fc7e8c7fcf8ce8124e43ae" integrity sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ== dependencies: "@isaacs/cliui" "^8.0.2" @@ -3462,6 +3478,11 @@ lodash.omit@^4.5.0: resolved "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz" integrity sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg== +lodash.pickby@^4.5.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.pickby/-/lodash.pickby-4.6.0.tgz#7dea21d8c18d7703a27c704c15d3b84a67e33aff" + integrity sha512-AZV+GsS/6ckvPOVQPXSiFFacKvKB4kOQu6ynt9wz0F3LO4R9Ij4K1ddYsIytDpSgLz88JHd9P+oaLeej5/Sl7Q== + lodash.times@^4.3.2: version "4.3.2" resolved "https://registry.npmjs.org/lodash.times/-/lodash.times-4.3.2.tgz" @@ -3591,12 +3612,12 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -minimatch@^10.0.0: - version "10.0.1" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz" - integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ== +minimatch@^10.0.3: + version "10.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.3.tgz#cf7a0314a16c4d9ab73a7730a0e8e3c3502d47aa" + integrity sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw== dependencies: - brace-expansion "^2.0.1" + "@isaacs/brace-expansion" "^5.0.0" minimist@^1.2.6: version "1.2.8" @@ -3979,13 +4000,6 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pidusage@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/pidusage/-/pidusage-4.0.1.tgz" - integrity sha512-yCH2dtLHfEBnzlHUJymR/Z1nN2ePG3m392Mv8TFlTP1B0xkpMQNHAnfkY0n2tAi6ceKO6YWhxYfZ96V4vVkh/g== - dependencies: - safe-buffer "^5.2.1" - pino-abstract-transport@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz" From 0f8fcfb0bbbab83a3f61cb9f980cc77f190413da Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 18 Sep 2025 21:24:52 -0400 Subject: [PATCH 2/8] increase timeout --- tests/e2e.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e.spec.ts b/tests/e2e.spec.ts index 39cb3e3..b4c54d6 100644 --- a/tests/e2e.spec.ts +++ b/tests/e2e.spec.ts @@ -1,6 +1,6 @@ import { test, expect } from '@playwright/test'; -const proofTimeout = 300_000; +const proofTimeout = 600_000; test.beforeAll(async ({ }, { config }) => { // Make sure the node is running From 034e55ec38339fd0d475f97f13094a9aa0a505cb Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 18 Sep 2025 21:44:56 -0400 Subject: [PATCH 3/8] moar --- tests/e2e.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e.spec.ts b/tests/e2e.spec.ts index b4c54d6..85a2b7e 100644 --- a/tests/e2e.spec.ts +++ b/tests/e2e.spec.ts @@ -1,6 +1,6 @@ import { test, expect } from '@playwright/test'; -const proofTimeout = 600_000; +const proofTimeout = 1_200_000; test.beforeAll(async ({ }, { config }) => { // Make sure the node is running From 72cbddbe7c65cafa48ae5338fe7f54e25e5d7a0a Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Thu, 18 Sep 2025 22:38:03 -0400 Subject: [PATCH 4/8] increase timeout --- playwright.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright.config.ts b/playwright.config.ts index 59f5010..dd432c6 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -17,7 +17,7 @@ export default defineConfig({ expect: { timeout: 20_000, }, - timeout: 400_000, + timeout: 800_000, projects: [ { name: 'webkit', From 59a2378aa8dbe8f4923a81c2f405d94942d47dfa Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Fri, 19 Sep 2025 08:34:04 -0400 Subject: [PATCH 5/8] try longer --- playwright.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright.config.ts b/playwright.config.ts index dd432c6..bf666f3 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -17,7 +17,7 @@ export default defineConfig({ expect: { timeout: 20_000, }, - timeout: 800_000, + timeout: 1_600_000, projects: [ { name: 'webkit', From b5538132e6208629fcf9cb7236847692e5dead76 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Fri, 19 Sep 2025 11:09:54 -0400 Subject: [PATCH 6/8] rm artifacts --- app/artifacts/PrivateVoting.ts | 160 - .../private_voting-PrivateVoting.json | 3410 ----------------- 2 files changed, 3570 deletions(-) delete mode 100644 app/artifacts/PrivateVoting.ts delete mode 100644 app/artifacts/private_voting-PrivateVoting.json diff --git a/app/artifacts/PrivateVoting.ts b/app/artifacts/PrivateVoting.ts deleted file mode 100644 index a184917..0000000 --- a/app/artifacts/PrivateVoting.ts +++ /dev/null @@ -1,160 +0,0 @@ - -/* Autogenerated file, do not edit! */ - -/* eslint-disable */ -import { - type AbiType, - AztecAddress, - type AztecAddressLike, - CompleteAddress, - Contract, - type ContractArtifact, - ContractBase, - ContractFunctionInteraction, - type ContractInstanceWithAddress, - type ContractMethod, - type ContractStorageLayout, - decodeFromAbi, - DeployMethod, - EthAddress, - type EthAddressLike, - EventSelector, - type FieldLike, - Fr, - type FunctionSelectorLike, - loadContractArtifact, - loadContractArtifactForPublic, - type NoirCompiledContract, - Point, - type PublicKey, - PublicKeys, - type Wallet, - type U128Like, - type WrappedFieldLike, -} from '@aztec/aztec.js'; -import PrivateVotingContractArtifactJson from './private_voting-PrivateVoting.json' with { type: 'json' }; -export const PrivateVotingContractArtifact = loadContractArtifact(PrivateVotingContractArtifactJson as NoirCompiledContract); - - - -/** - * Type-safe interface for contract PrivateVoting; - */ -export class PrivateVotingContract extends ContractBase { - - private constructor( - instance: ContractInstanceWithAddress, - wallet: Wallet, - ) { - super(instance, PrivateVotingContractArtifact, wallet); - } - - - - /** - * Creates a contract instance. - * @param address - The deployed contract's address. - * @param wallet - The wallet to use when interacting with the contract. - * @returns A promise that resolves to a new Contract instance. - */ - public static async at( - address: AztecAddress, - wallet: Wallet, - ) { - return Contract.at(address, PrivateVotingContract.artifact, wallet) as Promise; - } - - - /** - * Creates a tx to deploy a new instance of this contract. - */ - public static deploy(wallet: Wallet, admin: AztecAddressLike) { - return new DeployMethod(PublicKeys.default(), wallet, PrivateVotingContractArtifact, PrivateVotingContract.at, Array.from(arguments).slice(1)); - } - - /** - * Creates a tx to deploy a new instance of this contract using the specified public keys hash to derive the address. - */ - public static deployWithPublicKeys(publicKeys: PublicKeys, wallet: Wallet, admin: AztecAddressLike) { - return new DeployMethod(publicKeys, wallet, PrivateVotingContractArtifact, PrivateVotingContract.at, Array.from(arguments).slice(2)); - } - - /** - * Creates a tx to deploy a new instance of this contract using the specified constructor method. - */ - public static deployWithOpts( - opts: { publicKeys?: PublicKeys; method?: M; wallet: Wallet }, - ...args: Parameters - ) { - return new DeployMethod( - opts.publicKeys ?? PublicKeys.default(), - opts.wallet, - PrivateVotingContractArtifact, - PrivateVotingContract.at, - Array.from(arguments).slice(1), - opts.method ?? 'constructor', - ); - } - - - - /** - * Returns this contract's artifact. - */ - public static get artifact(): ContractArtifact { - return PrivateVotingContractArtifact; - } - - /** - * Returns this contract's artifact with public bytecode. - */ - public static get artifactForPublic(): ContractArtifact { - return loadContractArtifactForPublic(PrivateVotingContractArtifactJson as NoirCompiledContract); - } - - - public static get storage(): ContractStorageLayout<'admin' | 'tally' | 'vote_ended' | 'active_at_block'> { - return { - admin: { - slot: new Fr(1n), - }, -tally: { - slot: new Fr(2n), - }, -vote_ended: { - slot: new Fr(3n), - }, -active_at_block: { - slot: new Fr(4n), - } - } as ContractStorageLayout<'admin' | 'tally' | 'vote_ended' | 'active_at_block'>; - } - - - /** Type-safe wrappers for the public methods exposed by the contract. */ - public declare methods: { - - /** cast_vote(candidate: field) */ - cast_vote: ((candidate: FieldLike) => ContractFunctionInteraction) & Pick; - - /** constructor(admin: struct) */ - constructor: ((admin: AztecAddressLike) => ContractFunctionInteraction) & Pick; - - /** end_vote() */ - end_vote: (() => ContractFunctionInteraction) & Pick; - - /** get_vote(candidate: field) */ - get_vote: ((candidate: FieldLike) => ContractFunctionInteraction) & Pick; - - /** process_message(message_ciphertext: struct, message_context: struct) */ - process_message: ((message_ciphertext: FieldLike[], message_context: { tx_hash: FieldLike, unique_note_hashes_in_tx: FieldLike[], first_nullifier_in_tx: FieldLike, recipient: AztecAddressLike }) => ContractFunctionInteraction) & Pick; - - /** public_dispatch(selector: field) */ - public_dispatch: ((selector: FieldLike) => ContractFunctionInteraction) & Pick; - - /** sync_private_state() */ - sync_private_state: (() => ContractFunctionInteraction) & Pick; - }; - - -} diff --git a/app/artifacts/private_voting-PrivateVoting.json b/app/artifacts/private_voting-PrivateVoting.json deleted file mode 100644 index a4aafd1..0000000 --- a/app/artifacts/private_voting-PrivateVoting.json +++ /dev/null @@ -1,3410 +0,0 @@ -{ - "transpiled": true, - "noir_version": "1.0.0-beta.11+5b65f9637e85a4177692c3190cb35ea678fb15e9-aztec", - "name": "PrivateVoting", - "functions": [ - { - "name": "add_to_tally_public", - "is_unconstrained": true, - "custom_attributes": [ - "public", - "internal" - ], - "abi": { - "parameters": [ - { - "name": "candidate", - "type": { - "kind": "field" - }, - "visibility": "private" - } - ], - "return_type": null, - "error_types": { - "206160798890201757": { - "error_kind": "string", - "string": "Storage slot 0 not allowed. Storage slots must start from 1." - }, - "2024020833944022298": { - "error_kind": "string", - "string": "Function add_to_tally_public can only be called internally" - }, - "3557153117338734214": { - "error_kind": "string", - "string": "Vote has ended" - }, - "13699457482007836410": { - "error_kind": "string", - "string": "Not initialized" - }, - "17843811134343075018": { - "error_kind": "string", - "string": "Stack too deep" - } - } - }, - "bytecode": "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", - "debug_symbols": "tZvdbhRJD4bvZY5z0PVjVxW3skIoQFhFigLKwid9Qtz72i6/nglSl3pnwgk84+l2l3+qbPfAz9Pnh48//v7w+Pzl6z+nd3/9PH18eXx6evz7w9PXT/ffH78+i/TnadM/ej69q3en3k7v2t1pyKe03Z3SJl+mpEAOqQC6gNySskqagkq6QCkONQH49C4XAUoAeVImAc4ASJpKWKE5dEjGBpD1FNGTdYUTKmA4JEgSJBkSXapByYDmoGuewA6kjxBLc0sAcuj4qkMyIBkhGRPKVgDdIWVAc8gJwA5FFWaFChgOtQCaA2UAOzBuZ3JokDQobN2hu8Ka9BpWqIDhkCHJkBRISneoGdAcNO4T2MEW1hQqoDtoAhiYM8fdiZLcXjcFAgwHTb8JzUFjOkGeVcUcqhuAHAgSgoQhYUgaJE31SCaQ7RKD4TDqBNY8nEAAvUYiyLplJjQHjbKBBreSQgV0B/VhZYXmYEtVsKUqdPczd/c8W9YJtG0DuMNbSgCa7m0WUwX14YTmoI5Szzfm6cxm3jCogO7QM8BD0EaarmvDndm3DQBJgiRBkiHJkJQ0ndl1exrUCvAQdHKHd94Adbq3a0YZaEZNYAfdsLUrqB6xtFsoBcaWAc1BF0Zy6A09HCgrEGA4UAE0Bz3ZJshDSR461IcTyKFD0iEZkAyXyCG8BakmO5jVe041qIOyPpqMGkh9Sd2IQTVkZocRiT7WI3pTh7I9V/fEJDWhWUXQPHAaoB6yHrIRstGdkrrYqYE0P50YpI5v2agGDVAJWQlZDVntID0VnRqIUxCDWjxN4+OkmjerdyWog7RQOrFT3lIQBUGLFSUnaMk5BzWQ2WHl1eww0hRzChmHjEOm2e7EoJ6CCKSp5qRPI6PuVCxGkxhkUdBaX3QDNCv2mjmTbH2TGsj8PIlB6ue+GdWgAeoh6yEbIRuQ1Q0yq1Y9GTFIjzSnDtJ8cRograE9GzWQFisnAumZ0otRB6mfnfS56smqfnYaIFt9te4HUSCtBZNyDRqgghhZ6XJCjKgiRkQ5CDGihhjRQIxoIEa8lSDEiFMKQow4I0acaxB8b+XKKWQ1ZDVkFDJGjJgRI24lCDHiXoMQIx6IEQ/EqG0pCDFqure6NY66t7r6wErbJD3/nBhkKx1KmpNjM6pBHaQVzolBWuOcZAXDVqB+NuqanU4hSyFLIcshyyHT6PduNECWp5MaSPN0FCMGqZ+H9cx6Zk9qITOLjPQ0k4qhqMeAOcFKoFN3smroxHqLrnBk+GjYqo1KyLSHkSqjWMsZz1Ky+aIaNtylJ9mkiIXVyUk9BSECIyJgtdLJ1yODQQlqoMQg7bx0lwjVoA7S5svJjCZFPQJ0cwgNUAtZM/NYcfp24lk6hypTOnzr5YTtmJMeYk4EyimIQSVkJa4rWE+qoa/GMyjubTA64ZAQgtE2ZTmF0TZW2c2zhhmlkKUwL+dyxrO0hNE2Yc27YpE2WjnBmIyKIYSF2+TlFNe1WE8PfT2eMXBvSd68CdWgDrJOaZIZbbfoUaadWy5o73KhkJGZNxS5nPEs1bqQdH4WbLirF5B1eJO8i8x1S0EMSiFLcV3CeqzAOeEZtcS95JOTUA3qIO1MndRoneelzfC+PlvlmjRCpgeC9F42DpcznqXJjLZ5OfkYkGM4k9ZlCyJQTUEMopBRXEdYD3Ho43hGi3sxLmYby5xgNG85KIy24mY3W3GbVEJWwjyu5YxnKYXRTFgQxyIZM5MQjOGegrBwHiEbcd3AetpWgvCMluzeX7/uTniX8+H7y8ODvsq5eLkjr3y+3b88PH8/vXv+8fR0d/rf/dMPu+ifb/fP9vf3+xf5VnQ+PH+Wv0Xhl8enB6Vfd+e7t/1bte3Lfrs2eS1UyAnySklaKJGJBTrk8L1QkV+pyAsVbWjtnzqkEFMo4fFKR9nXUXLRA8B0COe6p2NpyhhYhowFu6bQG5jCf9oU6hGVvh+Vvq9CeiioaDK77y1iLAwpVduUaYiczLcaIkPWriGrNJfiEjrEt7yf5qskHRebZUhzv2vMOku100dox66SpTkl5bM5Je+b8xaJmt4iU49Hp9Rdc1ZKWqIwpvRQQa/PwrRM1pYjV8fFUdjb63NssQzJLR1OphJ539L3/JHTSsl23jXbtp9oeZGtcrJTKCEZzHeVrM1pF+bksquk7ivhBBV8kaqFxlWxrWMvtisNPUeGXZ5kv2nIbWFFJWQH03ax5dpv2bE4UKWbdxX5QoOci681LHK0Vf1VYx7JtZ8ToyR+XSdXQQ1D5JVLaJCO/bWGRYLKjzJILR0t9nUs8pMyKq20l9dpGJFXia6zI3csQs6xvK9jdYxSRgMmL3falTo42g75eeI6HWULHSX3fR2rgl9zJBdfpWFU7NRB163hVTfJ+3Gti7jWysjPKsPPea+O/+BO/aXB3UlXhrVEhgr2q3S8hSmpRIbKm83rdkpLcXS1xX6t7c/q0HeRsEVePF6no7Vy7nv2dz1tt+6UlYZjO2Wl4ehOoXJzei3dOc4Hz8j77lwWV4o2QybwultcadGKyhtprEOyK100kf21jlWK9hqFrV+E5fcW8Girwdteq0Fv0IjyWzSi/BaNKL9FI3rYqXxVB9hi2OkXm/43DUy3d4DMt3aA3G7vALnf2gHyuL0DbNutHeBSw6EOcGnHwQ6wlds7wLWOYx3gUsfBDrDxrXVtpeFYXVtpOFrX2ri5rq3deawDXOs41gG28mdNOdgBLnfKwe6t05/VcbQDXOo42AH2m2elfvOs1N9gVhq3z0pLdx7sAJfF9WAHOOrtHeCgP9wBnluNse2+rhqLIi9nBbwhL9DL7irGqsjLD9jRRsqP1fvv71etaKoEn5ZEaf+d97Z841Rj0xaii9D8pmW5XTa4ZOQrNxzDH6PRrVt2oWFZHg9ZsdRwyIqDJXqhYTm8HrJiqeGQFQcH6IWGcnNGlZszqlyXUe/l4/2nx5dX/+L/l6p6ebz/+PTgH7/8eP508e33/3/DN/gfA99evn56+Pzj5UE1nf/bgPzxF7V0RyO/vzsl+yjjCXHSj0k/yhBBbXv/SxfzLw==" - }, - { - "name": "cast_vote", - "is_unconstrained": false, - "custom_attributes": [ - "private" - ], - "abi": { - "parameters": [ - { - "name": "inputs", - "type": { - "kind": "struct", - "path": "aztec::context::inputs::private_context_inputs::PrivateContextInputs", - "fields": [ - { - "name": "call_context", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::call_context::CallContext", - "fields": [ - { - "name": "msg_sender", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "function_selector", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::function_selector::FunctionSelector", - "fields": [ - { - "name": "inner", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - } - ] - } - }, - { - "name": "historical_header", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::block_header::BlockHeader", - "fields": [ - { - "name": "last_archive", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "content_commitment", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::content_commitment::ContentCommitment", - "fields": [ - { - "name": "blobs_hash", - "type": { - "kind": "field" - } - }, - { - "name": "in_hash", - "type": { - "kind": "field" - } - }, - { - "name": "out_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "state", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::state_reference::StateReference", - "fields": [ - { - "name": "l1_to_l2_message_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "partial", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::partial_state_reference::PartialStateReference", - "fields": [ - { - "name": "note_hash_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "nullifier_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "public_data_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - ] - } - } - ] - } - }, - { - "name": "global_variables", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::global_variables::GlobalVariables", - "fields": [ - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - }, - { - "name": "block_number", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "slot_number", - "type": { - "kind": "field" - } - }, - { - "name": "timestamp", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 64 - } - }, - { - "name": "coinbase", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::eth_address::EthAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "fee_recipient", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "gas_fees", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_fees::GasFees", - "fields": [ - { - "name": "fee_per_da_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 128 - } - }, - { - "name": "fee_per_l2_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 128 - } - } - ] - } - } - ] - } - }, - { - "name": "total_fees", - "type": { - "kind": "field" - } - }, - { - "name": "total_mana_used", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "tx_context", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::transaction::tx_context::TxContext", - "fields": [ - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - }, - { - "name": "gas_settings", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_settings::GasSettings", - "fields": [ - { - "name": "gas_limits", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas::Gas", - "fields": [ - { - "name": "da_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "l2_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "teardown_gas_limits", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas::Gas", - "fields": [ - { - "name": "da_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "l2_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "max_fees_per_gas", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_fees::GasFees", - "fields": [ - { - "name": "fee_per_da_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 128 - } - }, - { - "name": "fee_per_l2_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 128 - } - } - ] - } - }, - { - "name": "max_priority_fees_per_gas", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_fees::GasFees", - "fields": [ - { - "name": "fee_per_da_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 128 - } - }, - { - "name": "fee_per_l2_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 128 - } - } - ] - } - } - ] - } - } - ] - } - }, - { - "name": "start_side_effect_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - }, - "visibility": "private" - }, - { - "name": "candidate", - "type": { - "kind": "field" - }, - "visibility": "private" - } - ], - "return_type": { - "abi_type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs", - "fields": [ - { - "name": "call_context", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::call_context::CallContext", - "fields": [ - { - "name": "msg_sender", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "function_selector", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::function_selector::FunctionSelector", - "fields": [ - { - "name": "inner", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - } - ] - } - }, - { - "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": "include_by_timestamp", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 64 - } - }, - { - "name": "note_hash_read_requests", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", - "fields": [ - { - "name": "array", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::read_request::ReadRequest", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "length", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "nullifier_read_requests", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", - "fields": [ - { - "name": "array", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::read_request::ReadRequest", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "length", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "key_validation_requests_and_generators", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", - "fields": [ - { - "name": "array", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator", - "fields": [ - { - "name": "request", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest", - "fields": [ - { - "name": "pk_m", - "type": { - "kind": "struct", - "path": "std::embedded_curve_ops::EmbeddedCurvePoint", - "fields": [ - { - "name": "x", - "type": { - "kind": "field" - } - }, - { - "name": "y", - "type": { - "kind": "field" - } - }, - { - "name": "is_infinite", - "type": { - "kind": "boolean" - } - } - ] - } - }, - { - "name": "sk_app", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "sk_app_generator", - "type": { - "kind": "field" - } - } - ] - } - } - }, - { - "name": "length", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "note_hashes", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", - "fields": [ - { - "name": "array", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::note_hash::NoteHash", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "length", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "nullifiers", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", - "fields": [ - { - "name": "array", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::nullifier::Nullifier", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "note_hash", - "type": { - "kind": "field" - } - } - ] - } - } - }, - { - "name": "length", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "private_call_requests", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", - "fields": [ - { - "name": "array", - "type": { - "kind": "array", - "length": 5, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::private_call_request::PrivateCallRequest", - "fields": [ - { - "name": "call_context", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::call_context::CallContext", - "fields": [ - { - "name": "msg_sender", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "function_selector", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::function_selector::FunctionSelector", - "fields": [ - { - "name": "inner", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - } - ] - } - }, - { - "name": "args_hash", - "type": { - "kind": "field" - } - }, - { - "name": "returns_hash", - "type": { - "kind": "field" - } - }, - { - "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": "length", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "public_call_requests", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", - "fields": [ - { - "name": "array", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::counted::Counted", - "fields": [ - { - "name": "inner", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::public_call_request::PublicCallRequest", - "fields": [ - { - "name": "msg_sender", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "calldata_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "length", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "public_teardown_call_request", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::public_call_request::PublicCallRequest", - "fields": [ - { - "name": "msg_sender", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "calldata_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "l2_to_l1_msgs", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", - "fields": [ - { - "name": "array", - "type": { - "kind": "array", - "length": 2, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::counted::Counted", - "fields": [ - { - "name": "inner", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message", - "fields": [ - { - "name": "recipient", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::eth_address::EthAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "content", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "length", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "private_logs", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", - "fields": [ - { - "name": "array", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::private_log::PrivateLogData", - "fields": [ - { - "name": "log", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::log::Log", - "fields": [ - { - "name": "fields", - "type": { - "kind": "array", - "length": 18, - "type": { - "kind": "field" - } - } - }, - { - "name": "length", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "note_hash_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "length", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "contract_class_logs_hashes", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::utils::arrays::ClaimedLengthArray", - "fields": [ - { - "name": "array", - "type": { - "kind": "array", - "length": 1, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::counted::Counted", - "fields": [ - { - "name": "inner", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::log_hash::LogHash", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "length", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "length", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "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": "historical_header", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::block_header::BlockHeader", - "fields": [ - { - "name": "last_archive", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "content_commitment", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::content_commitment::ContentCommitment", - "fields": [ - { - "name": "blobs_hash", - "type": { - "kind": "field" - } - }, - { - "name": "in_hash", - "type": { - "kind": "field" - } - }, - { - "name": "out_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "state", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::state_reference::StateReference", - "fields": [ - { - "name": "l1_to_l2_message_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "partial", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::partial_state_reference::PartialStateReference", - "fields": [ - { - "name": "note_hash_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "nullifier_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "public_data_tree", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot", - "fields": [ - { - "name": "root", - "type": { - "kind": "field" - } - }, - { - "name": "next_available_leaf_index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - ] - } - } - ] - } - }, - { - "name": "global_variables", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::global_variables::GlobalVariables", - "fields": [ - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - }, - { - "name": "block_number", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "slot_number", - "type": { - "kind": "field" - } - }, - { - "name": "timestamp", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 64 - } - }, - { - "name": "coinbase", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::eth_address::EthAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "fee_recipient", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "gas_fees", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_fees::GasFees", - "fields": [ - { - "name": "fee_per_da_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 128 - } - }, - { - "name": "fee_per_l2_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 128 - } - } - ] - } - } - ] - } - }, - { - "name": "total_fees", - "type": { - "kind": "field" - } - }, - { - "name": "total_mana_used", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "tx_context", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::transaction::tx_context::TxContext", - "fields": [ - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - }, - { - "name": "gas_settings", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_settings::GasSettings", - "fields": [ - { - "name": "gas_limits", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas::Gas", - "fields": [ - { - "name": "da_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "l2_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "teardown_gas_limits", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas::Gas", - "fields": [ - { - "name": "da_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "l2_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "max_fees_per_gas", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_fees::GasFees", - "fields": [ - { - "name": "fee_per_da_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 128 - } - }, - { - "name": "fee_per_l2_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 128 - } - } - ] - } - }, - { - "name": "max_priority_fees_per_gas", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::gas_fees::GasFees", - "fields": [ - { - "name": "fee_per_da_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 128 - } - }, - { - "name": "fee_per_l2_gas", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 128 - } - } - ] - } - } - ] - } - } - ] - } - } - ] - }, - "visibility": "databus" - }, - "error_types": { - "576755928210959028": { - "error_kind": "string", - "string": "0 has a square root; you cannot claim it is not square" - }, - "855401245733623969": { - "error_kind": "string", - "string": "Obtained invalid key validation request" - }, - "1004672304334401604": { - "error_kind": "fmtstring", - "length": 48, - "item_types": [ - { - "kind": "field" - }, - { - "kind": "field" - } - ] - }, - "2920182694213909827": { - "error_kind": "string", - "string": "attempt to subtract with overflow" - }, - "3206131020419630384": { - "error_kind": "fmtstring", - "length": 75, - "item_types": [] - }, - "3305101268118424981": { - "error_kind": "string", - "string": "Attempted to delete past the length of a CapsuleArray" - }, - "3738765135689704617": { - "error_kind": "fmtstring", - "length": 58, - "item_types": [ - { - "kind": "field" - } - ] - }, - "5019202896831570965": { - "error_kind": "string", - "string": "attempt to add with overflow" - }, - "5727012404371710682": { - "error_kind": "string", - "string": "push out of bounds" - }, - "6485997221020871071": { - "error_kind": "string", - "string": "call to assert_max_bit_size" - }, - "7233212735005103307": { - "error_kind": "string", - "string": "attempt to multiply with overflow" - }, - "8270195893599566439": { - "error_kind": "string", - "string": "Invalid public keys hint for address" - }, - "10676044680617262041": { - "error_kind": "fmtstring", - "length": 98, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - }, - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - }, - { - "kind": "field" - } - ] - }, - "11732781666457836689": { - "error_kind": "fmtstring", - "length": 77, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "13649294680379557736": { - "error_kind": "string", - "string": "extend_from_bounded_vec out of bounds" - }, - "14101993474458164081": { - "error_kind": "fmtstring", - "length": 61, - "item_types": [ - { - "kind": "field" - }, - { - "kind": "field" - } - ] - }, - "14225679739041873922": { - "error_kind": "string", - "string": "Index out of bounds" - }, - "14657895983200220173": { - "error_kind": "string", - "string": "Attempted to read past the length of a CapsuleArray" - }, - "15200354114977654233": { - "error_kind": "fmtstring", - "length": 144, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "15760694058516861966": { - "error_kind": "fmtstring", - "length": 128, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "16218014537381711836": { - "error_kind": "string", - "string": "Value does not fit in field" - }, - "16446004518090376065": { - "error_kind": "string", - "string": "Input length must be a multiple of 32" - }, - "16954218183513903507": { - "error_kind": "string", - "string": "Attempted to read past end of BoundedVec" - }, - "17226037485472400844": { - "error_kind": "fmtstring", - "length": 132, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "17610130137239148460": { - "error_kind": "fmtstring", - "length": 98, - "item_types": [] - }, - "17843811134343075018": { - "error_kind": "string", - "string": "Stack too deep" - } - } - }, - "bytecode": "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", - "debug_symbols": "TJ3LrjU9b5zv5R9nsHQgReVWMghyNAwYNpDDyMi9ZzdLZNXE71O/v62S1M1avbq5e//7P/77//iv//ef/vM//+v//Lf//Y//+J/+/R//9X/987/8yz//03/+l3/7b//l//zzv/3r3//67//4ff9n7H/8x7mu/b//8I/x6f33v47/8I898M/EPwv/bPxj+Mfxz8E/gX9u/mMYxTCKYRTDKIZRDKMYRjGMYhjFMIpjFMcojlEcozhGcYziGMUximMUxygHoxyMcjDKwSgHoxyMcjDKwSgHoxyMEhglMEpglMAogVECowRGCYwSGCUwysUoF6NcjHIxysUoF6NcjHIxysUoF6OM3+/9O96/8/273r/7/WvvX3//nvdvvH/feOONN95444033njjjTfeeOONN/7Gs+/feP9e/Dt/79/x/p3v3/X+3e9fe//6+/eNN9948288//t3/d6/4/0737/r/bvfv/b+/Rvvfv9+610fRMF9kOd5wiiYBd+qzwe7wAq84Bs5PoiC+yDP/W938uxPmAV/I8/9wS6wAi84BVFwH3z1ABgFs6BG9hrZa2Svkb/qmN/2fPUBuA++GgGMglmwCnaBFXhBjXxq5FMjR40cNXLUyFEjR40cNXLUyFEjR40cNfKtkW+NfGvkWyPfGvmrqvkdna+uAKcgCi5gfuUFGAWzYBXsAivwglMQBTXyqJFHjTxq5FEjjxp51MijRh418qiRR408a+RZI88aedbIs0aeNfKskWeNPGvkWSOvGnnVyKtGXjXyqpFXjbxq5FUjrxp51ci7Rt418q6Rd428a+RdI+8aedfIu0beNbLVyFYjW41sNbLVyFYjW41sNbLVyFYje4381eAaH8yCVbALrMALTkEU3AdfDQJq5FMjnxr51MhfDa79gRecgm/k+8F98NUgYBTMglWwC6zAC05BjRw18q2Rb418XyLNuwp2gRV4wSmIgpd16/crGAWzYBXsAiv4G3nPD05BFNwHXw0CRsEsWAW7wApq5FEjjxp51MizRv5qcK8PZsEq2AVW4AWnIArug68GATXyqpFXjbxq5K8G7feBF5yCKLgPvhoEjIJZsAp2QY28a+RdI+8aedfIViNbjWw1stXIViNbjWw1stXIViNbjew1stfIXiN7jew1stfIXiN7jew1stfIp0Y+NfKpkU+NfGrkUyOfGvnUyKdGPjVy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0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOkdbUjYrZ52DoukWZZ2DRtNsWk27yZra47THaY/THtEe0R7RHtEe0R7RHtEe0R7RHtEetz1ue9z2uO1x2+O2x22P2x63PW55oHEJNJpm02raTdbkTacpmtpjtMdoj9Eeoz1Ge4z2GO0x2mO0x2iP2R6zPWZ7zPaY7THbY7bHbI/ZHrM9Vnus9ljtsdpjtcdqj9Ueqz1We6z22O2x22O3x26P3R67PXZ77PbY7bHbw9rD2sPaw9rD2sPaw9rD2sPaw9rD28Pbw9vD28Pbw9uj63x3ne+u8911vrvOs//JR9JsWk27yZq86TRF0y366vxRe0R7RHtEe0R7RHtEe0R7RHvc9rjtcdvjtsdtj9setz1ue9z2uOWRzVGPRtNsWk27yZq86TRFU3uM9hjtMdpjtMdoj9Eeoz1Ge4z2GO0x22O2x2yP2R6zPWZ7zPaY7THbY7bHao/VHqs9Vnus9ljtsdpjtcdqj9Ueuz12e+z22O2x22O3x26P3R67PXZ7WHtYe1h7WHtYe1h7WHtYe1h7WHt4e3h7eHt4e3h7eHt4e3h7eHt4e5z26Dq3rnPrOreuc+s6t65z6zq3rnPrOreuc+s6t65z6zq3rnPrOreuc+s6t65z6zq3rnPrOreuc+s6t65z6zq3rnPrOreu8+y/cvze069pNM2m1bSbrMmbTlM0tcdoj9Eeoz1Ge4z2GO0x2mO0x2iP0R6zPWZ7zPaY7THb46vz80vyptMUTbfoq/NHo2k2rabd1B5fnZ+RdJqi6RZ9df5oNM2m1bSbrKk9dnvs9tjt8dX5WUmjaTatpt1kTd50mqLpFnl7eHt4e3h7eHt4e3h7eHt4e3h7nPY47XHa47THaY/THqc9Tnuc9jjt8dX5wW/2jabZ9OcRM2k3WdOfR2CU0xRNfx7x/SpmtnY9Gk2zaTXtJmvyptMUTeWRTV6PRtNs+jzw24q7yZo+j5t0mqLpFn11/mg0zabVtJusqT1Ge4z2GO3x1fn9JY2m2bSadpM1edNpiqZbtNpjtcdqj9Ueqz1We6z2WO2x2mO1x26P3R67PXZ77PbY7bHbY7fHbo/dHtYe1h7WHtYe1h7WHtYe1h7WHtYe3h7eHt4e3h7eHt4e3h7eHt4e3h6nPU57nPY47XHa47THaY/THqc9TntEe0R7RHtEe0R7RHtEe0R7RHtEe9z2uO1x2+O2x22P2x63PW573Pa45ZGNZI9G02xaTbvJmrzpNEVTe4z2GO0x2mO0x2iP0R6jPUZ7fHV+Z9ItyjoHjabZtJp2kzV502lqj9keqz1We6z2WO2x2mO1x2qP1R6rPVZ77PbY7bHbY7fHbo/dHrs9dnvs9tjtYe1h7WHtYe1h7WHtYe1h7WHtYe3h7eHt4e3h7eHt4e3h7eHt4e3h7XHa47THaY/THqc9Tnuc9jjtcdrjtEe0R7RHtEe0R7RHtEe0R7RHtEe0x22P2x63PW573Pa47XHb47bHbY9bHtms9mg0zabVtJusyZtOUzS1x2iP0R6jPUZ7jPYY7THaY7RH1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d57fr/Had367z23V+u85v1/ntOr9d59kBdy3Jm05TNN2irHPQaJpNq2k3tcdtj9setz2yzj3fl/FrGk2zaTXtJmvyptMUTe0x2mO0x2iP0R6jPUZ7jPYY7THaY7THbI/ZHrM9ZnvM9pjtMdtjtsdsj9keqz1We6z2WO2x2mO1x2qP1R6rPVZ77PbY7bHbY7fHbo/dHrs9dnvs9tjtYe1h7WHtYe1h7WHtYe1h7ZGvfvr9Em9jvgLq4fhwJU7iIm6iEZ14iEG8jfmqqId0O3Q7dDt0O3Q7dDt0O3Q7dAu6Bd2CbkG3oFvQLegWdAu6Bd0u3S7dLt0u3S7dLt0u3S7dLt1uu+ENVQ8HcRIXcRON6MRDDCLdBt0G3QbdBt0G3QbdBt0G3QbdBt0m3SbdJt0m3SbdJt0m3SbdJt0m3RbdFt0W3RbdFt0W3RbdFt0W3RbdNt023TbdNt023TbdNt023TbdNt2MbkY3o5vRzehmdDO6Gd2MbkY3pxuzZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMEsGs2QwSwazZDBLBrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDJLJrNkMksms2QySyazZDFLFrNkMUsWs2QxSxazZDFLFrNkMUsWs2QxSxazZDFLFrNkMUsWs2QxSxazZDFLFrNkMUsWs2QxSxazZDFLFrNkIUs88RCDeBuRJcBBnMRF3EQj0m3RbdFt0Q1ZchIHcRIXcRON6MRDDOJtNLoZ3YxuRjejm9HN6GZ0M7oZ3ZxuTjenm9PN6eZ0c7o53ZxuTrdDt0O3Q7dDt0O3Q7dDt0O3Q7dDt6Bb0C3oFnQLugXdgm5Bt6Bb0O3S7dLt0u3S7dLt0u3S7dLt0u222/79iIM4iYu4iUZ04iEGkW6DboNug26DboNumSXfy2dndh0WHuLnNnbibcwseTiIk7iIm2hEJx4i3SbdFt0W3RbdFt0W3RbdFt0W3RbdFt023TbdNt023TbdNt023TbdNt023YxuRjejm9HN6GZ0M7oZ3YxuRjenm9PN6eZ0c7o53ZxuTjenm9Pt0O3Q7dDt0O3Q7dDt0O3Q7dDt0C3oFnQLugXdgm5Bt6Bb0C3oFnS7dLt0u3S7dLt0u3S7dLt0u3S77ZadjIWDOImLuIlGdOIhBpFug26DboNug26DboNug26DbswSY5YYs8SYJcYsMWaJMUuMWWLMEmOWGLPEmCXGLDFmiTFLjFlizBJjlhizxJglxiwxZokxS4xZYswSY5YYs8SYJcYsMWaJMUuMWWLMEmOWGLPEmCXGLDFmiTFLjFlizBJjlhizxJglxiwxZokxS4xZYswSY5YYs8SYJcYsMWaJMUuMWWLMEmOWGLPEmCXGLDFmiTFLjFlizBJjlhizxJglxiwxZokxS4xZYswSY5YYs8SYJcYsMWaJMUuMWWLMEmOWOLPEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmyWGWHGbJYZYcZslhlhxmyWGWHGbJYZYcZslhlhxkyUmcxEXcRCM68RCDeBuRJUC6TbpNuk26ZZbMkejEQwzibcwseTiIk7iIm0i3RbdFt0W3RbdNt023TbdNt023zJL5S3TiIQbxNmaWPBzESVzETaSb0c3oZnQzujndnG5ON6eb083p5nRzujndnG6Hboduh26Hboduh26Hboduh26HbkG3oFvQLegWdAu6Bd2CbkG3oNul26Xbpdul26Xbpdul26Xbpdttt+z6LBzESVzETTSiEw8xiHQbdBt0G3QbdBt0G3QbdBt0G3QbdJt0m3SbdJt0m3SbdJt0m3SbdJt0W3RbdFt0W3RbdFt0W3RbdFt0W3TbdNt023TbdNt0Y5YEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSWXWXKZJZdZcpkll1lymSUXWTITN9GITjzEIN5GZAlwECeRbotui26Lbotui26Lbptum26bbptum26bbptum26bbptuRjejm9HN6GZ0M7oZ3YxuRjejm9PN6eZ0c7o53ZxuTjenm9PN6Xboduh26Hboduh26Hboduh26HboFnQLugXdgm7IEk80ohPTLRKDeBuRJcBBnMRF3EQjOpFul2633Nbv9yMO4iQu4iYa0YmHGES6DboNug26DboNug26DboNug26DbpNuk26TbpNuk26TbpNuk26TbpNui26Lbotui26Lbotui26Lbotui26bbptum26bbptum26bbptum26bboZ3YxuRjejm9HN6GZ0M7oZ3YxuTjenm9PN6eZ0c7o53ZxuTjen26Hboduh26Hboduh26Hboduh26Fb0C3oFnQLugXdgm5Bt6Bb0C3odul26Xbpdul26Xbpdul26XbpxiwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsGcySwSwZzJLBLBnMksEsmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySyZzJLJLJnMksksmcySySxB3+v3V2UX+l4fBvFzW+vDzJKHgziJi7iJRnTiIQaRboduyJKTOImLuIlGdOIhBvE2IkuAdAu6Bd2CbkG3oFvQLegWdLt0u3S7dLt0u3S7dLt0u3S7dLvthr7Xh4M4iYu4iUZ04iEGkW6DboNug26DboNug26DboNug26DbpNuk26TbpNumSX5N3rR9/rQiZ/b+wu7QbyNmSXfH1pe6Ht9OImLuIlGdOIhBvE2brptum26bbptum26bbptum26bboZ3YxuRjejm9HN6GZ0M7oZ3YxuTjenm9PN6eZ0c7o53ZxuTjen26Hboduh26Hboduh26Hboduh26Fb0C3oFnQLugXdgm5Bt6Bb0C3odul26Xbpdul26Xbpdul26XbpdtsNfa8PB3ESF3ETjejEQwwi3QbdBt0G3QbdBt0G3QbdBt0G3QbdJt3wTPgmTuIibqIRnXiIQbyN6C8B0m3RbdFt0W3RbdFt0W3RbdFt023TbdNt023TbdNt023TbdNt083oZnQzuhndjG5GN6Ob0c3oZnRzujndnG5ON6eb083p5nRzujndDt0O3Q7dDt0O3Q7dDt0O3Q7dDt2CbkG3oFvQLegWdAu6Bd2CbkG3S7dLt0u3S7dLt0u3S7dLt0u3226v7xU4iJO4iJtoRCceYhDpNug26JZZsj1xETcxrxQi0YmHGMTbmFnycBAncRE3kW6TbpNuk26Tbotui26Lbotui26Lbotui26Lbotum26bbptum26bbptum26bbptum25GN6Ob0c3oZnQzuhndjG5GN6Ob083p5nRzujndnG5ON6eb083pduh26Hboduh26Hboduh26HbodugWdAu6Bd2CbkG3oFvQLegWdAu6Xbpdul26Xbpdul26Xbpdul26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IQbxNub1w/cA1LI5rHAS080Sc1xPPMQg3sb5Iw7iJC7iJhqRbpNuk26Tbotui26Lbotui26Lbotui26Lbotum26bbptum26bbptum26bbptum25GN6Ob0c3oZnQzuhndjG5GN6Ob083p5nRzujndnG5ON6eb083pduh26Hboduh26Hboduh26HbodugWdAu6Bd2CbkG3oFvQLegWdAu6Xbpdul26Xbpdul26Xbpdul263Xbbvx9xECdxETfRiE48xCDSbdBt0G3QbdBt0G3QjVmymSWbWbKZJZtZspklm1mymSUbWXITjejEQwzibUSWAAdxEheRbotui26Lbotui26ZJd8TJsvX4RVO4iJuohHT7SQeYhBvI7IEOIiTuIibaES6Gd2Mbpkl35/gsGyzKxzEXFsuPrPk4SZ+bivXlqmBH8t8+Pp/LVvnCr8Rvh5Zy1fcFRrRiYcYxG++39NUyza7wkGcxHTLSWY+PDTi57Zz6pkPD4P4ue2ceubDw0GcxM9t5+IzH/IqPhvqPK/Xs6Gu8Bbmy+wKc1xPzHFPYo57E79xvwfBls13hU48xM/tezxs2Xz3MJPg4SB+bvmdITvuPG+aZcedW04ny/+782/5Bjt3/FgQb2OW/8NBnMRF/NzyDlx25xWeOo2yJa+wz9RsySscxElcxE00ohPptui26LbptumWNZ/35bIlr3ATc0G5k1nzDw8xiLcxa/7hIE7iIm4i3YxuWfP5fShfW1d4G7PmHw7iJH5ueSst2/cKjejEzy3vqmX7XuFtzOuH/PaV7Xue37Oyfa8w3fK0z3x4mG45ncyHh4cYxNuY+fBwECdxETeRbkG3oFvQLeh26Xbpdul26Xbpdul26Xbpdul22y1fW1c4iJO4iJtoRCceYhDpNug26DboNug26DboNug26DboNug26ZYBkl+2s0uxcBE3Masb6MRDDOJtRJYAB3ESF/EbN79nZechPvWy89DzrmV2HhZO4iJuohGd+I2bt2Gzx/Dtg3HFxhVnzT904rfivHOaPYaFtzFr/iGPptPNeTSdR9N5NJ1H03k0UfM5B9R8ImoeyKOZNY85ZM0/3ES6seadNe+seWfNO2veWfMePHeCOxncyeBOZs1jDsGdDO4ka95Z886ad9a8s+adNe+seb88bqh5IHfy9k5muyHmkO2GhZPYboc1f1jzhzV/WPOH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", - "verification_key": "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\nAAAFiSRi70jt/BTMpcaOrm4=" - }, - { - "name": "constructor", - "is_unconstrained": true, - "custom_attributes": [ - "public", - "initializer" - ], - "abi": { - "parameters": [ - { - "name": "admin", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - }, - "visibility": "private" - } - ], - "return_type": null, - "error_types": { - "2233873454491509486": { - "error_kind": "string", - "string": "Initializer address is not the contract deployer" - }, - "5019202896831570965": { - "error_kind": "string", - "string": "attempt to add with overflow" - }, - "14225679739041873922": { - "error_kind": "string", - "string": "Index out of bounds" - }, - "17618083556256589634": { - "error_kind": "string", - "string": "Initialization hash does not match" - }, - "17843811134343075018": { - "error_kind": "string", - "string": "Stack too deep" - } - } - }, - "bytecode": "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", - "debug_symbols": "tZzdjls3DoDfZa5zcfRDicyrLIoiTadFgEESTJMFFkXefUWKP54JjqLYzk39meNDUxRFkZKbfx/+fPzj69+/f/j416d/Ht7+59+HP54/PD19+Pv3p0/v33358OnjkP77cPB/MD+8rW8esD+87W8eKM2XJi/pSPqq75O+T/jwFsdrLvqq70vW1z5fq76vbb5C0tfxPh0DWjIghV4Nhs5UBrCFE7oCmYRUko9swHrGeHKqBqjAxk7oCmzuBJa0ARUU4DBgPcRACq0YoEI3STcJmoQdmg+GNqEcQ3PODKCQWFIZqgEpZJOwhwXY5gldoZqEvZzH9BQ2fgIoNJM0k3STsM0lDWCbJwzNZYy9sJ8ntAmVA2KCSZJJkknyYVANSKEUA1Rg48swo7JXJ3SFbn/qJkGToEnYvRNgArB7J1QDUkjFABUyKwSGplCSARiQQq0GqAD2OHSFZo83e5z9PMEkHLRlxEYTZwo0hWSSZJJskgwGpFCqASrUYjC+oo5ga7zgJoABKbBX6wi/RuPxOtZO50U0oSlwZE6oBqTAq6kCQ1fgyJxgkmqSahIwCZiE5702BlLoTQGTQVfggJzAnxkziDzdE6oBKiR+amQbZB9OAAP+ruEoZB8KiKkCXaGpe1FmUEAnDiUOBdTzSMVAPU9HMgAD9Txl9TxV9TxBNlDPUzsMqoF6nrp6nrr6kDAbmIRMQipJx5GdXJbU+YPIKDejkpy6Uc1OOgXpgMOpOqERr2dITH3ogyzUjLA6kVJiS6EycZABCHUjtkoJnMiIF6nSsABks2LvKnWj5rLmsu6y7jJ0Gc818KYj249SU8och0psgWyKPOGT2M9AQt2Io1IJnMYTTbRwYCqhES9vJZeBy8BlPDalZsS+VwIjPJz42+ZGjkYc0komK0dxclnKTs2Ix6YERuVw4m/j8cr+pERGzf/aXNZd1l3G25VSN+KZUWpKsmUp2bdVzmtKrLkLoRFHnVI34qhTakb1cHItlYzAtYBrkZkR4lnoXOZUqbU47mXr6kUIjDhylNCIbekc47IB9SbUjDhzKFUnNOLkocQVnxRjnGeVmhG5jEwm+5WSy5LLOLI7r1rZs5TAiYy4BugkhEZSJ0oZyOl3EsfGJB4RZiGW8cgbJ2XsQiwTCzieldCIo5iKECp1XqHEf5X9beQ+Qa78DhIkx1wDQ1pCWkLKy9OwO/IUGTbHWfdO5C+eFa8UwROlDFYMKYYUQ8pjNOyGKCWxYnPk+TL0L0Yu2QxlbCiIjqUEdseaApujlM6KoUzK54ktlLVQ1rMjyTCzIBrSUQJDmkKaQppzYHMsKRAc6xEoXyydRUVHmULF5jhniIORSJQ1QVIcO0IJ7I5zAiY2xzkBKFgDybGEtIS0hrSGFELaRC8JNkfpVxTRcQbXRHKU4JIO5pDgEpTG0BAcpefKSRAdZS4U2QbuebJs44bkKAOa2GzesmzMhuSI1ZGOQAgknayc51xM7I5zLgSnq4FR4lemZTZ/iujYcqBPoeywhmATkLtPS8YaGFIKKbm0HDUwpHPFknSuKdCnsJQS6FNYag1Em6wiUa3YHCVgFGVaZnssQQCC6IjNkZJhFdO5s8w1S2igIDmKkYrdUXKJYnOUuSiHYA0kxxbSFtIe0h5SDKkETJaOXyZAEQ1Bsqcim8ONcQYJGEUeW6mC8hU8YpDFy7X9CB0IJEeID0BIW0hbSMXrit1RjkMUm6NMgKJ/ceOKwlC+Igmio2RPxe4oK1axOcqKVQRHyZ61CtZAcoSQQkhbSOUYZaIsdMXuiCmwOcoUchszsAaiobSzijJZ3PmNoxrRIIc10/SJNRAdZYkodkfZu7mjyXPvnsgFiWFIMaQYUgopuRQlp3LPNBACyXFO1kQ2h7uljDJZijw24KBFOdpS7I5SorRDkIfJ1X9GKOYdnMMUlGEqQiCb03gCEN0lSDnQpdICjzpOsDmmkMq0NLaMss/F3LAnSqpQ9GmhmCyacSYIIYX4bMuBobfHt/XQMLe6LtgVx3FdCoRA8YNgtiQ22qMcGFJJbW1ic4SQgviBGGf+FWlrjr0EoqPkM0VypJCSfzYdOdD1pnQEuoY0dxEQ7I4yCkUI5Me4kSnSSMsGWHTDnhhSWcc9CTZHCqksBu6FivTT87F8NMdUAtEx10ByLCEt8dmaA0MvxLdBaOjuh9zdDxlTIAS6H4oXe0V6Y8OQZh9xye6HUkJa3A+lumUl7C1QAn1s0jkb+ihKD2mPz2JYhqGX4tu8kC1VelAQ6kY5OYGT+KAwcgPU5WFrUYu0wZMktfR5ZN0ce0glg06leNhT2IyoOGljW+S4V4mMksuSfy5nJ9MH5XDyZ8XFiujYQirhzq1vgWn5RAgkR7kO4FZ3IDpSM5TW2pA1cONb5uaLHBJy2KsoIazINnBrPM71i6PkEEVwFCMVmyOGVKIZefrm3qro0i5FtCI6SowrNsfsGrqsPu7aS5fFhew+Ofc17I7TyIngKLuoovgBBdFRMreiS/EogSFNIU0hlRyCPAFYjsDuOL0+ER2n1yd2m5a5dSpCIDnKQuy8e8ytU7yDEg+CJOlPsQbK9RKHxtwkxSWzq1UMqSQOSoLgCCGdF1tZ0KeFmnudJIkr+gwRlkB0pJCSfbbOrVMRAskxoWPRQ99BzYjHoFSdxAdFrqDaPOut82R5ksskaEiekcieSCGVjZLks6Tnx1W62Ukc10rdyM6jq9x4TiouK/65mpxcX/XvAH+WXczl+aBmxHYrVScZ9Lxc0xuCKt2rkstk2VEXBMcSUskjfPg1kOwpNnKSXUQM6kZyQzMJjbrLun8O3R50fejfYbdMVTZFGZYcGE/Kh1N18kHL1jcfhuTksubDk+tNxR7S7oOW8+P5lBspp8ZKNph6FCczXPZBJf9cTk7gZN8h15y1fPv25sEu3n//8vz4yPfuFzfx437+87vnx49fHt5+/Pr09Obhv++evsqH/vn87qO8fnn3PP46Vv7jxz/H61D414enR6Zvb+Lp4/zRxDWtPj46WMiuYoT8CyVpoQR4OqaOcUV5oSK/UJEXKkaCdh19nJy5kkYvdJRzHaOg43NC0TE41zMdq6E0vq7ToWA+HQqcqxhnC2bFuIaJORlH6y9UtIUVmGxORxo8V7FtRTlVse0LOvUFnavo3EmKhnF96wpq3jZh3Cd7VPR+akJKq7DAalExSshzTyzCM8tmPr05uoJzHbt2rHRsugPruTvgF04J1ohNOF/sqS/cOW6T3Z/HODI4Xam48CdnXnNoHeeAp0qWlpQclgw1Vyo5jgslp8krr8IDzI5RMLuCsQfvT0yLicF0noUXKbSCR8foy2JaxpnMto5xTQDNvYEXSfS1NxZRiiN/q45ReJ/vSrndIUCWhpQUhrSFIYtIHUWO23FcrPz+SsUykYKZ0dvF5I5a6eX2uNjroXF1KTpgHLSGjp+wgsCTR8nnVixS6bgP9QQ0uvhzHaud3p1RL8qNce3yUkNdJXTudjShH3SuYxEa4Jnjcpv/KQ1ee7UE140jx8Z0uU6+04Gr8i174oCLDfLndHhCH30MXaejHK5jbJanOmpaRZcvk9qu0kDVQnycF1+lYSRcM2Icqp7Pa13M67jssvis4zQr0g79hDtrdXfCldNaLroDwqt03GMocj03zRgXDtetlJ58V+qL9QrHr9XBv1vxqrrjdTp6jzqQzlc9lFtXykrD3kpZadhdKdBuDq+lOykSD+Vzd/6g6qnlouop1zSf6LXGqODOy/u2GEs5kvfAqS50pNuLjZZXxYY3j6PuyCfFxtqKvWKj1duLjQa3Fhut3V5stH5rsbHUsFVsLMeRS4yj5ut0bKbQnn6tjt00vNSxmYZ7vTUNrzTspeGVht003PvNaXjpzs00vMygUa/Q5anXsX++QZ52+Fd5pyow3d5Gp/WZgptxUfJ8Z8ZqeyXwLnpwPc72JKzLU9UOcapKxxUbW45NKV82wN8NZtnNg6fhHCsFfmJea9hwPq+LvZU87VCJVQIvD9tx0T+PEtrCc1xyXYQnvjwCpNUGP6qL7PORjtNTDVodNo0LKD9uSpBOJ5XyamOsnkPHbfiRzpSsXOqbK12cRr5yKdU7uBTu4dJ2D5f2X+vSEdDo2fwic7x2Kq0uD9rhxexI7P10zR/LSI0acHA7rokP8h32yP1sLONvy2Ov7JXo5TUGvsodx+pgNBdb++M2sS6U1Nsr2nG2eHtJO3byW2vadPTbi1r57f5tVe1axVZZux7K5iFaSun2U7QfKNk7Rlsr2TxHS+nmunSpYq8wXarYrUxTur00/YFP9w7TfqBk7zRtqeQuo9k8T1uvms0uLC2PTe6hZLeXWyvZbObS6sppc9WsVGyumpWK7VWzuuvZjbOlT3c7uuX+3Q8zBPpFOvtu6y3L35cU8AXcS6fTimZ57zTu7Uvc4Rc4r4uWA/KfywBe/lzmuwHBqjDy4RwXBWt+PT1lFSfZ7yVHKIQh4yp635BR8YQlrS0swTsUNYVuLmrqcYeiZnX/s1mRLO3YrUhquUNFslayWZHUO9ybpNrukKBrvzlBr1RsJuiViu0Evbq12E3QS5/eJ0HD4Qm6L/IZlDv04AnqHZrwBPCLu/BRefvq4/9X4uLA6bVbVof2/iu+dpyfWSVYXZ7u/rQyAS2PATd/XLkaTvPfNbZy/uPK1NI9dvLV9dT+Tr5MBYdlesrXZpMWB2Bwc0JaqVgWnXsDWarYG8hm6btSsew59wayVLE3kM3Od6Gi3zyOfvMw+s2jWF72lThGLBd3KT936bhZCt3hdmqpY7tpXivxaUm8P16nZPccYalktzpcK9msDtfD2TyvwtvPq/D28yq8x3kV/upg3T2vwtuTKd6eTPHmNLT8odLWOJYatoax+WOphYblDxO3RrHUsDWKzR9Hvtbw23j77v2H5xf/lug3VvX84d0fT4/69q+vH99f/PXL/z7bX+zfIv38/On9459fnx9ZU/yDpOM//6Gx6Y6r19/ePCR5OypSSoXfJn47jKPaf/vGxvwf" - }, - { - "name": "end_vote", - "is_unconstrained": true, - "custom_attributes": [ - "public" - ], - "abi": { - "parameters": [], - "return_type": null, - "error_types": { - "8095637994846897154": { - "error_kind": "string", - "string": "Only admin can end votes" - }, - "13699457482007836410": { - "error_kind": "string", - "string": "Not initialized" - }, - "17843811134343075018": { - "error_kind": "string", - "string": "Stack too deep" - } - } - }, - "bytecode": "JwACBAEoAAABBIBEJwAABAMnAgEEACcCAgQAHwoAAQACgEQlAAAAPyUAAABAKAIAAQSARCcCAgQAOw4AAgABJiUAAACXHgIAAQAeAgACADMqAAEAAgADJwIBAQEkAgADAAAAaSUAAADAJwIBAAEvCgABAAIeAgADAQoqAgMEJAIABAAAAIslAAAA0icCAgADMAoAAQACJigAgAQEeAANAAAAgASAAyQAgAMAAAC/KgEAAQX3ofOvpa3UyjwEAgEmKgEAAQW+Hj//PqT2+jwEAgEmKgEAAQVwWXvdIQFEAjwEAgEm", - "debug_symbols": "tZXLrqMwDIbfJWsWjp2b+ypHVUVbeoSEaMWBkUYV7z7OmSaFRbKYy6b5A82Hf8dOnuranZfPUz/e7l/q8PFU56kfhv7zNNwv7dzfR3n6VBB/HKuDaZQ36uBlkJmGRgUvo24U4+9RAyRhRTgRGpJwIlgEanVAiMK9BJkkhItWhIlP7Lo2KoVymqeui5FsYpOIH+3UjbM6jMswNOpHOyzff/p6tOP3OLeTvBV2N15lFOCtH7qo1ua9GspLNVnC13JNzvmMEI87iK5AADMDDG4QuENgBeE5uMTwzDZDHO8YVGYQEoQXQzSaEqNqhTmFoTUXrdh/YMX9bys25F0J5V0JZYT3ISF8MMUguGKEDOhkhIz5WyMay0ZqZc4+I5hdRth9o2isOfGYjfCmT4LfM2oVCi74BAEPoZgNU4PAO6UABoqQSpFK29sMsRSK+1JJKgKkjCAgFJPqa/uyOX7YVryEarN4+24Whj/wsikQ8UIlL9VsMCWC1r5EwEqhE+fqkK6hYolhrUxRej0nQ47jUjKwVqfa2HQMkra6mFGs1ak1DnKJWdA7yFFm7aWfdpfxGmlT356H7jW9LeNl83b++Uhv0mX+mO6X7rpMXSS9b/R4MX9gaIiO8XaWCfmG+LjGT/8C" - }, - { - "name": "get_vote", - "is_unconstrained": true, - "custom_attributes": [ - "utility" - ], - "abi": { - "parameters": [ - { - "name": "candidate", - "type": { - "kind": "field" - }, - "visibility": "private" - } - ], - "return_type": { - "abi_type": { - "kind": "field" - }, - "visibility": "public" - }, - "error_types": { - "206160798890201757": { - "error_kind": "string", - "string": "Storage slot 0 not allowed. Storage slots must start from 1." - }, - "576755928210959028": { - "error_kind": "string", - "string": "0 has a square root; you cannot claim it is not square" - }, - "1004672304334401604": { - "error_kind": "fmtstring", - "length": 48, - "item_types": [ - { - "kind": "field" - }, - { - "kind": "field" - } - ] - }, - "2920182694213909827": { - "error_kind": "string", - "string": "attempt to subtract with overflow" - }, - "3206131020419630384": { - "error_kind": "fmtstring", - "length": 75, - "item_types": [] - }, - "3305101268118424981": { - "error_kind": "string", - "string": "Attempted to delete past the length of a CapsuleArray" - }, - "3738765135689704617": { - "error_kind": "fmtstring", - "length": 58, - "item_types": [ - { - "kind": "field" - } - ] - }, - "5019202896831570965": { - "error_kind": "string", - "string": "attempt to add with overflow" - }, - "5727012404371710682": { - "error_kind": "string", - "string": "push out of bounds" - }, - "6485997221020871071": { - "error_kind": "string", - "string": "call to assert_max_bit_size" - }, - "7233212735005103307": { - "error_kind": "string", - "string": "attempt to multiply with overflow" - }, - "8270195893599566439": { - "error_kind": "string", - "string": "Invalid public keys hint for address" - }, - "10676044680617262041": { - "error_kind": "fmtstring", - "length": 98, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - }, - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - }, - { - "kind": "field" - } - ] - }, - "11732781666457836689": { - "error_kind": "fmtstring", - "length": 77, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "13649294680379557736": { - "error_kind": "string", - "string": "extend_from_bounded_vec out of bounds" - }, - "14101993474458164081": { - "error_kind": "fmtstring", - "length": 61, - "item_types": [ - { - "kind": "field" - }, - { - "kind": "field" - } - ] - }, - "14225679739041873922": { - "error_kind": "string", - "string": "Index out of bounds" - }, - "14657895983200220173": { - "error_kind": "string", - "string": "Attempted to read past the length of a CapsuleArray" - }, - "15200354114977654233": { - "error_kind": "fmtstring", - "length": 144, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "15760694058516861966": { - "error_kind": "fmtstring", - "length": 128, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "16218014537381711836": { - "error_kind": "string", - "string": "Value does not fit in field" - }, - "16446004518090376065": { - "error_kind": "string", - "string": "Input length must be a multiple of 32" - }, - "16954218183513903507": { - "error_kind": "string", - "string": "Attempted to read past end of BoundedVec" - }, - "17226037485472400844": { - "error_kind": "fmtstring", - "length": 132, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "17610130137239148460": { - "error_kind": "fmtstring", - "length": 98, - "item_types": [] - }, - "17843811134343075018": { - "error_kind": "string", - "string": "Stack too deep" - } - } - }, - "bytecode": "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", - "debug_symbols": "TL3LkjQ9b6R5L996FgmQAEndyizapqcPJjNZy6wPK918V8AJum/0Pa7/LToPAc/ISFTWf/zzX/7rf/4///0//ev/+G///r/++Zf/9z/++c//81//7d/+9b//p3/79/////vf//rv/+Pv//sf//y+/zPOP/8y/p9/5p/Iv//YP/+y//7j//yL/f7+O/7+63//nX//nX//jb//fv8s73/X/e++/z34b/zuf+3+1+9/x/3vvP+948UdL+54cceLO17e8fKOl3e8vOPlHS/veHnHyzte3vHyjrfueOuOt+5464637njrjrfueOuOt+54646373j7jrfvePuOt+94+46373j7jrfvePuOd+5454537njnjnfueOeOd+5454537njnjme/X4M1eMNomA3RkA2rYTf0yNYjW49sPbL1yNYjW49sPbL1yNYjW4/sPbL3yP43sv8+GA2zIRqyYTXshnNh/BqsoUcePfL4RrYPoiEbVsNuOBe+MgJ8I88PvpH3B6NhNkRDNqyGv5GHf3AufCUFsIa/kcf4YDTMhm/kb8e+wgKshm/k88G58BUXwBq8YTTMhmjIhtXQI2ePvHrk1SN/hTa//fkqDTAboiEbVsNuOBe+ggNYQ4+8e+TdI+8eeffIu0fePfLukU+PfHrk0yOfHvn0yKdHPj3y6ZFPj3zuyP7V4BwfWIM3jIbZEA3ZsBp2w7lgPbL1yNYjW49sPbL1yNYjW49sPbL1yN4je4/sPbL3yN4je4/sPbL3yN4je488euTRI48eefTIo0cePfLokUePPHrk0SPPHnn2yLNHnj3y7JFnjzx75Nkjzx559sjRI0ePHD1y9MjRI0ePHD1y9MjRI0ePnD1y9sjZI2ePnD1y9shfDc78YDXshnPhq0GANXjDaJgN0dAjrx559cirR64aPB9Ygzf8jRzzg9kQDdmwGnbDufDVIMAavKFHPj3y6ZFPj3xuIvnZDTeRxu/XYA3eMBpmQzRkw2rYDT2y9chfDcb6wBtGw2yIhmxYDbvhXPhqENAje4/sPbL3yN4jfzUY+4PVsBvOha8GAdbgDaNhNkRDjzx65NEjjx65bifjA2vwhtEwG6IhG1bDbjgXokeOHjl65OiRo0eOHjl65OiRo0eOHjl75OyRs0fOHjl75OyRs0fOHjl75OyRV4+8euTVI68eefXIq0dePfLqkVePvHrk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YJYMZslglgxmyWCWDGbJYJYMZslglgxmyWCWDGbJYJYMZkk1Y9r3xaVe3ZiNgziJQUziIm7ieVhZcpFuk26TbpNulSXuhUlcxE08DytLLhrRiYM4iXQLugXdgm5Bt6Rb0i3plnRLuiXdkm5Jt6Rb0m3RbdFt0W3RbdFt0W3RbdFt0W3RbdNt023TbdNt023TbdNt023TbdPt0O3Q7dDt0O3Q7dDt0O3Q7dDtPLfq6Gw0ohMHcRKDmMRF3ES6Gd2MbkY3o5vRzehmdDO6Gd2MbpUl31f+erV5Njqx3E7hJAYxiYu4iedhZclFIzqRboNug26DboNug26DbpNuk26TbpNuk26TbpNuk26TbpNuQbegW9At6BZ0C7oF3YJuQbegW9It6ZZ0S7ol3ZJuSbekW9It6bbotui26Lbotui26Lbotui26Lbotum26bbptum26bbptum26bbptul26Hboduh26Hboduh26Hboduh2nlv8fkQjOnEQJzGISVzETaSb0c3oZnQzuhndjG5GN6Ob0c3o5nRzujndmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWRLMkmCWBLMkmCXBLAlmSTBLglmSzJJkliSzJJklySxJZkkyS5JZksySZJYksySZJcksSWZJMkuSWZLMkmSWJLMkmSXJLElmSTJLklmSzJJkliSzJJklySxJZkkyS5JZksySZJYksySZJcksSWZJMkuSWZLMkmSWJLMkmSXJLElmSTJLklmSzJJkliSzJJklySxJZkkyS5JZksySZJYksySZJcksSWZJMkuSWZLMkmSWJLMkmSXJLElmSTJLklmSzJJkliSzJJklySxJZkkyS5JZksySZJYksySZJcksSWZJMkuSWZLMkmSWJLMkmSXJLElmSTJLklmSzJJkliSzJJkli1mymCWLWbKYJYtZspgli1mymCWLWbKYJYtZspgli1mymCWLWbKYJeh7/f7AiaPv9eImnoeVJReN6MRBnMQg0s3p5nRzulWW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3wVTnUezPtmqzqNGJw5ijXsKv3HXr/Abt24tq/OocRPPwyqculWrzqNGJw7i51Zvf6vdaNZ702o3mvVModqN/sKl8LOoN23VbtRoRCcO4iQG8XOr907VbtT4udU7wGo3ulj1dtGIThzEz60++qp2o8YkLuLnVp+IVbvRxaq3i5/bqZlVvV0cxHKr4656q081qt2ocRE38Tys18KLf25R7wCr3ahxECcxiElcxE08D7/XzUa6Lbotui26rRq3lrk28Tzc9f+ta2efh6fcam3HiE4cxEkMYq1tF9Yc6kI8m3guRjUANRrRiYM4iUFM4iJuIt2MbkY3o5vR7Sve+P7SdFRTT3wfvUQ19cT3yCCqqafRiYM4iUGscYGL+M33a2aJauq5+FVs4zeuzcIaIQoXsVZckxznHkBUo06jEZ1Y42bhJAYx78FGNeo0biLdgm5Bt6BbjIdVLQYcxEms3KkV113mxUXcxPOw7jIvfnPw2pKqlouDOIlBTOIibuJ5+L2wNtJt023TbdNt17h18lWFF8/DqsKLRnTiIE5iEJNIt0O389yqdabRiE4cxEkMYhIXcRPpZnQzuhndjG5GN6Ob0c3oZnQzujndnG5ON6eb083p5nRzujndnG6DboNug26DboNug26DboNug26DbpNuk26TbpNuk26TbpNuk26TbpNuQbegW9At6BZ0C7oF3YJuQbegW9It6ZZ0S7ol3ZJuSbekW9It6bbotui26Lbotui26Lbotui26Lbotum26bbptum26bbptunGLDFmiTFLjFlizBJjlhizxJglxiwxZokxSwxZMgpPoyNLgEZ04iDWy8wpTOIibuJ5WAFy0YhOHMRJpJvRzehmdDO6Od2cbk43p5vTzenmdHO6Od2cboNug26DboNug26DboNug26DboNuk26TbpNuk26TbpNuk26TbpNuk25Bt6Bb0C3oFnQLugXdgm5Bt6Bb0i3plnRLuiXdkm5Jt6Rb0i3ptui26Lbotui26Lbotui26Lbotui26bbptum26bbptum26bbptum26Xboduh26Hboduh26Hboduh26HaeW/VHNRrRiYM4iUFM4iJWXGXheYibEWDF1Sp04iBOYhCTWOFYbrgZAZ6HuBnZhUZ04iBOYhA/t++xfFQvVeMmnoeVJReN6MRBnMQg0m3QbdBt0K2y5HtaF9VL1ejE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" - }, - { - "name": "process_message", - "is_unconstrained": true, - "custom_attributes": [ - "utility" - ], - "abi": { - "parameters": [ - { - "name": "message_ciphertext", - "type": { - "kind": "struct", - "path": "std::collections::bounded_vec::BoundedVec", - "fields": [ - { - "name": "storage", - "type": { - "kind": "array", - "length": 17, - "type": { - "kind": "field" - } - } - }, - { - "name": "len", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - }, - "visibility": "private" - }, - { - "name": "message_context", - "type": { - "kind": "struct", - "path": "aztec::messages::processing::message_context::MessageContext", - "fields": [ - { - "name": "tx_hash", - "type": { - "kind": "field" - } - }, - { - "name": "unique_note_hashes_in_tx", - "type": { - "kind": "struct", - "path": "std::collections::bounded_vec::BoundedVec", - "fields": [ - { - "name": "storage", - "type": { - "kind": "array", - "length": 64, - "type": { - "kind": "field" - } - } - }, - { - "name": "len", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "first_nullifier_in_tx", - "type": { - "kind": "field" - } - }, - { - "name": "recipient", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - } - ] - }, - "visibility": "private" - } - ], - "return_type": null, - "error_types": { - "576755928210959028": { - "error_kind": "string", - "string": "0 has a square root; you cannot claim it is not square" - }, - "1004672304334401604": { - "error_kind": "fmtstring", - "length": 48, - "item_types": [ - { - "kind": "field" - }, - { - "kind": "field" - } - ] - }, - "2920182694213909827": { - "error_kind": "string", - "string": "attempt to subtract with overflow" - }, - "3206131020419630384": { - "error_kind": "fmtstring", - "length": 75, - "item_types": [] - }, - "3305101268118424981": { - "error_kind": "string", - "string": "Attempted to delete past the length of a CapsuleArray" - }, - "3738765135689704617": { - "error_kind": "fmtstring", - "length": 58, - "item_types": [ - { - "kind": "field" - } - ] - }, - "5019202896831570965": { - "error_kind": "string", - "string": "attempt to add with overflow" - }, - "5727012404371710682": { - "error_kind": "string", - "string": "push out of bounds" - }, - "6485997221020871071": { - "error_kind": "string", - "string": "call to assert_max_bit_size" - }, - "7233212735005103307": { - "error_kind": "string", - "string": "attempt to multiply with overflow" - }, - "8270195893599566439": { - "error_kind": "string", - "string": "Invalid public keys hint for address" - }, - "10676044680617262041": { - "error_kind": "fmtstring", - "length": 98, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - }, - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - }, - { - "kind": "field" - } - ] - }, - "11732781666457836689": { - "error_kind": "fmtstring", - "length": 77, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "13649294680379557736": { - "error_kind": "string", - "string": "extend_from_bounded_vec out of bounds" - }, - "14101993474458164081": { - "error_kind": "fmtstring", - "length": 61, - "item_types": [ - { - "kind": "field" - }, - { - "kind": "field" - } - ] - }, - "14225679739041873922": { - "error_kind": "string", - "string": "Index out of bounds" - }, - "14657895983200220173": { - "error_kind": "string", - "string": "Attempted to read past the length of a CapsuleArray" - }, - "15200354114977654233": { - "error_kind": "fmtstring", - "length": 144, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "15760694058516861966": { - "error_kind": "fmtstring", - "length": 128, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "16218014537381711836": { - "error_kind": "string", - "string": "Value does not fit in field" - }, - "16446004518090376065": { - "error_kind": "string", - "string": "Input length must be a multiple of 32" - }, - "16954218183513903507": { - "error_kind": "string", - "string": "Attempted to read past end of BoundedVec" - }, - "17226037485472400844": { - "error_kind": "fmtstring", - "length": 132, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "17610130137239148460": { - "error_kind": "fmtstring", - "length": 98, - "item_types": [] - }, - "17843811134343075018": { - "error_kind": "string", - "string": "Stack too deep" - } - } - }, - "bytecode": "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", - "debug_symbols": "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" - }, - { - "name": "public_dispatch", - "is_unconstrained": true, - "custom_attributes": [ - "public" - ], - "abi": { - "parameters": [ - { - "name": "selector", - "type": { - "kind": "field" - }, - "visibility": "private" - } - ], - "return_type": null, - "error_types": { - "206160798890201757": { - "error_kind": "string", - "string": "Storage slot 0 not allowed. Storage slots must start from 1." - }, - "2024020833944022298": { - "error_kind": "string", - "string": "Function add_to_tally_public can only be called internally" - }, - "2233873454491509486": { - "error_kind": "string", - "string": "Initializer address is not the contract deployer" - }, - "3557153117338734214": { - "error_kind": "string", - "string": "Vote has ended" - }, - "5019202896831570965": { - "error_kind": "string", - "string": "attempt to add with overflow" - }, - "8095637994846897154": { - "error_kind": "string", - "string": "Only admin can end votes" - }, - "10492081608786484886": { - "error_kind": "fmtstring", - "length": 27, - "item_types": [ - { - "kind": "field" - } - ] - }, - "13699457482007836410": { - "error_kind": "string", - "string": "Not initialized" - }, - "14225679739041873922": { - "error_kind": "string", - "string": "Index out of bounds" - }, - "17618083556256589634": { - "error_kind": "string", - "string": "Initialization hash does not match" - }, - "17843811134343075018": { - "error_kind": "string", - "string": "Stack too deep" - } - } - }, - "bytecode": "JwACBAEoAAABBIBOJwAABAMnAgIEAScCAwQAHwoAAgADgE0uCIBNAAElAAAARSUAAACaKAIAAQSATicCAgQAOw4AAgABKACAQwQAAygAgEQBAAAoAIBFBAAAKACARgAAACgAgEcBAAEoAIBIBAABKACASQAAASgAgEoEAAIoAIBLAAADKwCATAAAAAAAAAAAAQAAAAAAAAAAJiUAAAqqKQIAAgA1OT3zCioBAgMnAgQEACcCBgQDACoEBgUtCAECAAgBBQEnAwIEAQAiAgIFLQ4EBQAiBQIFLQ4EBScCBQQDACoCBQQkAgADAAAA8yMAAAZwLQgBAycCBAQCAAgBBAEnAwMEAQAiAwIEHzCASIBIAAQtCAEEAAABAgEtDgMELQgBAwAAAQIBLgyARQADJwIGBActCAAHLQoECC0KAwkACAAGACUAAArTLQIAAC0KCAUBIgAFgEgABC0LBAMeAgAEAC0IAQUnAgYEAwAIAQYBJwMFBAEAIgUCBjYOAAQABgABIgAFgEgABy0LBwYBIgAFgEoACC0LCAccCgYFAAQqBQcIJAIABgAAAbUnAgUEADwGBQEtCAEFJwIGBAMACAEGAScDBQQBACIFAgY2DgAEAAYCASIABYBIAAYtCwYEASIABYBKAActCwcGHAoEBQAEKgUGByQCAAQAAAIHJwIFBAA8BgUBLQgBBCcCBQQCAAgBBQEnAwQEAQAiBAIFHzCASIBFAAUBIgAEgEgABi0LBgUcCgUGBBwKBgQALQgBBScCBgQCAAgBBgEnAwUEAQAiBQIGHzCASIBIAAYnAgYALC0IAQknAgoEAgAIAQoBJwMJBAEAIgkCCi0KCgstDgYLJwIKBAstCAALLQoJDC0KBQ0ACAAKACUAAAswLQIAAC0KDAYnAgkECi0IAAotCgYLLgiASgAMLgiARAANAAgACQAlAAALey0CAAAtCgsFLQgBBicCCQQEAAgBCQEnAwYEAQAiBgIJLQoJCi4MgEYACgAiCgIKLgyARgAKACIKAgouDIBGAAorAgAJAAAAAAAAAAADAAAAAAAAAAAtCAEKJwILBAUACAELAScDCgQBACIKAgstCgsMLgyARgAMACIMAgwuDIBGAAwAIgwCDC4MgEYADAAiDAIMLQ4JDC0IAQkAAAECAS0OBgktCAEGAAABAgEtDgoGLQgBCgAAAQIBLgyARQAKLQgBCwAAAQIBLgyARAALJwIMAA0nAg0EDi0IAA4tCgkPLQoGEC0KChEtCgsSLQoMEwAIAA0AJQAADSotAgAAJwIMBA0tCAANLQoJDi0KBg8tCgoQLQoLES0KBBIACAAMACUAAA0qLQIAACcCBAQMLQgADC0KCQ0tCgYOLQoKDy0KCxAtCgURAAgABAAlAAANKi0CAAAnAgUEDC0IAAwtCgkNLQoGDi0KCg8tCgsQAAgABQAlAAAOSC0CAAAtCg0ECioHBAUkAgAFAAAEWSUAAA68CyIACIBGAAQeAgAFAQoqCAUGEioEBgUkAgAFAAAEfSUAAA7OMAIAA4BJMACARoBLHgIAAwUnAgQABC0IAQUnAgYEAgAIAQYBJwMFBAEAIgUCBi0KBgctDgQHJwIGAAYtCAEHJwIIBAIACAEIAScDBwQBACIHAggtCggJLQ4GCScCCAQJLQgACS0KBwotCgULAAgACAAlAAALMC0CAAAtCgoGJwIHBAgtCAAILQoGCS4IgEoACi4IgEQACwAIAAcAJQAAC3stAgAALQoJBTQCAAUcCgMFAC0IAQMnAgYEBAAIAQYBJwMDBAEAIgMCBi0KBgcuDIBGAAcAIgcCBy4MgEYABwAiBwIHLgyARgAHLQgBBicCBwQFAAgBBwEnAwYEAQAiBgIHLQoHCC4MgEYACAAiCAIILgyARgAIACIIAgguDIBGAAgAIggCCC4MgEwACC0IAQcAAAECAS0OAwctCAEDAAABAgEtDgYDLQgBBgAAAQIBLgyARQAGLQgBCAAAAQIBLgyARAAIJwIJBAotCAAKLQoHCy0KAwwtCgYNLQoIDi0KBQ8ACAAJACUAAA0qLQIAACcCCgQLLQgACy0KBwwtCgMNLQoGDi0KCA8ACAAKACUAAA5ILQIAAC0KDAkwCgAFAAQnAgMABTAKAAkAAx4CAAMANAIAAwAiAgIFLQsFBCcCBgQCACoFBgM7DgAEAAMjAAAGcCkCAAMAXwZhfgoqAQMELQsCAwAiAwIDLQ4DAiQCAAQAAAaYIwAACI4tCAEDJwIEBAIACAEEAScDAwQBACIDAgQfMIBIgEgABC0IAQQAAAECAS0OAwQtCAEDAAABAgEuDIBFAAMnAgYEBy0IAActCgQILQoDCQAIAAYAJQAACtMtAgAALQoIBQEiAAWASAAELQsEAx4CAAQAHgIABQAzKgAEAAUABiQCAAYAAAciJQAADuAeAgAEAR4CAAUACioEBQYkAgAGAAAHPiUAAA7yLwiASwAEHAoEBgEcCgYFABwKBQQBCyIABIBEAAUkAgAFAAAHaCUAAA8EJwIEAAItCAEFJwIGBAMACAEGAScDBQQBACIFAgYtCgYHLQ4EBwAiBwIHLQ4DBycCBwQILQgACC0KBQkuCIBKAAouCIBEAAsACAAHACUAAA8WLQIAAC0KCQYLIgAGgEYABQsiAAWARAAHJAIABwAAB94lAAAQxS8KAAYABQEiAAWASQAGLQgBBScCBwQDAAgBBwEnAwUEAQAiBQIHLQoHCC0OBAgAIggCCC0OAwgnAgQEBy0IAActCgUILgiASgAJLgiARAAKAAgABAAlAAAPFi0CAAAtCggDCyIAA4BGAAQLIgAEgEQABSQCAAUAAAhdJQAAEMUwCgAGAAMtCwIDACIDAgMtDgMCACICAgUtCwUEJwIGBAIAKgUGAzsOAAQAAyMAAAiOKQIAAwDyGfv/CioBAwQkAgAEAAAIqSMAAAjeJwIDBAQtCAAEAAgAAwAlAAAQ1y0CAAAAIgICBS0LBQQnAgYEAgAqBQYDOw4ABAADIwAACN4nAgICVScCAwJuJwIEAmsnAgUCbycCBgJ3JwIHAiAnAggCcycCCQJlJwIKAmwnAgsCYycCDAJ0JwINAnInAg4CeycCDwJ9LQgBECcCEQQcAAgBEQEnAxAEAQAiEAIRLQoREi0OAhIAIhICEi0OAxIAIhICEi0OBBIAIhICEi0OAxIAIhICEi0OBRIAIhICEi0OBhIAIhICEi0OAxIAIhICEi0OBxIAIhICEi0OCBIAIhICEi0OCRIAIhICEi0OChIAIhICEi0OCRIAIhICEi0OCxIAIhICEi0ODBIAIhICEi0OBRIAIhICEi0ODRIAIhICEi0OBxIAIhICEi0ODhIAIhICEi0OCBIAIhICEi0OCRIAIhICEi0OChIAIhICEi0OCRIAIhICEi0OCxIAIhICEi0ODBIAIhICEi0OBRIAIhICEi0ODRIAIhICEi0ODxILIIBEgEcAAiQCAAIAAAqqJwIDBB4tCAEEJwIFBB4ACAEFAS0KBAUqAwAFBZGbXKI+IJ6WACIFAgUAIhACBicCBwQbLgIABoADLgIABYAELgIAB4AFJQAAER8nAgYEGwAqBQYFLgyASQAFACIFAgUtDgEFACIFAgU8DgMEKACABAR4AA0AAACABIADJACAAwAACtIqAQABBfeh86+lrdTKPAQCASYlAAAKqi0LAgMtCwEECyIAA4BFAAUkAgAFAAAK9SUAABFlASIABIBIAAUtCwUDLQgBBScCBgQCAAgBBgEnAwUEAQAiBQIGLQoGBy0OAwctDgQBLgyASAACLQoFASYlAAAKqgEiAAGASAAELQsEAwEiAAKASAAELQsEAS0IAQInAgQEAwAIAQQBJwMCBAEAIgICBC0KBAUtDgMFACIFAgUtDgEFLQoCASYlAAAKqhwKAgUABSIABYBMAAYtCAEFJwIHBAQACAEHAScDBQQBACIFAgctCgcILgyARgAIACIIAgguDIBGAAgAIggCCC4MgEYACC0IAQcnAggEBQAIAQgBJwMHBAEAIgcCCC0KCAkuDIBGAAkAIgkCCS4MgEYACQAiCQIJLgyARgAJACIJAgktDgYJLQgBBgAAAQIBLQ4FBi0IAQUAAAECAS0OBwUtCAEHAAABAgEuDIBFAActCAEIAAABAgEuDIBEAAguCIBFAAQjAAAMSQ0iAASASgAJJAIACQAADMkjAAAMXiQCAAMAAAxrIwAADJ0nAgEECS0IAAktCgYKLQoFCy0KBwwtCggNLgiASQAOAAgAAQAlAAANKi0CAAAjAAAMnScCAgQJLQgACS0KBgotCgULLQoHDC0KCA0ACAACACUAAA5ILQIAAC0KCgEmDCoEAgkkAgAJAAAM2yMAAA0ZACIBAgoAKgoECy0LCwknAgoECy0IAAstCgYMLQoFDS0KBw4tCggPLQoJEAAIAAoAJQAADSotAgAAIwAADRkBIgAEgEgACS0KCQQjAAAMSSUAAAqqLQsEBgsiAAaARAAHJAIABwAADUwnAggEADwGCAEtCwMGCyIABoBDAAckAgAHAAAN2SMAAA1lLQsBBy0LAggNIgAGgEMACSQCAAkAAA2CJQAAEWUuAgAHgAMoAIAEBAAEJQAAEXcuCIAFAAkAIgkCCgAqCgYLLQ4FCwEiAAaASAAFDioGBQckAgAHAAANwiUAABIFLQ4JAS0OCAItDgUDLgyARAAEIwAADkcnAgYEBy0IAActCgEILQoCCS0KAwotCgQLAAgABgAlAAASFy0CAAAtCwEGLQsCBy0LBAguAgAGgAMoAIAEBAAEJQAAEXcuCIAFAAkBIgAJgEgACi0OBQotDgkBLQ4HAi4MgEgAAy0OCAQjAAAORyYlAAAKqi0LBAULIgAFgEQABiQCAAYAAA5qJwIHBAA8BgcBJwIFBAYtCAAGLQoBBy0KAggtCgMJLQoECgAIAAUAJQAAEhctAgAALQsBBS0LAgYtCwMHLQ4FAS0OBgItDgcDLgyARwAEASIABoBIAAItCwIBJioBAAEF9IABplnTJ0I8BAIBJioBAAEFHwBQEkAkIu48BAIBJioBAAEFvh4//z6k9vo8BAIBJioBAAEFHBbEOYk5LRo8BAIBJioBAAEFMV2L6eKmDoY8BAIBJiUAAAqqHAoCBQAFIgAFgEwABi0IAQUnAgcEBAAIAQcBJwMFBAEAIgUCBy0KBwguDIBGAAgAIggCCC4MgEYACAAiCAIILgyARgAILQgBBycCCAQFAAgBCAEnAwcEAQAiBwIILQoICS4MgEYACQAiCQIJLgyARgAJACIJAgkuDIBGAAkAIgkCCS0OBgktCAEGAAABAgEtDgUGLQgBBQAAAQIBLQ4HBS0IAQcAAAECAS4MgEUABy0IAQgAAAECAS4MgEQACC4IgEUABCMAAA/kDSIABIBKAAkkAgAJAAAQZCMAAA/5JAIAAwAAEAYjAAAQOCcCAQQJLQgACS0KBgotCgULLQoHDC0KCA0uCIBJAA4ACAABACUAAA0qLQIAACMAABA4JwICBAktCAAJLQoGCi0KBQstCgcMLQoIDQAIAAIAJQAADkgtAgAALQoKASYMKgQCCSQCAAkAABB2IwAAELQAIgECCgAqCgQLLQsLCScCCgQLLQgACy0KBgwtCgUNLQoHDi0KCA8tCgkQAAgACgAlAAANKi0CAAAjAAAQtAEiAASASAAJLQoJBCMAAA/kKgEAAQUC3G4ngHYSnTwEAgEmJQAACqoeAgABAB4CAAIAMyoAAQACAAMkAgADAAAQ+yUAAA7gLwiASQABHgIAAgEKKgECAyQCAAMAABEYJQAAEyEwAIBJgEsmAQCAA4AFgAcuAIADgAguAIAEgAkLAIAIgAeACiQAgAoAABFkLgGACIAGLgSABoAJAQCACAACgAgBAIAJAAKACSMAABEzJioBAAEFxWvEWg4QAAI8BAIBJi4BgAOABgsAgAYAAoAHJACABwAAEZIjAAARnS4AgAOABSMAABIELgAAAYAFAQAAAYAEAAEBAIADgASACS4AgAOACi4AgAWACwsAgAqACYAMJACADAAAEfAuAYAKgAguBIAIgAsBAIAKAAKACgEAgAsAAoALIwAAEb8oAYAFBAABAwCABgACgAYjAAASBCYqAQABBUWnynEZQeQVPAQCASYlAAAKqi4IgEUABSMAABInDSIABYBDAAYkAgAGAAASkiMAABI8LQsCBS0LBQYAIgYCBi0OBgUtCAEGJwIHBAUACAEHAScDBgQBACIFAgcnAggEBAAiBgIJPw8ABwAJLQsBBS0LAwctCwQILQ4FAS0OBgItDgcDLQ4IBCYtCwMGDCoFBgckAgAHAAASqCMAABMQLQsCBwAiBwIJACoJBQotCwoILQsBCQAiCQILACoLBQwtCwwKACoICgstCwQILgIAB4ADKACABAQABSUAABF3LgiABQAKACIKAgwAKgwFDS0OCw0tDgkBLQ4KAi0OBgMtDggEIwAAExABIgAFgEgABi0KBgUjAAASJyoBAAEFcFl73SEBRAI8BAIBJg==", - "debug_symbols": "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" - }, - { - "name": "sync_private_state", - "is_unconstrained": true, - "custom_attributes": [ - "utility" - ], - "abi": { - "parameters": [], - "return_type": null, - "error_types": { - "576755928210959028": { - "error_kind": "string", - "string": "0 has a square root; you cannot claim it is not square" - }, - "1004672304334401604": { - "error_kind": "fmtstring", - "length": 48, - "item_types": [ - { - "kind": "field" - }, - { - "kind": "field" - } - ] - }, - "2920182694213909827": { - "error_kind": "string", - "string": "attempt to subtract with overflow" - }, - "3206131020419630384": { - "error_kind": "fmtstring", - "length": 75, - "item_types": [] - }, - "3305101268118424981": { - "error_kind": "string", - "string": "Attempted to delete past the length of a CapsuleArray" - }, - "3738765135689704617": { - "error_kind": "fmtstring", - "length": 58, - "item_types": [ - { - "kind": "field" - } - ] - }, - "5019202896831570965": { - "error_kind": "string", - "string": "attempt to add with overflow" - }, - "5727012404371710682": { - "error_kind": "string", - "string": "push out of bounds" - }, - "6485997221020871071": { - "error_kind": "string", - "string": "call to assert_max_bit_size" - }, - "7233212735005103307": { - "error_kind": "string", - "string": "attempt to multiply with overflow" - }, - "8270195893599566439": { - "error_kind": "string", - "string": "Invalid public keys hint for address" - }, - "10676044680617262041": { - "error_kind": "fmtstring", - "length": 98, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - }, - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - }, - { - "kind": "field" - } - ] - }, - "11732781666457836689": { - "error_kind": "fmtstring", - "length": 77, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "13649294680379557736": { - "error_kind": "string", - "string": "extend_from_bounded_vec out of bounds" - }, - "14101993474458164081": { - "error_kind": "fmtstring", - "length": 61, - "item_types": [ - { - "kind": "field" - }, - { - "kind": "field" - } - ] - }, - "14225679739041873922": { - "error_kind": "string", - "string": "Index out of bounds" - }, - "14657895983200220173": { - "error_kind": "string", - "string": "Attempted to read past the length of a CapsuleArray" - }, - "15200354114977654233": { - "error_kind": "fmtstring", - "length": 144, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "15760694058516861966": { - "error_kind": "fmtstring", - "length": 128, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "16218014537381711836": { - "error_kind": "string", - "string": "Value does not fit in field" - }, - "16446004518090376065": { - "error_kind": "string", - "string": "Input length must be a multiple of 32" - }, - "16954218183513903507": { - "error_kind": "string", - "string": "Attempted to read past end of BoundedVec" - }, - "17226037485472400844": { - "error_kind": "fmtstring", - "length": 132, - "item_types": [ - { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - ] - }, - "17610130137239148460": { - "error_kind": "fmtstring", - "length": 98, - "item_types": [] - }, - "17843811134343075018": { - "error_kind": "string", - "string": "Stack too deep" - } - } - }, - "bytecode": "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", - "debug_symbols": "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us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d56PrfHSdj67z0XU+us5H1/noOh9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XU+u85n1/nsOp9d57PrfHadz67z2XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrfHWdr67z1XW+us5X1/nqOl9d56vrPDuTztevnK1Jj0bTbFpNu8mavOk03ab2uO1x2+O2x22P2x63PW573Pa47XHbI9oj2iPaI9oj2iPaI9oj2iPaI8ojG5cejabZtJp2kzV502m6Te0x2mO0x2iP0R6jPUZ7jPYY7THaY7THbI/ZHrM9ZnvM9pjtMdtjtsdsj9keqz1We6z2WO2x2mO1x2qP1R6rPVZ77PbY7bHbY7fHbo/dHrs9dnvs9tjtYe1h7WHtYe1h7WHtYe1h7WHtYe3h7eHt4e3h7eHt4e3h7eHt4e3Rdb67znfX+e46313n2QJ1PMmavOk03aYoyjoHjabZ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bbptumWWLEuMxsySh4M4iYu4iUZ04iHSzejmdHO6Od2cbk43p5vTzenmdHO6Hboduh26Hboduh26Hboduh26Hbpdul26Xbpdul26Xbpdul26XbpdugXdgm5Bt6Bb0C3oFnQLugXdot3Q9/pwECdxETfRiE48xEuk26DboNug26DboNug26DboNug26DbpNuk26TbpNuk26TbpNuk26TbpNui26Lbotui26Lbotui26Lbotui26bbptum26bbptum26bbphuz5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMkuCWRLMkmCWBLMkmCXBLAlmSTBLglkSzJJglgSzJJglwSwJZkkwS4JZEsySYJYEsySYJcEsCWZJMEuCWRLMEvS9rpN4iJcYjcgS4CBO4iJuohHptui26Lbotum26bbptum26bbptum26bbptulmdDO6Gd2MbkY3o5vRzehmdDO6Od2cbk43p5vTzenmdHO6Od2cboduh26Hboduh26Hboduh26Hbodul26Xbpdul26Xbpdul26ZJd9fupvoe30YjZkl+YfL0Pf6cBIXcRON6MRDvMR4uND3+nAQJ3ERN9GITjzES6TboNug26DboNug26DboNug26DboNuk26TbpNuk26TbpNuk26TbpNuk26Lbotui26Lbotui26Lbotui26Lbptum26bbptum26bbptum26bbppvRzehmdDO6Gd2MbkY3o5vRzejmdHO6Od2cbk43p5vTzenmdHO6Hboduh26Hboduh26Hboduh26Hbpdul26Xbpdul26Xbpdul26XbpdugXdgm5Bt6Bb0C3oFnQLugXdmCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglg1kymCWDWTKYJYNZMpglk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZMpklk1kymSWTWTKZJZNZgr7X7y/5LvS9PhzEdLuJi7iJRnTiIV5iNCJLgINIt0M3ZMlMNKITD/ESoxFZAhzESVxEul26Xbpdul26XboF3YJuQbegW9At6BZ0C7oF3aLd0Pf6cBAncRE30YhOPMRLpNug26DboNug26DboNug26DboNug26TbpNuk26TbpNuk26RbZkn+XWT0vT6MxsyS93eOB3ES0y0SN9GITjzES4xGZAlwECeRbptum26bbptum26bbkY3o5vRzehmdDO6Gd2MbkY3o5vTzenmdHO6Od2cbk43p5vTzel26Hboduh26Hboduh26Hboduh26Hbpdul26Xbpdul26Xbpdul26XbpFnQLugXdgm5Bt6Bb0C3oFnSLdkPf68NBnMRF3EQjOvEQL5Fug26DboNug26DboNug26DboNug26TbpNuk26Tbrj3uhON6MRDvMRoxL1X4CBO4iLSbdFt0W3RbdFt0W3TbdNt023TbdNt023TbdNt023TzehmdDO6Gd2MbkY3o5vRzehmdHO6Od2cbk43p5vTzenmdHO6Od0O3Q7dDt0O3Q7dDt0O3Q7dDt0O3S7dLt0u3S7dLt0u3S7dLt0u3S7dgm5Bt6Bb0C3oFnQLugXdgm7Rbuh7fTiIk7iIm2hEJx7iJdJt0G3QbdBt0G3QLbPER6ITD/Fz85UYjZklDwdxEhdxE43oxEOk26Tbotui26Lbotui26Lbotui26Lbotum26bbptum26bbptum26bbptumm9HN6GZ0M7oZ3YxuRjejm9HN6OZ0c7o53ZxuTjenm9PN6eZ0c7oduh26Hboduh26Hboduh26Hbodul26Xbpdul26Xbpdul26Xbpdul26Bd2CbkG3oFvQLegWdAu6Bd2i3dD3+nAQJ3ERN9GITjzES6TboNug26DboNug26DboNugG7PEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmiTNLnFnizBJnljizxJklzixxZokzS5xZ4swSZ5Y4s8SZJc4scWaJM0ucWeLMEmeWOLPEmSXOLHFmiTNLnFnizBJnljizxJklh1lymCWHWXKYJYdZcpglh1lymCWHWXKYJYdZcpglh1lymCWHWXKYJYdZcpglh1lymCXoe/WTOIiTuIibaEQnHuIlRuOi26Lbotui26JbZsmxRCceYrrNxGhElgAHcRIXcRON6MRDpNumm9HN6GZ0M7oZ3YxuRjejm9HN6OZ0c7o53ZxuTjenm9PN6eZ0c7oduh26Hboduh26Hboduh26Hbodul26Xbpdul26Xbpdul26Xbpdul26Bd2CbkG3oFvQLegWdAu6Bd2i3dD3+nAQJ3ERN9GITjzES6TboNug26DboNug26DboNug26DboNuk26TbpNuk26TbpNuk26TbpNuk26Lbotui26Lbotui26Lbohuz5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrPkMksus+QySy6z5DJLLrMEfa83MbPk4SB+bnclLuImfm7fO9wX+l4fHuLndiMxGjNLHg7iJC7iJhrRiYdIt0O3S7dLt8ySsMRF3MQ/t7+nq4lOPMT7Ya7DlyUPvywpHB+exElcxE00ohMP8RKjMPteCwdxEhdxE43oxEO8RLoNug26DboNug26DboNug26DboNuk26TbpNuk26TbpNuk26TbpNuk26Lbotui26Lbotui26Lbotui26Lbptum26bbptum26bbptum26bbptuhndjG5GN6Ob0c3oZnQzuhndjG5ON6eb083p5nRzujndnG5ON6fboduh26Hboduh26Hboduh26Hbodul26Xbpdul26Xbpdul26XbpdulW9CNWRLMkmCWBLMkmCXBLAlmSTBLorNk/zpL9q+zZP86S/avs2T/Okv2r7Nk/zpL9q+zZP86S/bvR7dBt0G3QbdBt0G3QbdBt0G3QbdBt0m3SbdJt0m3SbdJ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" - } - ], - "outputs": { - "globals": { - "storage": [ - { - "fields": [ - { - "name": "contract_name", - "value": { - "kind": "string", - "value": "PrivateVoting" - } - }, - { - "name": "fields", - "value": { - "fields": [ - { - "name": "admin", - "value": { - "fields": [ - { - "name": "slot", - "value": { - "kind": "integer", - "sign": false, - "value": "0000000000000000000000000000000000000000000000000000000000000001" - } - } - ], - "kind": "struct" - } - }, - { - "name": "tally", - "value": { - "fields": [ - { - "name": "slot", - "value": { - "kind": "integer", - "sign": false, - "value": "0000000000000000000000000000000000000000000000000000000000000002" - } - } - ], - "kind": "struct" - } - }, - { - "name": "vote_ended", - "value": { - "fields": [ - { - "name": "slot", - "value": { - "kind": "integer", - "sign": false, - "value": "0000000000000000000000000000000000000000000000000000000000000003" - } - } - ], - "kind": "struct" - } - }, - { - "name": "active_at_block", - "value": { - "fields": [ - { - "name": "slot", - "value": { - "kind": "integer", - "sign": false, - "value": "0000000000000000000000000000000000000000000000000000000000000004" - } - } - ], - "kind": "struct" - } - } - ], - "kind": "struct" - } - } - ], - "kind": "struct" - } - ] - }, - "structs": { - "functions": [ - { - "fields": [ - { - "name": "parameters", - "type": { - "fields": [ - { - "name": "candidate", - "type": { - "kind": "field" - } - } - ], - "kind": "struct", - "path": "PrivateVoting::add_to_tally_public_parameters" - } - } - ], - "kind": "struct", - "path": "PrivateVoting::add_to_tally_public_abi" - }, - { - "fields": [ - { - "name": "parameters", - "type": { - "fields": [ - { - "name": "candidate", - "type": { - "kind": "field" - } - } - ], - "kind": "struct", - "path": "PrivateVoting::cast_vote_parameters" - } - } - ], - "kind": "struct", - "path": "PrivateVoting::cast_vote_abi" - }, - { - "fields": [ - { - "name": "parameters", - "type": { - "fields": [ - { - "name": "admin", - "type": { - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ], - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress" - } - } - ], - "kind": "struct", - "path": "PrivateVoting::constructor_parameters" - } - } - ], - "kind": "struct", - "path": "PrivateVoting::constructor_abi" - }, - { - "fields": [ - { - "name": "parameters", - "type": { - "fields": [], - "kind": "struct", - "path": "PrivateVoting::end_vote_parameters" - } - } - ], - "kind": "struct", - "path": "PrivateVoting::end_vote_abi" - }, - { - "fields": [ - { - "name": "parameters", - "type": { - "fields": [ - { - "name": "candidate", - "type": { - "kind": "field" - } - } - ], - "kind": "struct", - "path": "PrivateVoting::get_vote_parameters" - } - }, - { - "name": "return_type", - "type": { - "kind": "field" - } - } - ], - "kind": "struct", - "path": "PrivateVoting::get_vote_abi" - }, - { - "fields": [ - { - "name": "parameters", - "type": { - "fields": [ - { - "name": "message_ciphertext", - "type": { - "fields": [ - { - "name": "storage", - "type": { - "kind": "array", - "length": 17, - "type": { - "kind": "field" - } - } - }, - { - "name": "len", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ], - "kind": "struct", - "path": "std::collections::bounded_vec::BoundedVec" - } - }, - { - "name": "message_context", - "type": { - "fields": [ - { - "name": "tx_hash", - "type": { - "kind": "field" - } - }, - { - "name": "unique_note_hashes_in_tx", - "type": { - "fields": [ - { - "name": "storage", - "type": { - "kind": "array", - "length": 64, - "type": { - "kind": "field" - } - } - }, - { - "name": "len", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ], - "kind": "struct", - "path": "std::collections::bounded_vec::BoundedVec" - } - }, - { - "name": "first_nullifier_in_tx", - "type": { - "kind": "field" - } - }, - { - "name": "recipient", - "type": { - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ], - "kind": "struct", - "path": "aztec::protocol_types::address::aztec_address::AztecAddress" - } - } - ], - "kind": "struct", - "path": "aztec::messages::processing::message_context::MessageContext" - } - } - ], - "kind": "struct", - "path": "PrivateVoting::process_message_parameters" - } - } - ], - "kind": "struct", - "path": "PrivateVoting::process_message_abi" - }, - { - "fields": [ - { - "name": "parameters", - "type": { - "fields": [], - "kind": "struct", - "path": "PrivateVoting::sync_private_state_parameters" - } - } - ], - "kind": "struct", - "path": "PrivateVoting::sync_private_state_abi" - } - ] - } - }, - "file_map": { - "102": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/macros/functions/initialization_utils.nr", - "source": "use dep::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::GENERATOR_INDEX__CONSTRUCTOR, hash::poseidon2_hash_with_separator, traits::ToField,\n};\n\nuse crate::{\n context::{PrivateContext, PublicContext},\n oracle::get_contract_instance::{\n get_contract_instance, get_contract_instance_deployer_avm,\n get_contract_instance_initialization_hash_avm,\n },\n};\n\npub fn mark_as_initialized_public(context: &mut PublicContext) {\n let init_nullifier =\n compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_nullifier(init_nullifier);\n}\n\npub fn mark_as_initialized_private(context: &mut PrivateContext) {\n let init_nullifier =\n compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_nullifier(init_nullifier);\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_unsiloed_contract_initialization_nullifier(context.this_address());\n context.push_nullifier_read_request(init_nullifier);\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 deployer = get_contract_instance_deployer_avm(address).unwrap();\n let initialization_hash = get_contract_instance_initialization_hash_avm(address).unwrap();\n let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash());\n assert(initialization_hash == expected_init, \"Initialization hash does not match\");\n assert(\n (deployer.is_zero()) | (deployer == context.msg_sender()),\n \"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()),\n \"Initializer address is not the contract deployer\",\n );\n}\n\n/// This function is not only used in macros but it's also used by external people to check that an instance has been\n/// initialized with the correct constructor arguments. Don't hide this unless you implement factory functionality.\npub fn compute_initialization_hash(\n init_selector: FunctionSelector,\n init_args_hash: Field,\n) -> Field {\n poseidon2_hash_with_separator(\n [init_selector.to_field(), init_args_hash],\n GENERATOR_INDEX__CONSTRUCTOR,\n )\n}\n" - }, - "105": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/macros/functions/utils.nr", - "source": "use crate::macros::{\n functions::{\n auth_registry::AUTHORIZE_ONCE_REGISTRY, call_interface_stubs::stub_fn, stub_registry,\n },\n notes::NOTES,\n utils::{\n add_to_hasher, fn_has_authorize_once, fn_has_noinitcheck, get_fn_visibility,\n is_fn_contract_library_method, is_fn_initializer, is_fn_internal, is_fn_private,\n is_fn_public, is_fn_test, is_fn_utility, is_fn_view, modify_fn_body, module_has_initializer,\n module_has_storage,\n },\n};\nuse std::meta::{ctstring::AsCtString, type_of};\n\npub(crate) comptime fn transform_private(f: FunctionDefinition) {\n let fn_stub = stub_fn(f);\n stub_registry::register(f.module(), fn_stub);\n\n let module_has_initializer = module_has_initializer(f.module());\n let module_has_storage = module_has_storage(f.module());\n\n // Private functions undergo a lot of transformations from their Aztec.nr form into a circuit that can be fed to the\n // Private Kernel Circuit.\n // First we change the function signature so that it also receives `PrivateContextInputs`, which contain information\n // about the execution context (e.g. the caller).\n let original_params = f.parameters();\n f.set_parameters(&[(\n quote { inputs },\n quote { crate::context::inputs::private_context_inputs::PrivateContextInputs }.as_type(),\n )]\n .append(original_params));\n\n let mut body = f.body().as_block().unwrap();\n\n // The original params are hashed and passed to the `context` object, so that the kernel can verify we've received\n // the correct values.\n // TODO: Optimize args_hasher for small number of arguments\n let args_hasher_name = quote { args_hasher };\n let args_hasher = original_params.fold(\n quote {\n let mut $args_hasher_name = dep::aztec::hash::ArgsHasher::new();\n },\n |args_hasher, param: (Quoted, Type)| {\n let (name, typ) = param;\n let appended_arg = add_to_hasher(args_hasher_name, name, typ);\n quote {\n $args_hasher\n $appended_arg\n }\n },\n );\n\n let context_creation = quote {\n let mut context = dep::aztec::context::private_context::PrivateContext::new(inputs, dep::aztec::protocol_types::traits::Hash::hash($args_hasher_name));\n };\n\n // Modifications introduced by the different marker attributes.\n let internal_check = if is_fn_internal(f) {\n create_internal_check(f)\n } else {\n quote {}\n };\n\n let view_check = if is_fn_view(f) {\n create_view_check(f)\n } else {\n quote {}\n };\n\n let (assert_initializer, mark_as_initialized) = if is_fn_initializer(f) {\n (create_assert_correct_initializer_args(f), create_mark_as_initialized(f))\n } else {\n (quote {}, quote {})\n };\n\n let storage_init = if module_has_storage {\n quote {\n // Some functions don't access storage, but it'd be quite difficult to only inject this variable if it is\n // referenced. We instead ignore 'unused variable' warnings for it.\n #[allow(unused_variables)]\n let storage = Storage::init(&mut context);\n }\n } else {\n quote {}\n };\n\n // Initialization checks are not included in contracts that don't have initializers.\n let init_check = if module_has_initializer & !is_fn_initializer(f) & !fn_has_noinitcheck(f) {\n create_init_check(f)\n } else {\n quote {}\n };\n\n // All private functions perform message discovery, since they may need to access notes. This is slightly\n // inefficient and could be improved by only doing it once we actually attempt to read any. Note that the message\n // discovery call syncs private events as well. We do not sync those here if there are no notes because we don't\n // have an API that would access events from private functions.\n let message_discovery_call = if NOTES.len() > 0 {\n create_message_discovery_call()\n } else {\n quote {}\n };\n\n // Inject the authwit check if the function is marked with #[authorize_once].\n let authorize_once_check = if fn_has_authorize_once(f) {\n create_authorize_once_check(f)\n } else {\n quote {}\n };\n\n // Finally, we need to change the return type to be `PrivateCircuitPublicInputs`, which is what the Private Kernel\n // circuit expects.\n let return_value_var_name = quote { macro__returned__values };\n\n let return_value_type = f.return_type();\n let return_value = if body.len() == 0 {\n quote {}\n } else if return_value_type != type_of(()) {\n // The original return value is passed to a second args hasher which the context receives.\n let (body_without_return, last_body_expr) = body.pop_back();\n let return_value = last_body_expr.quoted();\n let return_value_assignment =\n quote { let $return_value_var_name: $return_value_type = $return_value; };\n let return_hasher_name = quote { return_hasher };\n let return_value_into_hasher =\n add_to_hasher(return_hasher_name, return_value_var_name, return_value_type);\n\n body = body_without_return;\n\n quote {\n let mut $return_hasher_name = dep::aztec::hash::ArgsHasher::new();\n $return_value_assignment\n $return_value_into_hasher\n context.set_return_hash($return_hasher_name);\n }\n } else {\n let (body_without_return, last_body_expr) = body.pop_back();\n if !last_body_expr.has_semicolon()\n & last_body_expr.as_for().is_none()\n & last_body_expr.as_assert().is_none()\n & last_body_expr.as_for_range().is_none()\n & last_body_expr.as_assert_eq().is_none()\n & last_body_expr.as_let().is_none() {\n let unused_return_value_name = f\"_{return_value_var_name}\".quoted_contents();\n body = body_without_return.push_back(\n quote { let $unused_return_value_name = $last_body_expr; }.as_expr().unwrap(),\n );\n }\n quote {}\n };\n\n let context_finish = quote { context.finish() };\n\n // A quote to be injected at the beginning of the function body.\n let to_prepend = quote {\n dep::aztec::oracle::version::assert_compatible_oracle_version();\n $args_hasher\n $context_creation\n $assert_initializer\n $init_check\n $internal_check\n $view_check\n $storage_init\n $message_discovery_call\n $authorize_once_check\n };\n\n let to_append = quote {\n $return_value\n $mark_as_initialized\n $context_finish\n };\n let modified_body = modify_fn_body(body, to_prepend, to_append);\n f.set_body(modified_body);\n f.set_return_type(\n quote { dep::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs }\n .as_type(),\n );\n f.set_return_data();\n}\n\npub(crate) comptime fn transform_public(f: FunctionDefinition) {\n let fn_stub = stub_fn(f);\n stub_registry::register(f.module(), fn_stub);\n\n let module_has_initializer = module_has_initializer(f.module());\n let module_has_storage = module_has_storage(f.module());\n\n // Public functions undergo a lot of transformations from their Aztec.nr form.\n let original_params = f.parameters();\n\n let args_len_quote = if original_params.len() == 0 {\n // If the function has no parameters, we set the args_len to 0.\n quote { 0 }\n } else {\n // The following will give us ::N + ::N + ...\n original_params\n .map(|(_, param_type): (Quoted, Type)| {\n quote {\n <$param_type as $crate::protocol_types::traits::Serialize>::N\n }\n })\n .join(quote {+})\n };\n\n // Unlike in the private case, in public the `context` does not need to receive the hash of the original params.\n let context_creation = quote {\n let mut context = dep::aztec::context::public_context::PublicContext::new(|| {\n // We start from 1 because we skip the selector for the dispatch function.\n let serialized_args : [Field; $args_len_quote] = dep::aztec::context::public_context::calldata_copy(1, $args_len_quote);\n dep::aztec::hash::hash_args_array(serialized_args)\n });\n };\n\n // Modifications introduced by the different marker attributes.\n let internal_check = if is_fn_internal(f) {\n create_internal_check(f)\n } else {\n quote {}\n };\n\n let view_check = if is_fn_view(f) {\n create_view_check(f)\n } else {\n quote {}\n };\n\n let (assert_initializer, mark_as_initialized) = if is_fn_initializer(f) {\n (create_assert_correct_initializer_args(f), create_mark_as_initialized(f))\n } else {\n (quote {}, quote {})\n };\n\n let storage_init = if module_has_storage {\n // Some functions don't access storage, but it'd be quite difficult to only inject this variable if it is\n // referenced. We instead ignore 'unused variable' warnings for it.\n quote {\n #[allow(unused_variables)]\n let storage = Storage::init(&mut context);\n }\n } else {\n quote {}\n };\n\n // Initialization checks are not included in contracts that don't have initializers.\n let init_check = if module_has_initializer & !fn_has_noinitcheck(f) & !is_fn_initializer(f) {\n create_init_check(f)\n } else {\n quote {}\n };\n\n // Inject the authwit check if the function is marked with #[authorize_once].\n let authorize_once_check = if fn_has_authorize_once(f) {\n create_authorize_once_check(f)\n } else {\n quote {}\n };\n\n let to_prepend = quote {\n $context_creation\n $assert_initializer\n $init_check\n $internal_check\n $view_check\n $storage_init\n $authorize_once_check\n };\n\n let to_append = quote {\n $mark_as_initialized\n };\n\n let body = f.body().as_block().unwrap();\n let modified_body = modify_fn_body(body, to_prepend, to_append);\n f.set_body(modified_body);\n\n // All public functions are automatically made unconstrained, even if they were not marked as such. This is because\n // instead of compiling into a circuit, they will compile to bytecode that will be later transpiled into AVM\n // bytecode.\n f.set_unconstrained(true);\n f.set_return_public(true);\n}\n\npub(crate) comptime fn transform_utility(f: FunctionDefinition) {\n let fn_stub = stub_fn(f);\n stub_registry::register(f.module(), fn_stub);\n\n // Create utility context\n let context_creation =\n quote { let mut context = dep::aztec::context::utility_context::UtilityContext::new(); };\n let module_has_storage = module_has_storage(f.module());\n\n // Initialize Storage if module has storage\n let storage_init = if module_has_storage {\n quote {\n // Some functions don't access storage, but it'd be quite difficult to only inject this variable if it is\n // referenced. We instead ignore 'unused variable' warnings for it.\n #[allow(unused_variables)]\n let storage = Storage::init(context);\n }\n } else {\n quote {}\n };\n\n // All utility functions perform message discovery, since they may need to access private notes that would be\n // found during this process or they may be used to sync private events from TypeScript\n // (`sync_private_state` function gets invoked by PXE::getPrivateEvents function).\n let message_discovery_call = create_message_discovery_call();\n\n // A quote to be injected at the beginning of the function body.\n let to_prepend = quote {\n dep::aztec::oracle::version::assert_compatible_oracle_version();\n $context_creation\n $storage_init\n $message_discovery_call\n };\n let body = f.body().as_block().unwrap();\n let modified_body = modify_fn_body(body, to_prepend, quote {});\n f.set_body(modified_body);\n\n f.set_return_public(true);\n}\n\ncomptime fn create_internal_check(f: FunctionDefinition) -> Quoted {\n let name = f.name();\n let assertion_message = f\"Function {name} can only be called internally\";\n quote { assert(context.msg_sender() == context.this_address(), $assertion_message); }\n}\n\ncomptime fn create_view_check(f: FunctionDefinition) -> Quoted {\n let name = f.name();\n let assertion_message = f\"Function {name} can only be called statically\";\n if is_fn_private(f) {\n // Here `context` is of type context::PrivateContext\n quote { assert(context.inputs.call_context.is_static_call, $assertion_message); }\n } else {\n // Here `context` is of type context::PublicContext\n quote { assert(context.is_static_call(), $assertion_message); }\n }\n}\n\ncomptime fn create_assert_correct_initializer_args(f: FunctionDefinition) -> Quoted {\n let fn_visibility = get_fn_visibility(f);\n f\"dep::aztec::macros::functions::initialization_utils::assert_initialization_matches_address_preimage_{fn_visibility}(context);\"\n .quoted_contents()\n}\n\ncomptime fn create_mark_as_initialized(f: FunctionDefinition) -> Quoted {\n let fn_visibility = get_fn_visibility(f);\n f\"dep::aztec::macros::functions::initialization_utils::mark_as_initialized_{fn_visibility}(&mut context);\"\n .quoted_contents()\n}\n\ncomptime fn create_init_check(f: FunctionDefinition) -> Quoted {\n let fn_visibility = get_fn_visibility(f);\n f\"dep::aztec::macros::functions::initialization_utils::assert_is_initialized_{fn_visibility}(&mut context);\"\n .quoted_contents()\n}\n\n/// Injects a call to `aztec::messages::discovery::discover_new_messages`, causing for new notes to be added to PXE and made\n/// available for the current execution.\npub(crate) comptime fn create_message_discovery_call() -> Quoted {\n quote {\n /// Safety: message discovery returns nothing and is performed solely for its side-effects. It is therefore\n /// always safe to call.\n unsafe {\n dep::aztec::messages::discovery::discover_new_messages(\n context.this_address(),\n _compute_note_hash_and_nullifier,\n );\n };\n }\n}\n\n/// Injects an authwit verification check of the form:\n/// ```\n/// if (!from.eq(context.msg_sender())) {\n/// assert_current_call_valid_authwit::(&mut context, from);\n/// } else {\n/// assert(authwit_nonce, \"Invalid authwit nonce. When 'from' and 'msg_sender' are the same, authwit_nonce must be zero\");\n/// }\n/// ```\n/// where `from` and `authwit_nonce` are the names of the parameters that are expected to be present in the function definition.\n/// This check is injected by the `#[authorize_once(\"from_arg_name\", \"nonce_arg_name\")]`, which allows the user to define\n/// which parameters to use.\npub(crate) comptime fn create_authorize_once_check(f: FunctionDefinition) -> Quoted {\n let maybe_authorize_once_args = AUTHORIZE_ONCE_REGISTRY.get(f);\n let authorize_once_args = if maybe_authorize_once_args.is_some() {\n maybe_authorize_once_args.unwrap()\n } else {\n // We need to for authorize_once to have already executed so that we can retrieve its params - this depends on\n // the order in which the attributes are applied.\n panic(\n f\"Functions marked with #[authorize_once] must have the #[private] or #[public] attribute placed last\",\n )\n };\n\n let (from_arg_name, nonce_arg_name) = authorize_once_args;\n let name: Quoted = f.name();\n\n let from_arg_candidates =\n f.parameters().filter(|(name, _)| name == f\"{from_arg_name}\".quoted_contents());\n let (from_arg_name_quoted, from_arg_type) = if from_arg_candidates.len() == 1 {\n from_arg_candidates[0]\n } else {\n panic(\n f\"Function {name} does not have a {from_arg_name} parameter. Please specify which one to use in #[authorize_once(\\\"...\\\", \\\"authwit_nonce\\\")]\",\n )\n };\n if from_arg_type\n != quote { dep::protocol_types::address::aztec_address::AztecAddress }.as_type() {\n panic(\n f\"Argument {from_arg_name_quoted} in function {name} must be of type AztecAddress, but is of type {from_arg_type}\",\n )\n }\n\n let nonce_arg_candidates =\n f.parameters().filter(|(name, _)| name == f\"{nonce_arg_name}\".quoted_contents());\n let (nonce_arg_name_quoted, nonce_arg_type) = if nonce_arg_candidates.len() == 1 {\n nonce_arg_candidates[0]\n } else {\n panic(\n f\"Function {name} does not have a {nonce_arg_name}. Please specify which one to use in #[authorize_once(\\\"from\\\", \\\"...\\\")]\",\n )\n };\n if nonce_arg_type != quote { Field }.as_type() {\n panic(\n f\"Argument {nonce_arg_name_quoted} in function {name} must be of type Field, but is of type {nonce_arg_type}\",\n );\n }\n\n let nonce_check_quote = f\"{nonce_arg_name_quoted} == 0\".quoted_contents();\n\n let fn_call = if is_fn_private(f) {\n // At this point, the original args of the fn have already been altered by the macro\n // to include PrivateContextInputs, so we need to adjust the args_len accordingly.\n let args_len = f.parameters().len() - 1;\n quote { dep::aztec::authwit::auth::assert_current_call_valid_authwit::<$args_len> }\n } else {\n quote { dep::aztec::authwit::auth::assert_current_call_valid_authwit_public }\n };\n let invalid_nonce_message = f\"Invalid authwit nonce. When '{from_arg_name}' and 'msg_sender' are the same, '{nonce_arg_name}' must be zero\"\n .as_ctstring()\n .as_quoted_str();\n quote { \n if (!$from_arg_name_quoted.eq(context.msg_sender())) {\n $fn_call(&mut context, $from_arg_name_quoted);\n } else {\n assert($nonce_check_quote, $invalid_nonce_message);\n }\n }\n}\n\n/// Checks if each function in the module is marked with either #[private], #[public], #[utility],\n/// #[contract_library_method], or #[test]. Non-macroified functions are not allowed in contracts.\npub(crate) comptime fn check_each_fn_macroified(m: Module) {\n for f in m.functions() {\n let name = f.name();\n if !is_fn_private(f)\n & !is_fn_public(f)\n & !is_fn_utility(f)\n & !is_fn_contract_library_method(f)\n & !is_fn_test(f) {\n panic(\n f\"Function {name} must be marked as either #[private], #[public], #[utility], #[contract_library_method], or #[test]\",\n );\n }\n }\n}\n" - }, - "107": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/macros/notes.nr", - "source": "use crate::note::note_getter_options::PropertySelector;\nuse std::{collections::bounded_vec::BoundedVec, meta::{ctstring::AsCtString, type_of}};\n\n/// Maximum number of note types within 1 contract.\ncomptime global MAX_NOTE_TYPES: u32 = 128;\n\n/// A BoundedVec containing all the note types within this contract.\npub comptime mut global NOTES: BoundedVec = BoundedVec::new();\n\ncomptime mut global NOTE_TYPE_ID_COUNTER: u32 = 0;\n\n/// The note type id is set by enumerating the note types.\ncomptime fn get_next_note_type_id() -> Field {\n // We assert that the note type id fits within 7 bits\n assert(\n NOTE_TYPE_ID_COUNTER < MAX_NOTE_TYPES,\n f\"A contract can contain at most {MAX_NOTE_TYPES} different note types\",\n );\n\n let note_type_id = NOTE_TYPE_ID_COUNTER as Field;\n NOTE_TYPE_ID_COUNTER += 1;\n note_type_id\n}\n\n/// Generates default `NoteType` implementation for a given note struct `s` and returns it as a quote.\n///\n/// impl NoteType for NoteStruct {\n/// fn get_id() -> Field {\n/// ...\n/// }\n/// }\ncomptime fn generate_note_type_impl(s: TypeDefinition, note_type_id: Field) -> Quoted {\n let name = s.name();\n let typ = s.as_type();\n let note_type_name: str<_> = f\"{name}\".as_ctstring().as_quoted_str!();\n let max_note_packed_len = crate::messages::discovery::private_notes::MAX_NOTE_PACKED_LEN;\n\n quote {\n impl aztec::note::note_interface::NoteType for $name {\n fn get_id() -> Field {\n // This static assertion ensures the note's packed length doesn't exceed the maximum allowed size.\n // While this check would ideally live in the Packable trait implementation, we place it here since\n // this function is always generated by our macros and the Packable trait implementation is not.\n // Note: We set the note type name and max packed length as local variables because injecting them\n // directly into the error message doesn't work.\n let note_type_name = $note_type_name;\n let max_note_packed_len: u32 = $max_note_packed_len; // Casting to u32 to avoid the value to be printed in hex.\n let note_packed_len = <$typ as Packable>::N;\n std::static_assert(note_packed_len <= $max_note_packed_len, f\"{note_type_name} has a packed length of {note_packed_len} fields, which exceeds the maximum allowed length of {max_note_packed_len} fields\");\n\n $note_type_id\n }\n }\n }\n}\n\n/// Generates default `NoteHash` trait implementation for a given note struct `s` and returns it as a quote.\n///\n/// # Generated Implementation\n/// ```\n/// impl NoteHash for NoteStruct {\n/// fn compute_note_hash(self, storage_slot: Field) -> Field { ... }\n///\n/// fn compute_nullifier(self, context: &mut PrivateContext, note_hash_for_nullify: Field) -> Field { ... }\n///\n/// unconstrained fn compute_nullifier_unconstrained(note_hash_for_nullify: Field) -> Field { ... }\n/// }\n/// ```\ncomptime fn generate_note_hash_trait_impl(s: TypeDefinition) -> Quoted {\n let name = s.name();\n\n quote {\n impl aztec::note::note_interface::NoteHash for $name {\n fn compute_note_hash(self, storage_slot: Field) -> Field {\n let inputs = aztec::protocol_types::traits::Packable::pack(self).concat( [storage_slot]);\n aztec::protocol_types::hash::poseidon2_hash_with_separator(inputs, aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_HASH)\n }\n\n fn compute_nullifier(\n self,\n context: &mut aztec::context::PrivateContext,\n note_hash_for_nullify: Field,\n ) -> Field {\n let owner_npk_m = aztec::keys::getters::get_public_keys(self.owner).npk_m;\n // We invoke hash as a static trait function rather than calling owner_npk_m.hash() directly\n // in the quote to avoid \"trait not in scope\" compiler warnings.\n let owner_npk_m_hash = aztec::protocol_types::traits::Hash::hash(owner_npk_m);\n let secret = context.request_nsk_app(owner_npk_m_hash);\n aztec::protocol_types::hash::poseidon2_hash_with_separator(\n [note_hash_for_nullify, secret],\n aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n )\n }\n\n unconstrained fn compute_nullifier_unconstrained(\n self,\n note_hash_for_nullify: Field,\n ) -> Field {\n let owner_npk_m = aztec::keys::getters::get_public_keys(self.owner).npk_m;\n // We invoke hash as a static trait function rather than calling owner_npk_m.hash() directly\n // in the quote to avoid \"trait not in scope\" compiler warnings.\n let owner_npk_m_hash = aztec::protocol_types::traits::Hash::hash(owner_npk_m);\n let secret = aztec::keys::getters::get_nsk_app(owner_npk_m_hash);\n aztec::protocol_types::hash::poseidon2_hash_with_separator(\n [note_hash_for_nullify, secret],\n aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n )\n }\n }\n }\n}\n\n/// Generates note properties struct for a given note struct `s`.\n///\n/// Example:\n/// ```\n/// struct TokenNoteProperties {\n/// amount: aztec::note::note_getter_options::PropertySelector,\n/// npk_m_hash: aztec::note::note_getter_options::PropertySelector\n/// randomness: aztec::note::note_getter_options::PropertySelector\n/// }\n///\n/// impl aztec::note::note_interface::NoteProperties for TokenNote {\n/// fn properties() -> TokenNoteProperties {\n/// Self {\n/// amount: aztec::note::note_getter_options::PropertySelector { index: 0, offset: 0, length: 32 },\n/// npk_m_hash: aztec::note::note_getter_options::PropertySelector { index: 1, offset: 0, length: 32 },\n/// randomness: aztec::note::note_getter_options::PropertySelector { index: 2, offset: 0, length: 32 }\n/// }\n/// }\n/// }\n/// ```\ncomptime fn generate_note_properties(s: TypeDefinition) -> Quoted {\n let name = s.name();\n\n let struct_name = f\"{name}Properties\".quoted_contents();\n\n let property_selector_type = type_of(PropertySelector { index: 0, offset: 0, length: 0 });\n\n let note_fields = s.fields_as_written();\n\n let properties_types = note_fields\n .map(|(name, _, _)| quote { pub $name: $property_selector_type })\n .join(quote {,});\n\n // TODO #8694: Properly handle non-field types https://github.com/AztecProtocol/aztec-packages/issues/8694\n let mut properties_list = &[];\n for i in 0..note_fields.len() {\n let (name, _, _) = note_fields[i];\n properties_list = properties_list.push_back(\n quote { $name: aztec::note::note_getter_options::PropertySelector { index: $i, offset: 0, length: 32 } },\n );\n }\n\n let properties = properties_list.join(quote {,});\n\n quote {\n pub struct $struct_name {\n $properties_types\n }\n\n impl aztec::note::note_interface::NoteProperties<$struct_name> for $name {\n fn properties() -> $struct_name {\n $struct_name {\n $properties\n }\n }\n }\n }\n}\n\n/// Generates the core note functionality for a struct:\n///\n/// - NoteTypeProperties: Defines the structure and properties of note fields\n/// - NoteType trait implementation: Provides the note type ID\n/// - NoteHash trait implementation: Handles note hash and nullifier computation\n///\n/// # Requirements\n///\n/// The note struct must:\n/// - Have an `owner` field\n/// - Implement the `Packable` trait\n/// - Not exceed `MAX_NOTE_PACKED_LEN` when packed\n///\n/// # Registration\n///\n/// Registers the note in the global `NOTES` BoundedVec to enable note processing functionality.\n///\n/// # Generated Code\n///\n/// For detailed documentation on the generated implementations, see:\n/// - `generate_note_properties()`\n/// - `generate_note_type_impl()`\n/// - `generate_note_hash_trait_impl()`\npub comptime fn note(s: TypeDefinition) -> Quoted {\n assert_has_owner(s);\n assert_has_packable(s);\n\n // We register the note in the global `NOTES` BoundedVec because we need that information inside the #[aztec] macro\n // to generate note processing functionality.\n NOTES.push(s.as_type());\n\n let note_properties = generate_note_properties(s);\n let note_type_id = get_next_note_type_id();\n let note_type_impl = generate_note_type_impl(s, note_type_id);\n let note_hash_impl = generate_note_hash_trait_impl(s);\n\n quote {\n $note_properties\n $note_type_impl\n $note_hash_impl\n }\n}\n\n/// Generates code for a custom note implementation that requires specialized note hash or nullifier computation.\n///\n/// # Generated Code\n/// - NoteTypeProperties: Defines the structure and properties of note fields\n/// - NoteType trait implementation: Provides the note type ID\n///\n/// # Requirements\n///\n/// The note struct must:\n/// - Implement the `Packable` trait\n/// - Not exceed `MAX_NOTE_PACKED_LEN` when packed\n///\n/// Unlike the `#[note]` macro, there is no requirement for an `owner` field.\n///\n/// # Registration\n///\n/// Registers the note in the global `NOTES` BoundedVec to enable note processing functionality.\n///\n/// # Use Cases\n/// Use this macro when implementing a note that needs custom:\n/// - Note hash computation logic\n/// - Nullifier computation logic\n///\n/// The macro omits generating default NoteHash trait implementation, allowing you to provide your own.\n///\n/// # Example\n/// ```\n/// #[custom_note]\n/// struct CustomNote {\n/// value: Field,\n/// metadata: Field\n/// }\n///\n/// impl NoteHash for CustomNote {\n/// // Custom note hash computation...\n/// fn compute_note_hash(...) -> Field { ... }\n///\n/// // Custom nullifier computation...\n/// fn compute_nullifier(...) -> Field { ... }\n/// fn compute_nullifier_unconstrained(...) -> Field { ... }\n/// }\n/// ```\npub comptime fn custom_note(s: TypeDefinition) -> Quoted {\n assert_has_packable(s);\n\n // We register the note in the global `NOTES` BoundedVec because we need that information inside the #[aztec] macro\n // to generate note processing functionality.\n NOTES.push(s.as_type());\n\n let note_type_id = get_next_note_type_id();\n let note_properties = generate_note_properties(s);\n let note_type_impl = generate_note_type_impl(s, note_type_id);\n\n quote {\n $note_properties\n $note_type_impl\n }\n}\n\n/// Asserts that the given note implements the `Packable` trait.\n///\n/// We require that notes have the `Packable` trait implemented because it is used when emitting a note in a log or as\n/// an offchain message.\ncomptime fn assert_has_packable(note: TypeDefinition) {\n let packable_constraint =\n quote { crate::protocol_types::traits::Packable }.as_trait_constraint();\n let note_name = note.name();\n\n assert(\n note.as_type().implements(packable_constraint),\n f\"{note_name} does not implement Packable trait. Either implement it manually or place #[derive(Packable)] on the note struct before #[note] macro invocation.\",\n );\n}\n\n/// Asserts that the note has an 'owner' field.\n///\n/// We require notes implemented with #[note] macro macro to have an 'owner' field because our\n/// auto-generated nullifier functions expect it. This requirement is most likely only temporary.\ncomptime fn assert_has_owner(note: TypeDefinition) {\n let fields = note.fields_as_written();\n let mut has_owner = false;\n for i in 0..fields.len() {\n let (field_name, _, _) = fields[i];\n if field_name == quote { owner } {\n has_owner = true;\n break;\n }\n }\n let note_name = note.name();\n\n assert(\n has_owner,\n f\"{note_name} does not have an 'owner' field. If your notes have no owner, use #[custom_note] insteadof #[note] and implement the NoteHashing trait manually.\",\n );\n}\n" - }, - "108": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/macros/storage.nr", - "source": "use poseidon::poseidon2::Poseidon2Hasher;\nuse std::{collections::umap::UHashMap, hash::BuildHasherDefault};\n\nuse super::utils::AsStrQuote;\nuse super::utils::get_storage_size;\n\n/// Stores a map from a module to the name of the struct that describes its storage layout.\n/// This is then used when generating a `storage_layout()` getter on the contract struct.\npub comptime mut global STORAGE_LAYOUT_NAME: UHashMap> =\n UHashMap::default();\n\n/// Marks a struct as the one describing the storage layout of a contract.\n///\n/// The contract's storage is accessed via the `storage` variable, which will will automatically be made available in\n/// all functions as an instance of the struct this macro was applied to.\n///\n/// Only a single struct in the entire contract should have this macro (or `storage_no_init`) applied to it, and the\n/// struct has to be called 'Storage'.\npub comptime fn storage(s: TypeDefinition) -> Quoted {\n let struct_name = s.name();\n if struct_name != quote { Storage } {\n panic(\n f\"The #[storage] macro can only be applied to a struct with name 'Storage', got '{struct_name}' instead.\",\n )\n }\n\n assert(\n !s.has_named_attribute(\"storage_no_init\"),\n f\"Only one of #[storage] and #[storage_no_init] can be applied to the Storage struct.\",\n );\n\n // This macro performs three things:\n // - it marks the contract as having storage, so that `macros::utils::module_has_storage` will return true and\n // functions will have the storage variable injected and initialized via the `init` function.\n // - it implements said `init` function by allocating appropriate storage slots to each state variable.\n // - it exposes the storage layout by creating a `StorageLayout` struct that is exposed via the `abi(storage)`\n // macro.\n let mut slot: u32 = 1;\n let mut storage_vars_constructors = &[];\n let mut storage_layout_fields = &[];\n let mut storage_layout_constructors = &[];\n\n // TODO(#8658): uncomment the code below to inject the Context type parameter.\n //let mut new_storage_fields = &[];\n //let context_generic = s.add_generic(\"Context\");\n for field in s.fields_as_written() {\n // FIXME: This doesn't handle field types with generics\n let (name, typ, _) = field;\n let (storage_field_constructor, storage_size) =\n generate_storage_field_constructor(typ, quote { $slot });\n storage_vars_constructors =\n storage_vars_constructors.push_back(quote { $name: $storage_field_constructor });\n // We have `Storable` in a separate `.nr` file instead of defining it in the last quote of this function\n // because that way a dev gets a more reasonable error if he defines a struct with the same name in\n // a contract.\n storage_layout_fields = storage_layout_fields.push_back(\n quote { pub $name: dep::aztec::state_vars::storage::Storable },\n );\n storage_layout_constructors = storage_layout_constructors.push_back(\n quote { $name: dep::aztec::state_vars::storage::Storable { slot: $slot } },\n );\n //let with_context_generic = add_context_generic(typ, context_generic);\n //println(with_context_generic);\n //new_storage_fields = new_storage_fields.push_back((name, with_context_generic ));\n slot += storage_size;\n }\n\n //s.set_fields(new_storage_fields);\n let storage_vars_constructors = storage_vars_constructors.join(quote {,});\n let storage_impl = quote {\n impl Storage {\n fn init(context: Context) -> Self {\n Self {\n $storage_vars_constructors\n }\n }\n }\n };\n\n let storage_layout_fields = storage_layout_fields.join(quote {,});\n let storage_layout_constructors = storage_layout_constructors.join(quote {,});\n\n let module = s.module();\n let module_name = module.name();\n let storage_layout_name = f\"STORAGE_LAYOUT_{module_name}\".quoted_contents();\n let (module_name_str, module_name_len) = module_name.as_str_quote();\n STORAGE_LAYOUT_NAME.insert(module, storage_layout_name);\n\n quote {\n $storage_impl\n\n pub struct StorageLayoutFields {\n $storage_layout_fields\n }\n\n pub struct StorageLayout {\n pub contract_name: str,\n pub fields: StorageLayoutFields\n }\n\n #[abi(storage)]\n pub global $storage_layout_name: StorageLayout<$module_name_len> = StorageLayout {\n contract_name: $module_name_str,\n fields: StorageLayoutFields { $storage_layout_constructors }\n };\n }\n}\n\n/// Same as `storage`, except the user is in charge of providing an implementation of the `init` constructor function\n/// with signature `fn init(context: Context) -> Self`, which allows for manual control of storage slot\n/// allocation. Similarly, no `StorageLayout` struct will be created.\n///\n/// The contract's storage is accessed via the `storage` variable, which will will automatically be made available in\n/// all functions as an instance of the struct this macro was applied to.\n///\n/// Only a single struct in the entire contract can have this macro (or storage_no_init) applied to it, and the struct\n/// has to be called 'Storage'.\npub comptime fn storage_no_init(s: TypeDefinition) {\n // All `storage` does is provide the `init` implementation, so we don't need to do anything here. Applying this\n // macro however will cause for `macros::utils::module_has_storage` to return true, resulting in the injection of\n // the `storage` variable.\n\n // We do need to make sure that the type is called Storage, since we'll do `Storage::init` later on.\n\n if s.name() != quote { Storage } {\n let name = s.name();\n panic(\n f\"The #[storage_no_init] macro can only be applied to a struct with name 'Storage', got '{name}' instead.\",\n )\n }\n\n assert(\n !s.has_named_attribute(\"storage\"),\n f\"Only one of #[storage] and #[storage_no_init] can be applied to the Storage struct.\",\n );\n}\n\n/// Returns the expression required to initialize a state variable with a given slot, along with its serialization size,\n/// i.e. how many contiguous storage slots the variable requires.\ncomptime fn generate_storage_field_constructor(typ: Type, slot: Quoted) -> (Quoted, u32) {\n assert(\n typ.as_data_type().is_some(),\n \"Storage containers must be generic structs of the form `Container<_, Context>`, or Map\",\n );\n let (container_struct, generics) = typ.as_data_type().unwrap();\n let struct_name = container_struct.name();\n\n let constructor = if is_storage_map(typ) {\n // Map state variables recursively initialize their contents - this includes nested maps.\n let (value_constructor, _) =\n generate_storage_field_constructor(generics[1], quote { slot });\n\n quote { $struct_name::new(context, $slot, | context, slot | { $value_constructor }) }\n } else {\n // We assume below that all state variables implement `fn new(context: Context, slot: Field) -> Self`.\n quote { $struct_name::new(context, $slot)}\n };\n\n (constructor, get_storage_size(typ))\n}\n\n/// Returns true if `typ` is `state_vars::map::Map`.\ncomptime fn is_storage_map(typ: Type) -> bool {\n if typ.as_data_type().is_some() {\n let (def, generics) = typ.as_data_type().unwrap();\n let maybe_map = if (def.name() == quote { Map }) & (generics.len() == 3) {\n let maybe_key = generics[0];\n let maybe_value = generics[1];\n let maybe_context = generics[2];\n quote { crate::state_vars::map::Map<$maybe_key, $maybe_value, $maybe_context> }.as_type()\n } else {\n quote {()}.as_type()\n };\n typ == maybe_map\n } else {\n false\n }\n}\n\ncomptime fn add_context_generic(typ: Type, context_generic: Type) -> Type {\n let (def, mut generics) = typ.as_data_type().expect(\n f\"Storage containers must be generic structs of the form `Container<..., Context>`\",\n );\n let name = def.name();\n\n if is_storage_map(typ) {\n generics[generics.len() - 2] = add_context_generic(generics[1], context_generic);\n generics[generics.len() - 1] = context_generic;\n } else {\n generics[generics.len() - 1] = context_generic;\n }\n\n let generics = generics.map(|typ: Type| quote {$typ}).join(quote {,});\n quote { $name<$generics> }.as_type()\n}\n" - }, - "110": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/discovery/mod.nr", - "source": "use protocol_types::{address::AztecAddress, debug_log::{debug_log, debug_log_format}};\n\npub mod nonce_discovery;\npub mod partial_notes;\npub mod private_events;\npub mod private_notes;\npub mod process_message;\n\nuse crate::{\n messages::{\n discovery::{private_notes::MAX_NOTE_PACKED_LEN, process_message::do_process_message},\n processing::{\n get_private_logs, pending_tagged_log::PendingTaggedLog,\n validate_enqueued_notes_and_events,\n },\n },\n utils::array,\n};\n\npub struct NoteHashAndNullifier {\n /// The result of NoteHash::compute_note_hash\n pub note_hash: Field,\n /// The result of NoteHash::compute_nullifier_unconstrained (since all of message discovery is unconstrained)\n pub inner_nullifier: Field,\n}\n\n/// A function which takes a note's packed content, address of the emitting contract, note nonce, storage slot and note\n/// type ID and attempts to compute its note hash (not hashed by note nonce nor siloed by address) and inner nullifier\n/// (not siloed by address).\n///\n/// This function must be user-provided as its implementation requires knowledge of how note type IDs are allocated in a\n/// contract. The `#[aztec]` macro automatically creates such a contract library method called\n/// `_compute_note_hash_and_nullifier`, which looks something like this:\n///\n/// ```\n/// |packed_note, contract_address, note_nonce, storage_slot, note_type_id| {\n/// if note_type_id == MyNoteType::get_id() {\n/// assert(packed_note.len() == MY_NOTE_TYPE_SERIALIZATION_LENGTH);\n///\n/// let note = MyNoteType::unpack(aztec::utils::array::subarray(packed_note.storage(), 0));\n///\n/// let note_hash = note.compute_note_hash(storage_slot);\n/// let note_hash_for_nullify = aztec::note::utils::compute_note_hash_for_nullify(\n/// RetrievedNote{ note, contract_address, metadata: SettledNoteMetadata::new(note_nonce).into() },\n/// storage_slot\n/// );\n///\n/// let inner_nullifier = note.compute_nullifier_unconstrained(note_hash_for_nullify);\n///\n/// Option::some(\n/// aztec::messages::discovery::NoteHashAndNullifier {\n/// note_hash, inner_nullifier\n/// }\n/// )\n/// } else if note_type_id == MyOtherNoteType::get_id() {\n/// ... // Similar to above but calling MyOtherNoteType::unpack_content\n/// } else {\n/// Option::none() // Unknown note type ID\n/// };\n/// }\n/// ```\ntype ComputeNoteHashAndNullifier = unconstrained fn[Env](/* packed_note */BoundedVec, /* storage_slot */ Field, /* note_type_id */ Field, /* contract_address */ AztecAddress, /* note nonce */ Field) -> Option;\n\n/// Performs the message discovery process, in which private are downloaded and inspected to find new private notes,\n/// partial notes and events, etc., and pending partial notes are processed to search for their completion logs.\n/// This is the mechanism via which a contract updates its knowledge of its private state.\n///\n/// Receives the address of the contract on which discovery is performed along with its\n/// `compute_note_hash_and_nullifier` function.\npub unconstrained fn discover_new_messages(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n) {\n debug_log(\"Performing message discovery\");\n\n // First we process all private logs, which can contain different kinds of messages e.g. private notes, partial\n // notes, private events, etc.\n let mut logs = get_private_logs(contract_address);\n logs.for_each(|i, pending_tagged_log: PendingTaggedLog| {\n debug_log_format(\n \"Processing log with tag {0}\",\n [pending_tagged_log.log.get(0)],\n );\n\n // We remove the tag from the pending tagged log and process the message ciphertext contained in it.\n let message_ciphertext = array::subbvec(pending_tagged_log.log, 1);\n\n do_process_message(\n contract_address,\n compute_note_hash_and_nullifier,\n message_ciphertext,\n pending_tagged_log.context,\n );\n logs.remove(i);\n });\n\n // Then we process all pending partial notes, regardless of whether they were found in the current or previous\n // executions.\n partial_notes::fetch_and_process_partial_note_completion_logs(\n contract_address,\n compute_note_hash_and_nullifier,\n );\n\n // Finally we validate all notes and events that were found as part of the previous processes, resulting in them\n // being added to PXE's database and retrievable via oracles (get_notes) and our TS API (PXE::getPrivateEvents).\n validate_enqueued_notes_and_events(contract_address);\n}\n" - }, - "111": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/discovery/nonce_discovery.nr", - "source": "use crate::messages::discovery::{ComputeNoteHashAndNullifier, private_notes::MAX_NOTE_PACKED_LEN};\n\nuse dep::protocol_types::{\n address::AztecAddress,\n constants::MAX_NOTE_HASHES_PER_TX,\n debug_log::debug_log_format,\n hash::{compute_note_hash_nonce, compute_siloed_note_hash, compute_unique_note_hash},\n traits::ToField,\n};\n\n/// A struct with the discovered information of a complete note, required for delivery to PXE. Note that this is *not*\n/// the complete note information, since it does not include content, storage slot, etc.\npub struct DiscoveredNoteInfo {\n pub note_nonce: Field,\n pub note_hash: Field,\n pub inner_nullifier: Field,\n}\n\n/// Searches for note nonces that will result in a note that was emitted in a transaction. While rare, it is possible\n/// for multiple notes to have the exact same packed content and storage slot but different nonces, resulting in\n/// different unique note hashes. Because of this this function returns a *vector* of discovered notes, though in most\n/// cases it will contain a single element.\n///\n/// Due to how nonces are computed, this function requires knowledge of the transaction in which the note was created,\n/// more specifically the list of all unique note hashes in it plus the value of its first nullifier.\npub unconstrained fn attempt_note_nonce_discovery(\n unique_note_hashes_in_tx: BoundedVec,\n first_nullifier_in_tx: Field,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n packed_note: BoundedVec,\n) -> BoundedVec {\n let discovered_notes = &mut BoundedVec::new();\n\n debug_log_format(\n \"Attempting nonce discovery on {0} potential notes on contract {1} for storage slot {2}\",\n [unique_note_hashes_in_tx.len() as Field, contract_address.to_field(), storage_slot],\n );\n\n // We need to find nonces (typically just one) that result in a note hash that, once siloed into a unique note hash,\n // is one of the note hashes created by the transaction.\n unique_note_hashes_in_tx.for_eachi(|i, expected_unique_note_hash| {\n // Nonces are computed by hashing the first nullifier in the transaction with the index of the note in the\n // new note hashes array. We therefore know for each note in every transaction what its nonce is.\n let candidate_nonce = compute_note_hash_nonce(first_nullifier_in_tx, i);\n\n // Given note nonce, note content and metadata, we can compute the note hash and silo it to check if it matches\n // the note hash at the array index we're currently processing.\n // TODO(#11157): handle failed note_hash_and_nullifier computation\n let hashes = compute_note_hash_and_nullifier(\n packed_note,\n storage_slot,\n note_type_id,\n contract_address,\n candidate_nonce,\n )\n .expect(f\"Failed to compute a note hash for note type {note_type_id}\");\n\n let siloed_note_hash = compute_siloed_note_hash(contract_address, hashes.note_hash);\n let unique_note_hash = compute_unique_note_hash(candidate_nonce, siloed_note_hash);\n\n if unique_note_hash == expected_unique_note_hash {\n // Note that while we did check that the note hash is the preimage of the expected unique note hash, we\n // perform no validations on the nullifier - we fundamentally cannot, since only the application knows\n // how to compute nullifiers. We simply trust it to have provided the correct one: if it hasn't, then\n // PXE may fail to realize that a given note has been nullified already, and calls to the application\n // could result in invalid transactions (with duplicate nullifiers). This is not a concern because an\n // application already has more direct means of making a call to it fail the transaction.\n discovered_notes.push(\n DiscoveredNoteInfo {\n note_nonce: candidate_nonce,\n note_hash: hashes.note_hash,\n inner_nullifier: hashes.inner_nullifier,\n },\n );\n\n // We don't exit the loop - it is possible (though rare) for the exact same note content to be present\n // multiple times in the same transaction with different nonces. This typically doesn't happen due to\n // notes containing random values in order to hide their contents.\n }\n });\n\n debug_log_format(\n \"Found valid nonces for a total of {0} notes\",\n [discovered_notes.len() as Field],\n );\n\n *discovered_notes\n}\n\nmod test {\n use crate::{\n messages::discovery::{NoteHashAndNullifier, private_notes::MAX_NOTE_PACKED_LEN},\n note::{\n note_interface::{NoteHash, NoteType},\n note_metadata::SettledNoteMetadata,\n retrieved_note::RetrievedNote,\n utils::compute_note_hash_for_nullify,\n },\n oracle::random::random,\n test::mocks::mock_note::MockNote,\n utils::array,\n };\n\n use dep::protocol_types::{\n address::AztecAddress,\n hash::{compute_note_hash_nonce, compute_siloed_note_hash, compute_unique_note_hash},\n traits::{FromField, Packable},\n };\n\n use super::attempt_note_nonce_discovery;\n\n // This implementation could be simpler, but this serves as a nice example of the expected flow in a real\n // implementation, and as a sanity check that the interface is sufficient.\n unconstrained fn compute_note_hash_and_nullifier(\n packed_note: BoundedVec,\n storage_slot: Field,\n note_type_id: Field,\n contract_address: AztecAddress,\n note_nonce: Field,\n ) -> Option {\n if note_type_id == MockNote::get_id() {\n let note = MockNote::unpack(array::subarray(packed_note.storage(), 0));\n let note_hash = note.compute_note_hash(storage_slot);\n\n let note_hash_for_nullify = compute_note_hash_for_nullify(\n RetrievedNote {\n note,\n contract_address,\n metadata: SettledNoteMetadata::new(note_nonce).into(),\n },\n storage_slot,\n );\n\n let inner_nullifier = note.compute_nullifier_unconstrained(note_hash_for_nullify);\n\n Option::some(NoteHashAndNullifier { note_hash, inner_nullifier })\n } else {\n Option::none()\n }\n }\n\n global VALUE: Field = 7;\n global FIRST_NULLIFIER_IN_TX: Field = 47;\n global CONTRACT_ADDRESS: AztecAddress = AztecAddress::from_field(13);\n global STORAGE_SLOT: Field = 99;\n\n #[test]\n unconstrained fn no_note_hashes() {\n let unique_note_hashes_in_tx = BoundedVec::new();\n let packed_note = BoundedVec::new();\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n MockNote::get_id(),\n packed_note,\n );\n\n assert_eq(discovered_notes.len(), 0);\n }\n\n #[test(should_fail_with = \"Failed to compute a note hash\")]\n unconstrained fn failed_hash_computation() {\n let unique_note_hashes_in_tx = BoundedVec::from_array([random()]);\n let packed_note = BoundedVec::new();\n let note_type_id = 0; // This note type id is unknown to compute_note_hash_and_nullifier\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n note_type_id,\n packed_note,\n );\n\n assert_eq(discovered_notes.len(), 0);\n }\n\n struct NoteAndData {\n note: MockNote,\n note_nonce: Field,\n note_hash: Field,\n unique_note_hash: Field,\n inner_nullifier: Field,\n }\n\n unconstrained fn construct_note(value: Field, note_index_in_tx: u32) -> NoteAndData {\n let note_nonce = compute_note_hash_nonce(FIRST_NULLIFIER_IN_TX, note_index_in_tx);\n\n let retrieved_note = MockNote::new(value)\n .contract_address(CONTRACT_ADDRESS)\n .note_metadata(SettledNoteMetadata::new(note_nonce).into())\n .build_retrieved_note();\n let note = retrieved_note.note;\n\n let note_hash = note.compute_note_hash(STORAGE_SLOT);\n let unique_note_hash = compute_unique_note_hash(\n note_nonce,\n compute_siloed_note_hash(CONTRACT_ADDRESS, note_hash),\n );\n let inner_nullifier = note.compute_nullifier_unconstrained(compute_note_hash_for_nullify(\n retrieved_note,\n STORAGE_SLOT,\n ));\n\n NoteAndData { note, note_nonce, note_hash, unique_note_hash, inner_nullifier }\n }\n\n #[test]\n unconstrained fn single_note() {\n let note_index_in_tx = 2;\n let note_and_data = construct_note(VALUE, note_index_in_tx);\n\n let mut unique_note_hashes_in_tx = BoundedVec::from_array([\n random(), random(), random(), random(), random(), random(), random(),\n ]);\n unique_note_hashes_in_tx.set(note_index_in_tx, note_and_data.unique_note_hash);\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n MockNote::get_id(),\n BoundedVec::from_array(note_and_data.note.pack()),\n );\n\n assert_eq(discovered_notes.len(), 1);\n let discovered_note = discovered_notes.get(0);\n\n assert_eq(discovered_note.note_nonce, note_and_data.note_nonce);\n assert_eq(discovered_note.note_hash, note_and_data.note_hash);\n assert_eq(discovered_note.inner_nullifier, note_and_data.inner_nullifier);\n }\n\n #[test]\n unconstrained fn multiple_notes_same_preimage() {\n let first_note_index_in_tx = 3;\n let first_note_and_data = construct_note(VALUE, first_note_index_in_tx);\n\n let second_note_index_in_tx = 5;\n let second_note_and_data = construct_note(VALUE, second_note_index_in_tx);\n\n // Both notes have the same preimage (and therefore packed representation), so both should be found in the same\n // call.\n assert_eq(first_note_and_data.note, second_note_and_data.note);\n let packed_note = first_note_and_data.note.pack();\n\n let mut unique_note_hashes_in_tx = BoundedVec::from_array([\n random(), random(), random(), random(), random(), random(), random(),\n ]);\n unique_note_hashes_in_tx.set(first_note_index_in_tx, first_note_and_data.unique_note_hash);\n unique_note_hashes_in_tx.set(second_note_index_in_tx, second_note_and_data.unique_note_hash);\n\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n FIRST_NULLIFIER_IN_TX,\n compute_note_hash_and_nullifier,\n CONTRACT_ADDRESS,\n STORAGE_SLOT,\n MockNote::get_id(),\n BoundedVec::from_array(packed_note),\n );\n\n assert_eq(discovered_notes.len(), 2);\n\n assert(discovered_notes.any(|discovered_note| {\n (discovered_note.note_nonce == first_note_and_data.note_nonce)\n & (discovered_note.note_hash == first_note_and_data.note_hash)\n & (discovered_note.inner_nullifier == first_note_and_data.inner_nullifier)\n }));\n\n assert(discovered_notes.any(|discovered_note| {\n (discovered_note.note_nonce == second_note_and_data.note_nonce)\n & (discovered_note.note_hash == second_note_and_data.note_hash)\n & (discovered_note.inner_nullifier == second_note_and_data.inner_nullifier)\n }));\n }\n}\n" - }, - "112": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/discovery/partial_notes.nr", - "source": "use crate::{\n capsules::CapsuleArray,\n messages::{\n discovery::{ComputeNoteHashAndNullifier, nonce_discovery::attempt_note_nonce_discovery},\n encoding::MAX_MESSAGE_CONTENT_LEN,\n processing::{\n enqueue_note_for_validation, get_pending_partial_notes_completion_logs,\n log_retrieval_response::LogRetrievalResponse,\n },\n },\n utils::array,\n};\n\nuse protocol_types::{\n address::AztecAddress,\n debug_log::debug_log_format,\n hash::sha256_to_field,\n traits::{Deserialize, Serialize},\n};\n\nglobal PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN: u32 = 2;\n\n/// Partial notes have a maximum packed length of their private fields bound by extra content in their private message\n/// (e.g. the storage slot, note completion log tag, etc.).\npub global MAX_PARTIAL_NOTE_PRIVATE_PACKED_LEN: u32 =\n MAX_MESSAGE_CONTENT_LEN - PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN;\n\n/// The slot in the PXE capsules where we store a `CapsuleArray` of `DeliveredPendingPartialNote`.\npub global DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT\".as_bytes(),\n);\n\n/// A partial note that was delivered but is still pending completion. Contains the information necessary to find the\n/// log that will complete it and lead to a note being discovered and delivered.\n#[derive(Serialize, Deserialize)]\npub(crate) struct DeliveredPendingPartialNote {\n pub(crate) note_completion_log_tag: Field,\n pub(crate) storage_slot: Field,\n pub(crate) note_type_id: Field,\n pub(crate) packed_private_note_content: BoundedVec,\n pub(crate) recipient: AztecAddress,\n}\n\npub unconstrained fn process_partial_note_private_msg(\n contract_address: AztecAddress,\n recipient: AztecAddress,\n msg_metadata: u64,\n msg_content: BoundedVec,\n) {\n let (note_type_id, storage_slot, note_completion_log_tag, packed_private_note_content) =\n decode_partial_note_private_msg(msg_metadata, msg_content);\n\n // We store the information of the partial note we found in a persistent capsule in PXE, so that we can later search\n // for the public log that will complete it.\n let pending = DeliveredPendingPartialNote {\n note_completion_log_tag,\n storage_slot,\n note_type_id,\n packed_private_note_content,\n recipient,\n };\n\n CapsuleArray::at(\n contract_address,\n DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT,\n )\n .push(pending);\n}\n\n/// Searches for logs that would result in the completion of pending partial notes, ultimately resulting in the notes\n/// being delivered to PXE if completed.\npub unconstrained fn fetch_and_process_partial_note_completion_logs(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n) {\n let pending_partial_notes = CapsuleArray::at(\n contract_address,\n DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT,\n );\n\n debug_log_format(\n \"{} pending partial notes\",\n [pending_partial_notes.len() as Field],\n );\n\n // Each of the pending partial notes might get completed by a log containing its public values. For performance\n // reasons, we fetch all of these logs concurrently and then process them one by one, minimizing the amount of time\n // waiting for the node roundtrip.\n let maybe_completion_logs =\n get_pending_partial_notes_completion_logs(contract_address, pending_partial_notes);\n\n // Each entry in the maybe completion logs array corresponds to the entry in the pending partial notes array at the\n // same index. This means we can use the same index as we iterate through the responses to get both the partial note\n // and the log that might complete it.\n assert_eq(maybe_completion_logs.len(), pending_partial_notes.len());\n\n maybe_completion_logs.for_each(|i, maybe_log: Option| {\n // We clear the completion logs as we read them so that the array is empty by the time we next query it.\n // TODO(#14943): use volatile arrays to avoid having to manually clear this.\n maybe_completion_logs.remove(i);\n\n let pending_partial_note = pending_partial_notes.get(i);\n\n if maybe_log.is_none() {\n debug_log_format(\n \"Found no completion logs for partial note with tag {}\",\n [pending_partial_note.note_completion_log_tag],\n );\n\n // Note that we're not removing the pending partial note from the capsule array, so we will continue\n // searching for this tagged log when performing message discovery in the future until we either find it or\n // the entry is somehow removed from the array.\n } else {\n debug_log_format(\n \"Completion log found for partial note with tag {}\",\n [pending_partial_note.note_completion_log_tag],\n );\n let log = maybe_log.unwrap();\n\n // Public fields are assumed to all be placed at the end of the packed representation, so we combine the\n // private and public packed fields (i.e. the contents of the private message and public log plaintext to get\n // the complete packed content.\n let complete_packed_note = array::append(\n pending_partial_note.packed_private_note_content,\n log.log_payload,\n );\n\n let discovered_notes = attempt_note_nonce_discovery(\n log.unique_note_hashes_in_tx,\n log.first_nullifier_in_tx,\n compute_note_hash_and_nullifier,\n contract_address,\n pending_partial_note.storage_slot,\n pending_partial_note.note_type_id,\n complete_packed_note,\n );\n\n // TODO(#11627): is there anything reasonable we can do if we get a log but it doesn't result in a note\n // being found?\n if discovered_notes.len() == 0 {\n panic(\n f\"A partial note's completion log did not result in any notes being found - this should never happen\",\n );\n }\n\n debug_log_format(\n \"Discovered {0} notes for partial note with tag {1}\",\n [discovered_notes.len() as Field, pending_partial_note.note_completion_log_tag],\n );\n\n discovered_notes.for_each(|discovered_note| {\n enqueue_note_for_validation(\n contract_address,\n pending_partial_note.storage_slot,\n discovered_note.note_nonce,\n complete_packed_note,\n discovered_note.note_hash,\n discovered_note.inner_nullifier,\n log.tx_hash,\n pending_partial_note.recipient,\n );\n });\n\n // Because there is only a single log for a given tag, once we've processed the tagged log then we\n // simply delete the pending work entry, regardless of whether it was actually completed or not.\n pending_partial_notes.remove(i);\n }\n });\n}\n\nfn decode_partial_note_private_msg(\n msg_metadata: u64,\n msg_content: BoundedVec,\n) -> (Field, Field, Field, BoundedVec) {\n let note_type_id = msg_metadata as Field; // TODO: make note type id not be a full field\n\n assert(\n msg_content.len() > PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN,\n f\"Invalid private note message: all partial note private messages must have at least {PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN} fields\",\n );\n\n // If PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN is changed, causing the assertion below to fail, then the\n // destructuring of the partial note private message encoding below must be updated as well.\n std::static_assert(\n PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN == 2,\n \"unexpected value for PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN\",\n );\n\n // We currently have two fields that are not the partial note's packed representation, which are the storage slot\n // and the note completion log tag.\n let storage_slot = msg_content.get(0);\n let note_completion_log_tag = msg_content.get(1);\n\n let packed_private_note_content = array::subbvec(msg_content, 2);\n\n (note_type_id, storage_slot, note_completion_log_tag, packed_private_note_content)\n}\n" - }, - "113": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/discovery/private_events.nr", - "source": "use crate::{\n event::event_selector::EventSelector,\n messages::{encoding::MAX_MESSAGE_CONTENT_LEN, processing::enqueue_event_for_validation},\n utils::array,\n};\nuse protocol_types::{\n address::AztecAddress, constants::GENERATOR_INDEX__EVENT_COMMITMENT,\n hash::poseidon2_hash_with_separator_bounded_vec, traits::FromField,\n};\n\n/// The number of fields in a private event message content that are not the event's serialized representation\n/// (1 field for randomness).\nglobal PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN: u32 = 1;\n\n/// The maximum length of the packed representation of an event's contents. This is limited by private log size,\n/// encryption overhead and extra fields in the message (e.g. message type id, randomness, etc.).\npub global MAX_EVENT_SERIALIZED_LEN: u32 =\n MAX_MESSAGE_CONTENT_LEN - PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN;\n\npub unconstrained fn process_private_event_msg(\n contract_address: AztecAddress,\n recipient: AztecAddress,\n msg_metadata: u64,\n msg_content: BoundedVec,\n tx_hash: Field,\n) {\n // In the case of events, the msg metadata is the event selector.\n let event_type_id = EventSelector::from_field(msg_metadata as Field);\n\n assert(\n msg_content.len() > PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN,\n f\"Invalid private event message: all private event messages must have at least {PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN} fields\",\n );\n\n // If PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN is changed, causing the assertion below to fail, then the\n // destructuring of the private event message encoding below must be updated as well.\n std::static_assert(\n PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN == 1,\n \"unexpected value for PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN\",\n );\n\n let serialized_event_with_randomness = msg_content;\n\n let event_commitment = poseidon2_hash_with_separator_bounded_vec(\n serialized_event_with_randomness,\n GENERATOR_INDEX__EVENT_COMMITMENT,\n );\n\n // Randomness was injected into the event payload in `emit_event_in_private` but we have already used it\n // to compute the event commitment, so we can safely discard it now.\n let serialized_event = array::subbvec(\n serialized_event_with_randomness,\n PRIVATE_EVENT_MSG_CONTENT_NON_EVENT_FIELDS_LEN,\n );\n\n enqueue_event_for_validation(\n contract_address,\n event_type_id,\n serialized_event,\n event_commitment,\n tx_hash,\n recipient,\n );\n}\n" - }, - "114": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/discovery/private_notes.nr", - "source": "use crate::{\n messages::{\n discovery::{ComputeNoteHashAndNullifier, nonce_discovery::attempt_note_nonce_discovery},\n encoding::MAX_MESSAGE_CONTENT_LEN,\n processing::enqueue_note_for_validation,\n },\n utils::array,\n};\nuse protocol_types::{\n address::AztecAddress, constants::MAX_NOTE_HASHES_PER_TX, debug_log::debug_log_format,\n};\n\n/// The number of fields in a private note message content that are not the note's packed representation.\n// See the call to `std::static_assert` below to see what's in these fields.\nglobal PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN: u32 = 1;\n\n/// The maximum length of the packed representation of a note's contents. This is limited by private log size,\n/// encryption overhead and extra fields in the message (e.g. message type id, storage slot, etc.).\npub global MAX_NOTE_PACKED_LEN: u32 =\n MAX_MESSAGE_CONTENT_LEN - PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN;\n\npub unconstrained fn process_private_note_msg(\n contract_address: AztecAddress,\n tx_hash: Field,\n unique_note_hashes_in_tx: BoundedVec,\n first_nullifier_in_tx: Field,\n recipient: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n msg_metadata: u64,\n msg_content: BoundedVec,\n) {\n let (note_type_id, storage_slot, packed_note) =\n decode_private_note_msg(msg_metadata, msg_content);\n\n attempt_note_discovery(\n contract_address,\n tx_hash,\n unique_note_hashes_in_tx,\n first_nullifier_in_tx,\n recipient,\n compute_note_hash_and_nullifier,\n storage_slot,\n note_type_id,\n packed_note,\n );\n}\n\n/// Attempts discovery of a note given information about its contents and the transaction in which it is\n/// suspected the note was created.\npub unconstrained fn attempt_note_discovery(\n contract_address: AztecAddress,\n tx_hash: Field,\n unique_note_hashes_in_tx: BoundedVec,\n first_nullifier_in_tx: Field,\n recipient: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n storage_slot: Field,\n note_type_id: Field,\n packed_note: BoundedVec,\n) {\n let discovered_notes = attempt_note_nonce_discovery(\n unique_note_hashes_in_tx,\n first_nullifier_in_tx,\n compute_note_hash_and_nullifier,\n contract_address,\n storage_slot,\n note_type_id,\n packed_note,\n );\n\n debug_log_format(\n \"Discovered {0} notes from a private message\",\n [discovered_notes.len() as Field],\n );\n\n discovered_notes.for_each(|discovered_note| {\n enqueue_note_for_validation(\n contract_address,\n storage_slot,\n discovered_note.note_nonce,\n packed_note,\n discovered_note.note_hash,\n discovered_note.inner_nullifier,\n tx_hash,\n recipient,\n );\n });\n}\n\nfn decode_private_note_msg(\n msg_metadata: u64,\n msg_content: BoundedVec,\n) -> (Field, Field, BoundedVec) {\n let note_type_id = msg_metadata as Field; // TODO: make note type id not be a full field\n\n assert(\n msg_content.len() > PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN,\n f\"Invalid private note message: all private note messages must have at least {PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN} fields\",\n );\n\n // If PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN is changed, causing the assertion below to fail, then the\n // destructuring of the private note message encoding below must be updated as well.\n std::static_assert(\n PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN == 1,\n \"unexpected value for PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN\",\n );\n\n // We currently have a single field that is not the note's packed representation, which is the storage slot.\n let storage_slot = msg_content.get(0);\n let packed_note = array::subbvec(msg_content, PRIVATE_NOTE_MSG_CONTENT_NON_NOTE_FIELDS_LEN);\n\n (note_type_id, storage_slot, packed_note)\n}\n" - }, - "115": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/discovery/process_message.nr", - "source": "use crate::messages::{\n discovery::{\n ComputeNoteHashAndNullifier, partial_notes::process_partial_note_private_msg,\n private_events::process_private_event_msg, private_notes::process_private_note_msg,\n },\n encoding::decode_message,\n encryption::{aes128::AES128, log_encryption::LogEncryption},\n msg_type::{\n PARTIAL_NOTE_PRIVATE_MSG_TYPE_ID, PRIVATE_EVENT_MSG_TYPE_ID, PRIVATE_NOTE_MSG_TYPE_ID,\n },\n processing::message_context::MessageContext,\n};\n\nuse protocol_types::{\n address::AztecAddress,\n constants::PRIVATE_LOG_CIPHERTEXT_LEN,\n debug_log::{debug_log, debug_log_format},\n};\n\n/// Processes a message that can contain notes, partial notes, or events.\n///\n/// Notes result in nonce discovery being performed prior to delivery, which requires knowledge of the transaction hash\n/// in which the notes would've been created (typically the same transaction in which the log was emitted), along with\n/// the list of unique note hashes in said transaction and the `compute_note_hash_and_nullifier` function. Once\n/// discovered, the notes are enqueued for validation.\n///\n/// Partial notes result in a pending partial note entry being stored in a PXE capsule, which will later be retrieved to\n/// search for the note's completion public log.\n///\n/// Events are processed by computing an event commitment from the serialized event data and its randomness field, then\n/// enqueueing the event data and commitment for validation.\npub unconstrained fn do_process_message(\n contract_address: AztecAddress,\n compute_note_hash_and_nullifier: ComputeNoteHashAndNullifier,\n message_ciphertext: BoundedVec,\n message_context: MessageContext,\n) {\n let message = AES128::decrypt_log(message_ciphertext, message_context.recipient);\n\n // The first thing to do after decrypting the message is to determine what type of message we're processing. We\n // have 3 message types: private notes, partial notes and events.\n\n // We decode the message to obtain the message type id, metadata and content.\n let (msg_type_id, msg_metadata, msg_content) = decode_message(message);\n\n if msg_type_id == PRIVATE_NOTE_MSG_TYPE_ID {\n debug_log(\"Processing private note msg\");\n\n process_private_note_msg(\n contract_address,\n message_context.tx_hash,\n message_context.unique_note_hashes_in_tx,\n message_context.first_nullifier_in_tx,\n message_context.recipient,\n compute_note_hash_and_nullifier,\n msg_metadata,\n msg_content,\n );\n } else if msg_type_id == PARTIAL_NOTE_PRIVATE_MSG_TYPE_ID {\n debug_log(\"Processing partial note private msg\");\n\n process_partial_note_private_msg(\n contract_address,\n message_context.recipient,\n msg_metadata,\n msg_content,\n );\n } else if msg_type_id == PRIVATE_EVENT_MSG_TYPE_ID {\n debug_log(\"Processing private event msg\");\n\n process_private_event_msg(\n contract_address,\n message_context.recipient,\n msg_metadata,\n msg_content,\n message_context.tx_hash,\n );\n } else {\n debug_log_format(\"Unknown msg type id {0}\", [msg_type_id as Field]);\n }\n}\n" - }, - "116": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/encoding.nr", - "source": "// TODO(#12750): don't make these values assume we're using AES.\nuse crate::{\n messages::encryption::log_encryption::PRIVATE_LOG_PLAINTEXT_SIZE_IN_FIELDS, utils::array,\n};\n\npub global MAX_MESSAGE_LEN: u32 = PRIVATE_LOG_PLAINTEXT_SIZE_IN_FIELDS;\n\nglobal MESSAGE_EXPANDED_METADATA_LEN: u32 = 1;\n\n// The standard message layout is composed of:\n// - an initial field called the 'expanded metadata'\n// - an arbitrary number of fields following that called the 'message content'\n//\n// ```\n// message: [ msg_expanded_metadata, ...msg_content ]\n// ```\n//\n// The expanded metadata itself is interpreted as a u128, of which:\n// - the upper 64 bits are the message type id\n// - the lower 64 bits are called the 'message metadata'\n//\n// ```\n// msg_expanded_metadata: [ msg_type_id | msg_metadata ]\n// <--- 64 bits --->|<--- 64 bits --->\n// ```\n//\n// The meaning of the message metadata and message content depend on the value of the message type id. Note that there\n// is nothing special about the message metadata, it _can_ be considered part of the content. It just has a different\n// name to make it distinct from the message content given that it is not a full field.\n\n/// The maximum length of a message's content, i.e. not including the expanded message metadata.\npub global MAX_MESSAGE_CONTENT_LEN: u32 = MAX_MESSAGE_LEN - MESSAGE_EXPANDED_METADATA_LEN;\n\n/// Encodes a message following aztec-nr's standard message encoding. This message can later be decoded with\n/// `decode_message` to retrieve the original values.\n///\n/// - The `msg_type` is an identifier that groups types of messages that are all processed the same way, e.g. private\n/// notes or events. Possible values are defined in `aztec::messages::msg_type`.\n/// - The `msg_metadata` and `msg_content` are the values stored in the message, whose meaning depends on the\n/// `msg_type`. The only special thing about `msg_metadata` that separates it from `msg_content` is that it is a u64\n/// instead of a full Field (due to details of how messages are encoded), allowing applications that can fit values into\n/// this smaller variable to achieve higher data efficiency.\npub fn encode_message(\n msg_type: u64,\n msg_metadata: u64,\n msg_content: [Field; N],\n) -> [Field; (N + MESSAGE_EXPANDED_METADATA_LEN)] {\n std::static_assert(\n msg_content.len() <= MAX_MESSAGE_CONTENT_LEN,\n \"Invalid message content: it must have a length of at most MAX_MESSAGE_CONTENT_LEN\",\n );\n\n // If MESSAGE_EXPANDED_METADATA_LEN is changed, causing the assertion below to fail, then the destructuring of\n // the message encoding below must be updated as well.\n std::static_assert(\n MESSAGE_EXPANDED_METADATA_LEN == 1,\n \"unexpected value for MESSAGE_EXPANDED_METADATA_LEN\",\n );\n let mut message: [Field; (N + MESSAGE_EXPANDED_METADATA_LEN)] = std::mem::zeroed();\n\n message[0] = to_expanded_metadata(msg_type, msg_metadata);\n for i in 0..msg_content.len() {\n message[MESSAGE_EXPANDED_METADATA_LEN + i] = msg_content[i];\n }\n\n message\n}\n\n/// Decodes a standard aztec-nr message, i.e. one created via `encode_message`, returning the original encoded values.\n///\n/// Note that `encode_message` returns a fixed size array while this function takes a `BoundedVec`: this is because\n/// prior to decoding the message type is unknown, and consequentially not known at compile time. If working with\n/// fixed-size messages, consider using `BoundedVec::from_array` to convert them.\npub unconstrained fn decode_message(\n message: BoundedVec,\n) -> (u64, u64, BoundedVec) {\n assert(\n message.len() >= MESSAGE_EXPANDED_METADATA_LEN,\n f\"Invalid message: it must have at least {MESSAGE_EXPANDED_METADATA_LEN} fields\",\n );\n\n // If MESSAGE_EXPANDED_METADATA_LEN is changed, causing the assertion below to fail, then the destructuring of\n // the message encoding below must be updated as well.\n std::static_assert(\n MESSAGE_EXPANDED_METADATA_LEN == 1,\n \"unexpected value for MESSAGE_EXPANDED_METADATA_LEN\",\n );\n\n let msg_expanded_metadata = message.get(0);\n let (msg_type_id, msg_metadata) = from_expanded_metadata(msg_expanded_metadata);\n let msg_content = array::subbvec(message, MESSAGE_EXPANDED_METADATA_LEN);\n\n (msg_type_id, msg_metadata, msg_content)\n}\n\nglobal U64_SHIFT_MULTIPLIER: Field = 2.pow_32(64);\n\nfn to_expanded_metadata(msg_type: u64, msg_metadata: u64) -> Field {\n // We use multiplication instead of bit shifting operations to shift the type bits as bit shift operations are\n // expensive in circuits.\n let type_field: Field = (msg_type as Field) * U64_SHIFT_MULTIPLIER;\n let msg_metadata_field = msg_metadata as Field;\n\n type_field + msg_metadata_field\n}\n\nfn from_expanded_metadata(input: Field) -> (u64, u64) {\n input.assert_max_bit_size::<128>();\n let msg_metadata = (input as u64);\n let msg_type = ((input - (msg_metadata as Field)) / U64_SHIFT_MULTIPLIER) as u64;\n // Use division instead of bit shift since bit shifts are expensive in circuits\n (msg_type, msg_metadata)\n}\n\nmod tests {\n use crate::utils::array::subarray::subarray;\n use super::{\n decode_message, encode_message, from_expanded_metadata, MAX_MESSAGE_CONTENT_LEN,\n to_expanded_metadata,\n };\n\n global U64_MAX: u64 = (2.pow_32(64) - 1) as u64;\n global U128_MAX: Field = (2.pow_32(128) - 1);\n\n #[test]\n unconstrained fn encode_decode_empty_message(msg_type: u64, msg_metadata: u64) {\n let encoded = encode_message(msg_type, msg_metadata, []);\n let (decoded_msg_type, decoded_msg_metadata, decoded_msg_content) =\n decode_message(BoundedVec::from_array(encoded));\n\n assert_eq(decoded_msg_type, msg_type);\n assert_eq(decoded_msg_metadata, msg_metadata);\n assert_eq(decoded_msg_content.len(), 0);\n }\n\n #[test]\n unconstrained fn encode_decode_short_message(\n msg_type: u64,\n msg_metadata: u64,\n msg_content: [Field; MAX_MESSAGE_CONTENT_LEN / 2],\n ) {\n let encoded = encode_message(msg_type, msg_metadata, msg_content);\n let (decoded_msg_type, decoded_msg_metadata, decoded_msg_content) =\n decode_message(BoundedVec::from_array(encoded));\n\n assert_eq(decoded_msg_type, msg_type);\n assert_eq(decoded_msg_metadata, msg_metadata);\n assert_eq(decoded_msg_content.len(), msg_content.len());\n assert_eq(subarray(decoded_msg_content.storage(), 0), msg_content);\n }\n\n #[test]\n unconstrained fn encode_decode_full_message(\n msg_type: u64,\n msg_metadata: u64,\n msg_content: [Field; MAX_MESSAGE_CONTENT_LEN],\n ) {\n let encoded = encode_message(msg_type, msg_metadata, msg_content);\n let (decoded_msg_type, decoded_msg_metadata, decoded_msg_content) =\n decode_message(BoundedVec::from_array(encoded));\n\n assert_eq(decoded_msg_type, msg_type);\n assert_eq(decoded_msg_metadata, msg_metadata);\n assert_eq(decoded_msg_content.len(), msg_content.len());\n assert_eq(subarray(decoded_msg_content.storage(), 0), msg_content);\n }\n\n #[test]\n unconstrained fn to_expanded_metadata_packing() {\n // Test case 1: All bits set\n let packed = to_expanded_metadata(U64_MAX, U64_MAX);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 2: Only log type bits set\n let packed = to_expanded_metadata(U64_MAX, 0);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, 0);\n\n // Test case 3: Only msg_metadata bits set\n let packed = to_expanded_metadata(0, U64_MAX);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 4: No bits set\n let packed = to_expanded_metadata(0, 0);\n let (msg_type, msg_metadata) = from_expanded_metadata(packed);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, 0);\n }\n\n #[test]\n unconstrained fn from_expanded_metadata_packing() {\n // Test case 1: All bits set\n let input = U128_MAX as Field;\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 2: Only log type bits set\n let input = (U128_MAX - U64_MAX as Field);\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, U64_MAX);\n assert_eq(msg_metadata, 0);\n\n // Test case 3: Only msg_metadata bits set\n let input = U64_MAX as Field;\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, U64_MAX);\n\n // Test case 4: No bits set\n let input = 0;\n let (msg_type, msg_metadata) = from_expanded_metadata(input);\n assert_eq(msg_type, 0);\n assert_eq(msg_metadata, 0);\n }\n\n #[test]\n unconstrained fn to_from_expanded_metadata(original_msg_type: u64, original_msg_metadata: u64) {\n let packed = to_expanded_metadata(original_msg_type, original_msg_metadata);\n let (unpacked_msg_type, unpacked_msg_metadata) = from_expanded_metadata(packed);\n\n assert_eq(original_msg_type, unpacked_msg_type);\n assert_eq(original_msg_metadata, unpacked_msg_metadata);\n }\n}\n" - }, - "117": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/encryption/aes128.nr", - "source": "use dep::protocol_types::{\n address::AztecAddress,\n constants::{\n GENERATOR_INDEX__SYMMETRIC_KEY, GENERATOR_INDEX__SYMMETRIC_KEY_2,\n PRIVATE_LOG_CIPHERTEXT_LEN,\n },\n hash::poseidon2_hash_with_separator,\n point::Point,\n};\n\nuse crate::{\n keys::{\n ecdh_shared_secret::derive_ecdh_shared_secret_using_aztec_address,\n ephemeral::generate_ephemeral_key_pair,\n },\n messages::{\n encryption::log_encryption::{\n EPH_PK_SIGN_BYTE_SIZE_IN_BYTES, EPH_PK_X_SIZE_IN_FIELDS,\n HEADER_CIPHERTEXT_SIZE_IN_BYTES, LogEncryption, PRIVATE_LOG_PLAINTEXT_SIZE_IN_FIELDS,\n },\n logs::arithmetic_generics_utils::{\n get_arr_of_size__log_bytes__from_PT, get_arr_of_size__log_bytes_padding__from_PT,\n },\n },\n oracle::{aes128_decrypt::aes128_decrypt_oracle, shared_secret::get_shared_secret},\n utils::{\n array,\n conversion::{\n bytes_to_fields::{bytes_from_fields, bytes_to_fields},\n fields_to_bytes::{fields_from_bytes, fields_to_bytes},\n },\n point::{get_sign_of_point, point_from_x_coord_and_sign},\n random::get_random_bytes,\n },\n};\n\nuse std::aes128::aes128_encrypt;\n\n/**\n * Computes N close-to-uniformly-random 256 bits from a given ECDH shared_secret.\n *\n * NEVER re-use the same iv and sym_key.\n * DO NOT call this function more than once with the same shared_secret.\n *\n * This function is only known to be safe if shared_secret is computed by combining a \n * random ephemeral key with an address point. See big comment within the body of the function.\n * See big comment within the body of the function.\n */\nfn extract_many_close_to_uniformly_random_256_bits_from_ecdh_shared_secret_using_poseidon2_unsafe(\n shared_secret: Point,\n) -> [[u8; 32]; N] {\n /*\n * Unsafe because of https://eprint.iacr.org/2010/264.pdf Page 13, Lemma 2 (and the * two paragraphs below it).\n *\n * If you call this function, you need to be careful and aware of how the arg\n * `shared_secret` has been derived.\n *\n * The paper says that the way you derive aes keys and IVs should be fine with poseidon2\n * (modelled as a RO), as long as you _don't_ use Poseidon2 as a PRG to generate the * two exponents x & y which multiply to the shared secret S:\n *\n * S = [x*y]*G.\n *\n * (Otherwise, you would have to \"key\" poseidon2, i.e. generate a uniformly string K\n * which can be public and compute Hash(x) as poseidon(K,x)).\n * In that lemma, k would be 2*254=508, and m would be the number of points on the * grumpkin curve (which is close to r according to the Hasse bound).\n *\n * Our shared secret S is [esk * address_sk] * G, and the question is: * Can we compute hash(S) using poseidon2 instead of sha256?\n *\n * Well, esk is random and not generated with poseidon2, so that's good.\n * What about address_sk?\n * Well, address_sk = poseidon2(stuff) + ivsk, so there was some\n * discussion about whether address_sk is independent of poseidon2.\n * Given that ivsk is random and independent of poseidon2, the address_sk is also\n * independent of poseidon2.\n *\n * Tl;dr: we believe it's safe to hash S = [esk * address_sk] * G using poseidon2,\n * in order to derive a symmetric key.\n *\n * If you're calling this function for a differently-derived `shared_secret`, be\n * careful.\n *\n */\n\n /* The output of this function needs to be 32 random bytes.\n * A single field won't give us 32 bytes of entropy.\n * So we compute two \"random\" fields, by poseidon-hashing with two different\n * generators.\n * We then extract the last 16 (big endian) bytes of each \"random\" field.\n * Note: we use to_be_bytes because it's slightly more efficient. But we have to\n * be careful not to take bytes from the \"big end\", because the \"big\" byte is\n * not uniformly random over the byte: it only has < 6 bits of randomness, because\n * it's the big end of a 254-bit field element.\n */\n\n let mut all_bytes: [[u8; 32]; N] = std::mem::zeroed();\n // We restrict N to be < 2^8, because of how we compute the domain separator\n // from k below (where k <= N must be 8 bits). In practice, it's extremely\n // unlikely that an app will want to compute >= 256 ciphertexts.\n std::static_assert(N < 256, \"N too large\");\n for k in 0..N {\n // We augment the domain separator with the loop index, so that we can\n // generate N lots of randomness.\n let k_shift = (k as u16 << 8);\n let separator_1 = k_shift + GENERATOR_INDEX__SYMMETRIC_KEY as u16;\n let separator_2 = k_shift + GENERATOR_INDEX__SYMMETRIC_KEY_2 as u16;\n\n let rand1: Field =\n poseidon2_hash_with_separator([shared_secret.x, shared_secret.y], separator_1);\n let rand2: Field =\n poseidon2_hash_with_separator([shared_secret.x, shared_secret.y], separator_2);\n\n let rand1_bytes: [u8; 32] = rand1.to_be_bytes();\n let rand2_bytes: [u8; 32] = rand2.to_be_bytes();\n\n let mut bytes: [u8; 32] = [0; 32];\n for i in 0..16 {\n // We take bytes from the \"little end\" of the be-bytes arrays:\n let j = 32 - i - 1;\n bytes[i] = rand1_bytes[j];\n bytes[16 + i] = rand2_bytes[j];\n }\n\n all_bytes[k] = bytes;\n }\n\n all_bytes\n}\n\nfn derive_aes_symmetric_key_and_iv_from_uniformly_random_256_bits(\n many_random_256_bits: [[u8; 32]; N],\n) -> [([u8; 16], [u8; 16]); N] {\n // Many (sym_key, iv) pairs:\n let mut many_pairs: [([u8; 16], [u8; 16]); N] = std::mem::zeroed();\n for k in 0..N {\n let random_256_bits = many_random_256_bits[k];\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n for i in 0..16 {\n sym_key[i] = random_256_bits[i];\n iv[i] = random_256_bits[i + 16];\n }\n many_pairs[k] = (sym_key, iv);\n }\n\n many_pairs\n}\n\npub fn derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_poseidon2_unsafe(\n shared_secret: Point,\n) -> [([u8; 16], [u8; 16]); N] {\n let many_random_256_bits: [[u8; 32]; N] = extract_many_close_to_uniformly_random_256_bits_from_ecdh_shared_secret_using_poseidon2_unsafe(\n shared_secret,\n );\n\n derive_aes_symmetric_key_and_iv_from_uniformly_random_256_bits(many_random_256_bits)\n}\n\npub struct AES128 {}\n\nimpl LogEncryption for AES128 {\n fn encrypt_log(\n plaintext: [Field; PlaintextLen],\n recipient: AztecAddress,\n ) -> [Field; PRIVATE_LOG_CIPHERTEXT_LEN] {\n // AES 128 operates on bytes, not fields, so we need to convert the fields to bytes.\n // (This process is then reversed when processing the log in `do_process_log`)\n let plaintext_bytes = fields_to_bytes(plaintext);\n\n // *****************************************************************************\n // Compute the shared secret\n // *****************************************************************************\n\n let (eph_sk, eph_pk) = generate_ephemeral_key_pair();\n\n let eph_pk_sign_byte: u8 = get_sign_of_point(eph_pk) as u8;\n\n // (not to be confused with the tagging shared secret)\n let ciphertext_shared_secret =\n derive_ecdh_shared_secret_using_aztec_address(eph_sk, recipient);\n // TODO: also use this shared secret for deriving note randomness.\n\n // *****************************************************************************\n // Convert the plaintext into whatever format the encryption function expects\n // *****************************************************************************\n\n // Already done for this strategy: AES expects bytes.\n\n // *****************************************************************************\n // Encrypt the plaintext\n // *****************************************************************************\n\n // It is safe to call the `unsafe` function here, because we know the `shared_secret`\n // was derived using an AztecAddress (the recipient). See the block comment\n // at the start of this unsafe target function for more info.\n let pairs = derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_poseidon2_unsafe::<2>(\n ciphertext_shared_secret,\n );\n let (body_sym_key, body_iv) = pairs[0];\n let (header_sym_key, header_iv) = pairs[1];\n\n let ciphertext_bytes = aes128_encrypt(plaintext_bytes, body_iv, body_sym_key);\n\n // |full_pt| = |pt_length| + |pt|\n // |pt_aes_padding| = 16 - (|full_pt| % 16)\n // or... since a % b is the same as a - b * (a // b) (integer division), so:\n // |pt_aes_padding| = 16 - (|full_pt| - 16 * (|full_pt| // 16))\n // |ct| = |full_pt| + |pt_aes_padding|\n // = |full_pt| + 16 - (|full_pt| - 16 * (|full_pt| // 16))\n // = 16 + 16 * (|full_pt| // 16)\n // = 16 * (1 + |full_pt| // 16)\n assert(ciphertext_bytes.len() == 16 * (1 + (PlaintextLen * 32) / 16));\n\n // *****************************************************************************\n // Compute the header ciphertext\n // *****************************************************************************\n\n // Header contains only the length of the ciphertext stored in 2 bytes.\n let mut header_plaintext: [u8; 2] = [0 as u8; 2];\n let ciphertext_bytes_length = ciphertext_bytes.len();\n header_plaintext[0] = (ciphertext_bytes_length >> 8) as u8;\n header_plaintext[1] = ciphertext_bytes_length as u8;\n\n // Note: the aes128_encrypt builtin fn automatically appends bytes to the\n // input, according to pkcs#7; hence why the output `header_ciphertext_bytes` is 16\n // bytes larger than the input in this case.\n let header_ciphertext_bytes = aes128_encrypt(header_plaintext, header_iv, header_sym_key);\n // I recall that converting a slice to an array incurs constraints, so I'll check the length this way instead:\n assert(header_ciphertext_bytes.len() == HEADER_CIPHERTEXT_SIZE_IN_BYTES);\n\n // *****************************************************************************\n // Prepend / append more bytes of data to the ciphertext, before converting back\n // to fields.\n // *****************************************************************************\n\n let mut log_bytes_padding_to_mult_31 =\n get_arr_of_size__log_bytes_padding__from_PT::();\n // Safety: this randomness won't be constrained to be random. It's in the\n // interest of the executor of this fn to encrypt with random bytes.\n log_bytes_padding_to_mult_31 = unsafe { get_random_bytes() };\n\n let mut log_bytes = get_arr_of_size__log_bytes__from_PT::();\n\n assert(\n log_bytes.len() % 31 == 0,\n \"Unexpected error: log_bytes.len() should be divisible by 31, by construction.\",\n );\n\n log_bytes[0] = eph_pk_sign_byte;\n let mut offset = 1;\n for i in 0..header_ciphertext_bytes.len() {\n log_bytes[offset + i] = header_ciphertext_bytes[i];\n }\n offset += header_ciphertext_bytes.len();\n\n for i in 0..ciphertext_bytes.len() {\n log_bytes[offset + i] = ciphertext_bytes[i];\n }\n offset += ciphertext_bytes.len();\n\n for i in 0..log_bytes_padding_to_mult_31.len() {\n log_bytes[offset + i] = log_bytes_padding_to_mult_31[i];\n }\n\n assert(\n offset + log_bytes_padding_to_mult_31.len() == log_bytes.len(),\n \"Something has gone wrong\",\n );\n\n // *****************************************************************************\n // Convert bytes back to fields\n // *****************************************************************************\n\n // TODO(#12749): As Mike pointed out, we need to make logs produced by different encryption schemes\n // indistinguishable from each other and for this reason the output here and in the last for-loop of this function\n // should cover a full field.\n let log_bytes_as_fields = bytes_to_fields(log_bytes);\n\n // *****************************************************************************\n // Prepend / append fields, to create the final log\n // *****************************************************************************\n\n let mut ciphertext: [Field; PRIVATE_LOG_CIPHERTEXT_LEN] = [0; PRIVATE_LOG_CIPHERTEXT_LEN];\n\n ciphertext[0] = eph_pk.x;\n\n let mut offset = 1;\n for i in 0..log_bytes_as_fields.len() {\n ciphertext[offset + i] = log_bytes_as_fields[i];\n }\n offset += log_bytes_as_fields.len();\n\n for i in offset..PRIVATE_LOG_CIPHERTEXT_LEN {\n // We need to get a random value that fits in 31 bytes to not leak information about the size of the log\n // (all the \"real\" log fields contain at most 31 bytes because of the way we convert the bytes to fields).\n // TODO(#12749): Long term, this is not a good solution.\n\n // Safety: we assume that the sender wants for the log to be private - a malicious one could simply reveal its\n // contents publicly. It is therefore fine to trust the sender to provide random padding.\n let field_bytes = unsafe { get_random_bytes::<31>() };\n ciphertext[i] = Field::from_be_bytes::<31>(field_bytes);\n }\n\n ciphertext\n }\n\n unconstrained fn decrypt_log(\n ciphertext: BoundedVec,\n recipient: AztecAddress,\n ) -> BoundedVec {\n let eph_pk_x = ciphertext.get(0);\n\n let ciphertext_without_eph_pk_x_fields = array::subbvec::(\n ciphertext,\n EPH_PK_X_SIZE_IN_FIELDS,\n );\n\n // Convert the ciphertext represented as fields to a byte representation (its original format)\n let ciphertext_without_eph_pk_x = bytes_from_fields(ciphertext_without_eph_pk_x_fields);\n\n // First byte of the ciphertext represents the ephemeral public key sign\n let eph_pk_sign_bool = ciphertext_without_eph_pk_x.get(0) != 0;\n // With the sign and the x-coordinate of the ephemeral public key, we can reconstruct the point\n let eph_pk = point_from_x_coord_and_sign(eph_pk_x, eph_pk_sign_bool);\n\n // Derive shared secret\n let ciphertext_shared_secret = get_shared_secret(recipient, eph_pk);\n\n // Derive symmetric keys:\n let pairs = derive_aes_symmetric_key_and_iv_from_ecdh_shared_secret_using_poseidon2_unsafe::<2>(\n ciphertext_shared_secret,\n );\n let (body_sym_key, body_iv) = pairs[0];\n let (header_sym_key, header_iv) = pairs[1];\n\n // Extract the header ciphertext\n let header_start = EPH_PK_SIGN_BYTE_SIZE_IN_BYTES; // Skip eph_pk_sign byte\n let header_ciphertext: [u8; HEADER_CIPHERTEXT_SIZE_IN_BYTES] =\n array::subarray(ciphertext_without_eph_pk_x.storage(), header_start);\n // We need to convert the array to a BoundedVec because the oracle expects a BoundedVec as it's designed to work\n // with logs with unknown length at compile time. This would not be necessary here as the header ciphertext length\n // is fixed. But we do it anyway to not have to have duplicate oracles.\n let header_ciphertext_bvec =\n BoundedVec::::from_array(header_ciphertext);\n\n // Decrypt header\n let header_plaintext =\n aes128_decrypt_oracle(header_ciphertext_bvec, header_iv, header_sym_key);\n\n // Extract ciphertext length from header (2 bytes, big-endian)\n let ciphertext_length =\n ((header_plaintext.get(0) as u32) << 8) | (header_plaintext.get(1) as u32);\n\n // Extract and decrypt main ciphertext\n let ciphertext_start = header_start + HEADER_CIPHERTEXT_SIZE_IN_BYTES;\n let ciphertext_with_padding: [u8; (PRIVATE_LOG_CIPHERTEXT_LEN - EPH_PK_X_SIZE_IN_FIELDS) * 31 - HEADER_CIPHERTEXT_SIZE_IN_BYTES - EPH_PK_SIGN_BYTE_SIZE_IN_BYTES] =\n array::subarray(ciphertext_without_eph_pk_x.storage(), ciphertext_start);\n let ciphertext: BoundedVec =\n BoundedVec::from_parts(ciphertext_with_padding, ciphertext_length);\n\n // Decrypt main ciphertext and return it\n let plaintext_bytes = aes128_decrypt_oracle(ciphertext, body_iv, body_sym_key);\n\n // Each field of the original note log was serialized to 32 bytes so we convert the bytes back to fields.\n fields_from_bytes(plaintext_bytes)\n }\n}\n\nmod test {\n use crate::{\n keys::ecdh_shared_secret::derive_ecdh_shared_secret_using_aztec_address,\n messages::encryption::log_encryption::{LogEncryption, PRIVATE_LOG_PLAINTEXT_SIZE_IN_FIELDS},\n test::helpers::test_environment::TestEnvironment,\n };\n use super::AES128;\n use protocol_types::{\n address::AztecAddress,\n indexed_tagging_secret::IndexedTaggingSecret,\n traits::{Deserialize, FromField},\n };\n use std::{embedded_curve_ops::EmbeddedCurveScalar, test::OracleMock};\n\n #[test]\n unconstrained fn encrypt_decrypt_log() {\n let env = TestEnvironment::new();\n\n // Log decryption requires oracles that are only available during private execution\n env.private_context(|_| {\n let plaintext = [1, 2, 3];\n\n let recipient = AztecAddress::from_field(\n 0x25afb798ea6d0b8c1618e50fdeafa463059415013d3b7c75d46abf5e242be70c,\n );\n\n // Mock random values for deterministic test\n let eph_sk = 0x1358d15019d4639393d62b97e1588c095957ce74a1c32d6ec7d62fe6705d9538;\n let _ = OracleMock::mock(\"utilityGetRandomField\").returns(eph_sk).times(1);\n\n let randomness = 0x0101010101010101010101010101010101010101010101010101010101010101;\n let _ = OracleMock::mock(\"utilityGetRandomField\").returns(randomness).times(1000000);\n\n let _ = OracleMock::mock(\"utilityGetIndexedTaggingSecretAsSender\").returns(\n IndexedTaggingSecret::deserialize([69420, 1337]),\n );\n let _ = OracleMock::mock(\"privateIncrementAppTaggingSecretIndexAsSender\").returns(());\n\n // Encrypt the log\n let encrypted_log = BoundedVec::from_array(AES128::encrypt_log(plaintext, recipient));\n\n // Mock shared secret for deterministic test\n let shared_secret = derive_ecdh_shared_secret_using_aztec_address(\n EmbeddedCurveScalar::from_field(eph_sk),\n recipient,\n );\n let _ = OracleMock::mock(\"utilityGetSharedSecret\").returns(shared_secret);\n\n // Decrypt the log\n let decrypted = AES128::decrypt_log(encrypted_log, recipient);\n\n // The decryption function spits out a BoundedVec because it's designed to work with logs with unknown length\n // at compile time. For this reason we need to convert the original input to a BoundedVec.\n let plaintext_bvec =\n BoundedVec::::from_array(plaintext);\n\n // Verify decryption matches original plaintext\n assert_eq(\n decrypted,\n plaintext_bvec,\n \"Decrypted bytes should match original plaintext\",\n );\n\n // The following is a workaround of \"struct is never constructed\" Noir compilation error (we only ever use\n // static methods of the struct).\n let _ = AES128 {};\n });\n }\n}\n" - }, - "12": { - "path": "std/convert.nr", - "source": "// docs:start:from-trait\npub trait From {\n fn from(input: T) -> Self;\n}\n// docs:end:from-trait\n\nimpl From for T {\n fn from(input: T) -> T {\n input\n }\n}\n\n// docs:start:into-trait\npub trait Into {\n fn into(self) -> T;\n}\n\nimpl Into for U\nwhere\n T: From,\n{\n fn into(self) -> T {\n T::from(self)\n }\n}\n// docs:end:into-trait\n\n// docs:start:from-impls\n// Unsigned integers\n\nimpl From for u16 {\n fn from(value: u8) -> u16 {\n value as u16\n }\n}\n\nimpl From for u32 {\n fn from(value: u8) -> u32 {\n value as u32\n }\n}\n\nimpl From for u32 {\n fn from(value: u16) -> u32 {\n value as u32\n }\n}\n\nimpl From for u64 {\n fn from(value: u8) -> u64 {\n value as u64\n }\n}\n\nimpl From for u64 {\n fn from(value: u16) -> u64 {\n value as u64\n }\n}\n\nimpl From for u64 {\n fn from(value: u32) -> u64 {\n value as u64\n }\n}\n\nimpl From for u128 {\n fn from(value: u8) -> u128 {\n value as u128\n }\n}\n\nimpl From for u128 {\n fn from(value: u16) -> u128 {\n value as u128\n }\n}\n\nimpl From for u128 {\n fn from(value: u32) -> u128 {\n value as u128\n }\n}\nimpl From for u128 {\n fn from(value: u64) -> u128 {\n value as u128\n }\n}\n\nimpl From for Field {\n fn from(value: u8) -> Field {\n value as Field\n }\n}\n\nimpl From for Field {\n fn from(value: u16) -> Field {\n value as Field\n }\n}\n\nimpl From for Field {\n fn from(value: u32) -> Field {\n value as Field\n }\n}\nimpl From for Field {\n fn from(value: u64) -> Field {\n value as Field\n }\n}\n\nimpl From for Field {\n fn from(value: u128) -> Field {\n value as Field\n }\n}\n\n// Signed integers\n\nimpl From for i16 {\n fn from(value: i8) -> i16 {\n value as i16\n }\n}\n\nimpl From for i32 {\n fn from(value: i8) -> i32 {\n value as i32\n }\n}\n\nimpl From for i32 {\n fn from(value: i16) -> i32 {\n value as i32\n }\n}\n\nimpl From for i64 {\n fn from(value: i8) -> i64 {\n value as i64\n }\n}\n\nimpl From for i64 {\n fn from(value: i16) -> i64 {\n value as i64\n }\n}\n\nimpl From for i64 {\n fn from(value: i32) -> i64 {\n value as i64\n }\n}\n\n// Booleans\nimpl From for u8 {\n fn from(value: bool) -> u8 {\n value as u8\n }\n}\nimpl From for u16 {\n fn from(value: bool) -> u16 {\n value as u16\n }\n}\nimpl From for u32 {\n fn from(value: bool) -> u32 {\n value as u32\n }\n}\nimpl From for u64 {\n fn from(value: bool) -> u64 {\n value as u64\n }\n}\nimpl From for u128 {\n fn from(value: bool) -> u128 {\n value as u128\n }\n}\nimpl From for i8 {\n fn from(value: bool) -> i8 {\n value as i8\n }\n}\nimpl From for i16 {\n fn from(value: bool) -> i16 {\n value as i16\n }\n}\nimpl From for i32 {\n fn from(value: bool) -> i32 {\n value as i32\n }\n}\nimpl From for i64 {\n fn from(value: bool) -> i64 {\n value as i64\n }\n}\nimpl From for Field {\n fn from(value: bool) -> Field {\n value as Field\n }\n}\n// docs:end:from-impls\n\n/// A generic interface for casting between primitive types,\n/// equivalent of using the `as` keyword between values.\n///\n/// # Example\n///\n/// ```\n/// let x: Field = 1234567890;\n/// let y: u8 = x as u8;\n/// let z: u8 = x.as_();\n/// assert_eq(y, z);\n/// ```\npub trait AsPrimitive {\n /// The equivalent of doing `self as T`.\n fn as_(self) -> T;\n}\n\n#[generate_as_primitive_impls]\ncomptime fn generate_as_primitive_impls(_: FunctionDefinition) -> Quoted {\n let types = [\n quote { bool },\n quote { u8 },\n quote { u16 },\n quote { u32 },\n quote { u64 },\n quote { u128 },\n quote { i8 },\n quote { i16 },\n quote { i32 },\n quote { i64 },\n ];\n\n let mut impls = &[];\n for type1 in types {\n for type2 in types {\n let body = if type1 == type2 {\n quote { self }\n } else if type1 == quote { bool } {\n quote { self != 0 }\n } else {\n quote { self as $type1 }\n };\n\n impls = impls.push_back(\n quote {\n impl AsPrimitive<$type1> for $type2 {\n fn as_(self) -> $type1 {\n $body\n }\n }\n },\n );\n }\n }\n\n let u_types =\n [quote { bool }, quote { u8 }, quote { u16 }, quote { u32 }, quote { u64 }, quote { u128 }];\n\n for type2 in u_types {\n let body = quote { self as Field };\n\n impls = impls.push_back(\n quote {\n impl AsPrimitive for $type2 {\n fn as_(self) -> Field {\n $body\n }\n }\n },\n );\n }\n\n for type1 in u_types {\n let body = if type1 == quote { bool } {\n quote { self != 0 }\n } else {\n quote { self as $type1 }\n };\n\n impls = impls.push_back(\n quote {\n impl AsPrimitive<$type1> for Field {\n fn as_(self) -> $type1 {\n $body\n }\n }\n },\n );\n }\n\n impls.join(quote {})\n}\n" - }, - "133": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/messages/processing/mod.nr", - "source": "pub(crate) mod event_validation_request;\npub mod message_context;\npub(crate) mod note_validation_request;\npub(crate) mod log_retrieval_request;\npub(crate) mod log_retrieval_response;\npub(crate) mod pending_tagged_log;\n\nuse crate::{\n capsules::CapsuleArray,\n event::event_selector::EventSelector,\n messages::{\n discovery::{\n partial_notes::DeliveredPendingPartialNote, private_events::MAX_EVENT_SERIALIZED_LEN,\n private_notes::MAX_NOTE_PACKED_LEN,\n },\n processing::{\n log_retrieval_request::LogRetrievalRequest,\n log_retrieval_response::LogRetrievalResponse,\n note_validation_request::NoteValidationRequest, pending_tagged_log::PendingTaggedLog,\n },\n },\n oracle,\n};\nuse event_validation_request::EventValidationRequest;\nuse protocol_types::{address::AztecAddress, hash::sha256_to_field};\n\n// Base slot for the pending tagged log array to which the fetch_tagged_logs oracle inserts found private logs.\nglobal PENDING_TAGGED_LOG_ARRAY_BASE_SLOT: Field =\n sha256_to_field(\"AZTEC_NR::PENDING_TAGGED_LOG_ARRAY_BASE_SLOT\".as_bytes());\n\nglobal NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\nglobal EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\nglobal LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\nglobal LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT: Field = sha256_to_field(\n \"AZTEC_NR::LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT\".as_bytes(),\n);\n\n/// Searches for private logs emitted by `contract_address` that might contain messages for one of the local accounts,\n/// and stores them in a `CapsuleArray` which is then returned.\npub(crate) unconstrained fn get_private_logs(\n contract_address: AztecAddress,\n) -> CapsuleArray {\n // We will eventually perform log discovery via tagging here, but for now we simply call the `fetchTaggedLogs`\n // oracle. This makes PXE synchronize tags, download logs and store the pending tagged logs in a capsule array.\n oracle::message_processing::fetch_tagged_logs(PENDING_TAGGED_LOG_ARRAY_BASE_SLOT);\n\n CapsuleArray::at(contract_address, PENDING_TAGGED_LOG_ARRAY_BASE_SLOT)\n}\n\n/// Enqueues a note for validation by PXE, so that it becomes aware of a note's existence allowing for later retrieval\n/// via `get_notes` oracle. The note will be scoped to `contract_address`, meaning other contracts will not be able to\n/// access it unless authorized.\n///\n/// In order for the note validation and insertion to occur, `validate_enqueued_notes_and_events` must be later called.\n/// For optimal performance, accumulate as many note validation requests as possible and then validate them all at the\n/// end (which results in PXE minimizing the number of network round-trips).\n///\n/// The `packed_note` is what `getNotes` will later return. PXE indexes notes by `storage_slot`, so this value\n/// is typically used to filter notes that correspond to different state variables. `note_hash` and `nullifier` are\n/// the inner hashes, i.e. the raw hashes returned by `NoteHash::compute_note_hash` and\n/// `NoteHash::compute_nullifier`. PXE will verify that the siloed unique note hash was inserted into the tree\n/// at `tx_hash`, and will store the nullifier to later check for nullification.\n///\n/// `recipient` is the account to which the note was sent to. Other accounts will not be able to access this note (e.g.\n/// other accounts will not be able to see one another's token balance notes, even in the same PXE) unless authorized.\npub(crate) unconstrained fn enqueue_note_for_validation(\n contract_address: AztecAddress,\n storage_slot: Field,\n note_nonce: Field,\n packed_note: BoundedVec,\n note_hash: Field,\n nullifier: Field,\n tx_hash: Field,\n recipient: AztecAddress,\n) {\n // We store requests in a `CapsuleArray`, which PXE will later read from and deserialize into its version of the\n // Noir `NoteValidationRequest`\n CapsuleArray::at(contract_address, NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT).push(\n NoteValidationRequest {\n contract_address,\n storage_slot,\n note_nonce,\n packed_note,\n note_hash,\n nullifier,\n tx_hash,\n recipient,\n },\n )\n}\n\n/// Enqueues an event for validation by PXE, so that it can be efficiently validated and then inserted into the event\n/// store.\n///\n/// In order for the event validation and insertion to occur, `validate_enqueued_notes_and_events` must be later\n/// called. For optimal performance, accumulate as many event validation requests as possible and then validate them\n/// all at the end (which results in PXE minimizing the number of network round-trips).\npub(crate) unconstrained fn enqueue_event_for_validation(\n contract_address: AztecAddress,\n event_type_id: EventSelector,\n serialized_event: BoundedVec,\n event_commitment: Field,\n tx_hash: Field,\n recipient: AztecAddress,\n) {\n // We store requests in a `CapsuleArray`, which PXE will later read from and deserialize into its version of the\n // Noir `EventValidationRequest`\n CapsuleArray::at(contract_address, EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT).push(\n EventValidationRequest {\n contract_address,\n event_type_id,\n serialized_event,\n event_commitment,\n tx_hash,\n recipient,\n },\n )\n}\n\n/// Validates all note and event validation requests enqueued via `enqueue_note_for_validation` and\n/// `enqueue_event_for_validation`, inserting them into the note database and event store respectively, making them\n/// queryable via `get_notes` oracle and our TS API (PXE::getPrivateEvents).\n///\n/// This automatically clears both validation request queues, so no further work needs to be done by the caller.\npub(crate) unconstrained fn validate_enqueued_notes_and_events(contract_address: AztecAddress) {\n oracle::message_processing::validate_enqueued_notes_and_events(\n contract_address,\n NOTE_VALIDATION_REQUESTS_ARRAY_BASE_SLOT,\n EVENT_VALIDATION_REQUESTS_ARRAY_BASE_SLOT,\n );\n}\n\n/// Efficiently queries the node for logs that result in the completion of all `DeliveredPendingPartialNote`s stored in\n/// a `CapsuleArray` by performing all node communication concurrently. Returns a second `CapsuleArray` with Options for\n/// the responses that correspond to the pending partial notes at the same index.\n///\n/// For example, given an array with pending partial notes `[ p1, p2, p3 ]`, where `p1` and `p3` have corresponding\n/// completion logs but `p2` does not, the returned `CapsuleArray` will have contents\n/// `[some(p1_log), none(), some(p3_log)]`.\npub(crate) unconstrained fn get_pending_partial_notes_completion_logs(\n contract_address: AztecAddress,\n pending_partial_notes: CapsuleArray,\n) -> CapsuleArray> {\n let log_retrieval_requests =\n CapsuleArray::at(contract_address, LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT);\n\n // We create a LogRetrievalRequest for each PendingPartialNote in the CapsuleArray. Because we need the indices in\n // the request array to match the indices in the partial note array, we can't use CapsuleArray::for_each, as that\n // function has arbitrary iteration order. Instead, we manually iterate the array from the beginning and push into\n // the requests array, which we expect to be empty.\n let mut i = 0;\n let pending_partial_notes_count = pending_partial_notes.len();\n while i < pending_partial_notes_count {\n let pending_partial_note = pending_partial_notes.get(i);\n log_retrieval_requests.push(\n LogRetrievalRequest {\n contract_address,\n unsiloed_tag: pending_partial_note.note_completion_log_tag,\n },\n );\n i += 1;\n }\n\n oracle::message_processing::bulk_retrieve_logs(\n contract_address,\n LOG_RETRIEVAL_REQUESTS_ARRAY_BASE_SLOT,\n LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT,\n );\n\n CapsuleArray::at(contract_address, LOG_RETRIEVAL_RESPONSES_ARRAY_BASE_SLOT)\n}\n" - }, - "145": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/note/note_metadata.nr", - "source": "use protocol_types::traits::{Packable, Serialize};\n\n// There's temporarily quite a bit of boilerplate here because Noir does not yet support enums. This file will\n// eventually be simplified into something closer to:\n//\n// pub enum NoteMetadata {\n// PendingSamePhase{ note_hash_counter: u32 },\n// PendingOtherPhase{ note_hash_counter: u32, note_nonce: Field },\n// Settled{ note_nonce: Field },\n// }\n//\n// For now, we have `NoteMetadata` acting as a sort of tagged union.\n\nstruct NoteStageEnum {\n /// A note that was created in the transaction that is currently being executed, during the current execution phase,\n /// i.e. non-revertible or revertible.\n ///\n /// These notes are not yet in the note hash tree, though they will be inserted unless nullified in this transaction\n /// (becoming a transient note).\n PENDING_SAME_PHASE: u8,\n /// A note that was created in the transaction that is currently being executed, during the previous execution\n /// phase. Because there are only two phases and their order is always the same (first non-revertible and then\n /// revertible) this implies that the note was created in the non-revertible phase, and that the current phase is\n /// the revertible phase.\n ///\n /// These notes are not yet in the note hash tree, though they will be inserted **even if nullified in this\n /// transaction**. This means that they must be nullified as if they were settled (i.e. using the unique note hash)\n /// in order to avoid double spends once they become settled.\n PENDING_PREVIOUS_PHASE: u8,\n /// A note that was created in a prior transaction and is therefore already in the note hash tree.\n SETTLED: u8,\n}\n\nglobal NoteStage: NoteStageEnum =\n NoteStageEnum { PENDING_SAME_PHASE: 1, PENDING_PREVIOUS_PHASE: 2, SETTLED: 3 };\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a note in any of the three valid stages (pending same phase, pending previous phase, or settled). In\n/// order to access the underlying fields callers must first find the appropriate stage (e.g. via `is_settled()`) and\n/// then convert this into the appropriate type (e.g. via `to_settled()`).\n#[derive(Eq, Serialize, Packable)]\npub struct NoteMetadata {\n stage: u8,\n maybe_note_nonce: Field,\n}\n\nimpl NoteMetadata {\n /// Constructs a `NoteMetadata` object from optional note hash counter and nonce. Both a zero note hash counter and\n /// a zero nonce are invalid, so those are used to signal non-existent values.\n pub fn from_raw_data(nonzero_note_hash_counter: bool, maybe_note_nonce: Field) -> Self {\n if nonzero_note_hash_counter {\n if maybe_note_nonce == 0 {\n Self { stage: NoteStage.PENDING_SAME_PHASE, maybe_note_nonce }\n } else {\n Self { stage: NoteStage.PENDING_PREVIOUS_PHASE, maybe_note_nonce }\n }\n } else if maybe_note_nonce != 0 {\n Self { stage: NoteStage.SETTLED, maybe_note_nonce }\n } else {\n panic(\n f\"Note has a zero note hash counter and no nonce - existence cannot be proven\",\n )\n }\n }\n\n /// Returns true if the note is pending **and** from the same phase, i.e. if it's been created in the current\n /// transaction during the current execution phase (either non-revertible or revertible).\n pub fn is_pending_same_phase(self) -> bool {\n self.stage == NoteStage.PENDING_SAME_PHASE\n }\n\n /// Returns true if the note is pending **and** from the previous phase, i.e. if it's been created in the current\n /// transaction during an execution phase prior to the current one. Because private execution only has two phases\n /// with strict ordering, this implies that the note was created in the non-revertible phase, and that the current\n /// phase is the revertible phase.\n pub fn is_pending_previous_phase(self) -> bool {\n self.stage == NoteStage.PENDING_PREVIOUS_PHASE\n }\n\n /// Returns true if the note is settled, i.e. if it's been created in a prior transaction and is therefore already\n /// in the note hash tree.\n pub fn is_settled(self) -> bool {\n self.stage == NoteStage.SETTLED\n }\n\n /// Asserts that the metadata is that of a pending note from the same phase and converts it accordingly.\n pub fn to_pending_same_phase(self) -> PendingSamePhaseNoteMetadata {\n assert_eq(self.stage, NoteStage.PENDING_SAME_PHASE);\n PendingSamePhaseNoteMetadata::new()\n }\n\n /// Asserts that the metadata is that of a pending note from a previous phase and converts it accordingly.\n pub fn to_pending_previous_phase(self) -> PendingPreviousPhaseNoteMetadata {\n assert_eq(self.stage, NoteStage.PENDING_PREVIOUS_PHASE);\n PendingPreviousPhaseNoteMetadata::new(self.maybe_note_nonce)\n }\n\n /// Asserts that the metadata is that of a settled note and converts it accordingly.\n pub fn to_settled(self) -> SettledNoteMetadata {\n assert_eq(self.stage, NoteStage.SETTLED);\n SettledNoteMetadata::new(self.maybe_note_nonce)\n }\n}\n\nimpl From for NoteMetadata {\n fn from(_value: PendingSamePhaseNoteMetadata) -> Self {\n NoteMetadata::from_raw_data(true, std::mem::zeroed())\n }\n}\n\nimpl From for NoteMetadata {\n fn from(value: PendingPreviousPhaseNoteMetadata) -> Self {\n NoteMetadata::from_raw_data(true, value.note_nonce())\n }\n}\n\nimpl From for NoteMetadata {\n fn from(value: SettledNoteMetadata) -> Self {\n NoteMetadata::from_raw_data(false, value.note_nonce())\n }\n}\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a pending same phase note, i.e. a note that was created in the transaction that is currently being\n/// executed during the current execution phase (either non-revertible or revertible).\npub struct PendingSamePhaseNoteMetadata {\n // This struct contains no fields since there is no metadata associated with a pending same phase note: it has no\n // nonce (since it may get squashed by a nullifier emitted in the same phase), and while it does have a note hash\n // counter we cannot constrain its value (and don't need to - only that it is non-zero).\n}\n\nimpl PendingSamePhaseNoteMetadata {\n pub fn new() -> Self {\n Self {}\n }\n}\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a pending previous phase note, i.e. a note that was created in the transaction that is currently\n/// being executed, during the previous execution phase. Because there are only two phases and their order is always the\n/// same (first non-revertible and then revertible) this implies that the note was created in the non-revertible phase,\n/// and that the current phase is the revertible phase.\npub struct PendingPreviousPhaseNoteMetadata {\n note_nonce: Field,\n // This struct does not contain a note hash counter, even though one exists for this note, because we cannot\n // constrain its value (and don't need to - only that it is non-zero).\n}\n\nimpl PendingPreviousPhaseNoteMetadata {\n pub fn new(note_nonce: Field) -> Self {\n Self { note_nonce }\n }\n\n pub fn note_nonce(self) -> Field {\n self.note_nonce\n }\n}\n\n/// The metadata required to both prove a note's existence and destroy it, by computing the correct note hash for kernel\n/// read requests, as well as the correct nullifier to avoid double-spends.\n///\n/// This represents a settled note, i.e. a note that was created in a prior transaction and is therefore already in the\n/// note hash tree.\npub struct SettledNoteMetadata {\n note_nonce: Field,\n}\n\nimpl SettledNoteMetadata {\n pub fn new(note_nonce: Field) -> Self {\n Self { note_nonce }\n }\n\n pub fn note_nonce(self) -> Field {\n self.note_nonce\n }\n}\n" - }, - "148": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/note/utils.nr", - "source": "use crate::{\n context::PrivateContext,\n note::{note_interface::NoteHash, retrieved_note::RetrievedNote},\n};\n\nuse dep::protocol_types::hash::{\n compute_siloed_note_hash, compute_siloed_nullifier, compute_unique_note_hash,\n};\n\n/// Returns the note hash that must be used to issue a private kernel read request for a note.\npub fn compute_note_hash_for_read_request(\n retrieved_note: RetrievedNote,\n storage_slot: Field,\n) -> Field\nwhere\n Note: NoteHash,\n{\n let note_hash = retrieved_note.note.compute_note_hash(storage_slot);\n\n if retrieved_note.metadata.is_settled() {\n // Settled notes are read by siloing with contract address and nonce (resulting in the final unique note hash,\n // which is already in the note hash tree).\n let siloed_note_hash = compute_siloed_note_hash(retrieved_note.contract_address, note_hash);\n compute_unique_note_hash(\n retrieved_note.metadata.to_settled().note_nonce(),\n siloed_note_hash,\n )\n } else {\n // Pending notes (both same phase and previous phase ones) re read by their non-siloed hash (not even by\n // contract address), which is what is stored in the new note hashes array (at the position hinted by note hash\n // counter).\n note_hash\n }\n}\n\n/// Returns the note hash that must be used to compute a note's nullifier when calling `NoteHash::compute_nullifier` or\n/// `NoteHash::compute_nullifier_unconstrained`.\npub fn compute_note_hash_for_nullify(\n retrieved_note: RetrievedNote,\n storage_slot: Field,\n) -> Field\nwhere\n Note: NoteHash,\n{\n compute_note_hash_for_nullify_from_read_request(\n retrieved_note,\n compute_note_hash_for_read_request(retrieved_note, storage_slot),\n )\n}\n\n/// Same as `compute_note_hash_for_nullify`, except it takes the note hash used in a read request (i.e. what\n/// `compute_note_hash_for_read_request` would return). This is useful in scenarios where that hash has already been\n/// computed to reduce constraints by reusing this value.\npub fn compute_note_hash_for_nullify_from_read_request(\n retrieved_note: RetrievedNote,\n note_hash_for_read_request: Field,\n) -> Field {\n // There is just one instance in which the note hash for nullification does not match the note hash used for a read\n // request, which is when dealing with pending previous phase notes. These had their existence proven using their\n // non-siloed note hash along with the note hash counter (like all pending notes), but since they will be\n // unconditionally inserted in the note hash tree (since they cannot be squashed) they must be nullified using the\n // *unique* note hash.\n // If we didn't, it'd be possible to emit a second different nullifier for the same note in a follow up transaction,\n // once the note is settled, resulting in a double spend.\n\n if retrieved_note.metadata.is_pending_previous_phase() {\n let siloed_note_hash =\n compute_siloed_note_hash(retrieved_note.contract_address, note_hash_for_read_request);\n let note_nonce = retrieved_note.metadata.to_pending_previous_phase().note_nonce();\n\n compute_unique_note_hash(note_nonce, siloed_note_hash)\n } else {\n note_hash_for_read_request\n }\n}\n\n/// Computes a note's siloed nullifier, i.e. the one that will be inserted into the nullifier tree.\npub fn compute_siloed_note_nullifier(\n retrieved_note: RetrievedNote,\n storage_slot: Field,\n context: &mut PrivateContext,\n) -> Field\nwhere\n Note: NoteHash,\n{\n let note_hash_for_nullify = compute_note_hash_for_nullify(retrieved_note, storage_slot);\n let inner_nullifier = retrieved_note.note.compute_nullifier(context, note_hash_for_nullify);\n\n compute_siloed_nullifier(retrieved_note.contract_address, inner_nullifier)\n}\n" - }, - "153": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/capsules.nr", - "source": "use protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}};\n\n/// Stores arbitrary information in a per-contract non-volatile database, which can later be retrieved with `load`. If\n/// data was already stored at this slot, it is overwritten.\npub unconstrained fn store(contract_address: AztecAddress, slot: Field, value: T)\nwhere\n T: Serialize,\n{\n let serialized = value.serialize();\n store_oracle(contract_address, slot, serialized);\n}\n\n/// Returns data previously stored via `storeCapsule` in the per-contract non-volatile database. Returns Option::none() if\n/// nothing was stored at the given slot.\npub unconstrained fn load(contract_address: AztecAddress, slot: Field) -> Option\nwhere\n T: Deserialize,\n{\n let serialized_option = load_oracle(contract_address, slot, ::N);\n serialized_option.map(|arr| Deserialize::deserialize(arr))\n}\n\n/// Deletes data in the per-contract non-volatile database. Does nothing if no data was present.\npub unconstrained fn delete(contract_address: AztecAddress, slot: Field) {\n delete_oracle(contract_address, slot);\n}\n\n/// Copies a number of contiguous entries in the per-contract non-volatile database. This allows for efficient data\n/// structures by avoiding repeated calls to `loadCapsule` and `storeCapsule`.\n/// Supports overlapping source and destination regions (which will result in the overlapped source values being\n/// overwritten). All copied slots must exist in the database (i.e. have been stored and not deleted)\npub unconstrained fn copy(\n contract_address: AztecAddress,\n src_slot: Field,\n dst_slot: Field,\n num_entries: u32,\n) {\n copy_oracle(contract_address, src_slot, dst_slot, num_entries);\n}\n\n#[oracle(utilityStoreCapsule)]\nunconstrained fn store_oracle(\n contract_address: AztecAddress,\n slot: Field,\n values: [Field; N],\n) {}\n\n/// We need to pass in `array_len` (the value of N) as a parameter to tell the oracle how many fields the response must\n/// have.\n///\n/// Note that the oracle returns an Option<[Field; N]> because we cannot return an Option directly. That would\n/// require for the oracle resolver to know the shape of T (e.g. if T were a struct of 3 u32 values then the expected\n/// response shape would be 3 single items, whereas it were a struct containing `u32, [Field;10], u32` then the expected\n/// shape would be single, array, single.). Instead, we return the serialization and deserialize in Noir.\n#[oracle(utilityLoadCapsule)]\nunconstrained fn load_oracle(\n contract_address: AztecAddress,\n slot: Field,\n array_len: u32,\n) -> Option<[Field; N]> {}\n\n#[oracle(utilityDeleteCapsule)]\nunconstrained fn delete_oracle(contract_address: AztecAddress, slot: Field) {}\n\n#[oracle(utilityCopyCapsule)]\nunconstrained fn copy_oracle(\n contract_address: AztecAddress,\n src_slot: Field,\n dst_slot: Field,\n num_entries: u32,\n) {}\n\nmod test {\n // These tests are sort of redundant since we already test the oracle implementation directly in TypeScript, but\n // they are cheap regardless and help ensure both that the TXE implementation works accordingly and that the Noir\n // oracles are hooked up correctly.\n\n use crate::{\n oracle::capsules::{copy, delete, load, store},\n test::{helpers::test_environment::TestEnvironment, mocks::mock_struct::MockStruct},\n };\n use protocol_types::{address::AztecAddress, traits::{FromField, ToField}};\n\n global SLOT: Field = 1;\n\n #[test]\n unconstrained fn stores_and_loads() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value);\n\n assert_eq(load(contract_address, SLOT).unwrap(), value);\n });\n }\n\n #[test]\n unconstrained fn store_overwrites() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value);\n\n let new_value = MockStruct::new(7, 8);\n store(contract_address, SLOT, new_value);\n\n assert_eq(load(contract_address, SLOT).unwrap(), new_value);\n });\n }\n\n #[test]\n unconstrained fn loads_empty_slot() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let loaded_value: Option = load(contract_address, SLOT);\n assert_eq(loaded_value, Option::none());\n });\n }\n\n #[test]\n unconstrained fn deletes_stored_value() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let value = MockStruct::new(5, 6);\n store(contract_address, SLOT, value);\n delete(contract_address, SLOT);\n\n let loaded_value: Option = load(contract_address, SLOT);\n assert_eq(loaded_value, Option::none());\n });\n }\n\n #[test]\n unconstrained fn deletes_empty_slot() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n delete(contract_address, SLOT);\n let loaded_value: Option = load(contract_address, SLOT);\n assert_eq(loaded_value, Option::none());\n });\n }\n\n #[test]\n unconstrained fn copies_non_overlapping_values() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let src = 5;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0]);\n store(contract_address, src + 1, values[1]);\n store(contract_address, src + 2, values[2]);\n\n let dst = 10;\n copy(contract_address, src, dst, 3);\n\n assert_eq(load(contract_address, dst).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2).unwrap(), values[2]);\n });\n }\n\n #[test]\n unconstrained fn copies_overlapping_values_with_src_ahead() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let src = 1;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0]);\n store(contract_address, src + 1, values[1]);\n store(contract_address, src + 2, values[2]);\n\n let dst = 2;\n copy(contract_address, src, dst, 3);\n\n assert_eq(load(contract_address, dst).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2).unwrap(), values[2]);\n\n // src[1] and src[2] should have been overwritten since they are also dst[0] and dst[1]\n assert_eq(load(contract_address, src).unwrap(), values[0]); // src[0] (unchanged)\n assert_eq(load(contract_address, src + 1).unwrap(), values[0]); // dst[0]\n assert_eq(load(contract_address, src + 2).unwrap(), values[1]); // dst[1]\n });\n }\n\n #[test]\n unconstrained fn copies_overlapping_values_with_dst_ahead() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let src = 2;\n\n let values = [MockStruct::new(5, 6), MockStruct::new(7, 8), MockStruct::new(9, 10)];\n store(contract_address, src, values[0]);\n store(contract_address, src + 1, values[1]);\n store(contract_address, src + 2, values[2]);\n\n let dst = 1;\n copy(contract_address, src, dst, 3);\n\n assert_eq(load(contract_address, dst).unwrap(), values[0]);\n assert_eq(load(contract_address, dst + 1).unwrap(), values[1]);\n assert_eq(load(contract_address, dst + 2).unwrap(), values[2]);\n\n // src[0] and src[1] should have been overwritten since they are also dst[1] and dst[2]\n assert_eq(load(contract_address, src).unwrap(), values[1]); // dst[1]\n assert_eq(load(contract_address, src + 1).unwrap(), values[2]); // dst[2]\n assert_eq(load(contract_address, src + 2).unwrap(), values[2]); // src[2] (unchanged)\n });\n }\n\n #[test(should_fail_with = \"copy empty slot\")]\n unconstrained fn cannot_copy_empty_values() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n copy(contract_address, SLOT, SLOT, 1);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_store_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n let value = MockStruct::new(5, 6);\n store(other_contract_address, SLOT, value);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_load_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n let _: Option = load(other_contract_address, SLOT);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_delete_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n delete(other_contract_address, SLOT);\n });\n }\n\n #[test(should_fail_with = \"not allowed to access\")]\n unconstrained fn cannot_copy_other_contract() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let other_contract_address = AztecAddress::from_field(contract_address.to_field() + 1);\n\n copy(other_contract_address, SLOT, SLOT, 0);\n });\n }\n}\n" - }, - "154": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr", - "source": "use dep::protocol_types::address::AztecAddress;\n\n#[oracle(privateNotifyEnqueuedPublicFunctionCall)]\nunconstrained fn notify_enqueued_public_function_call_oracle(\n _contract_address: AztecAddress,\n _calldata_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n) {}\n\nunconstrained fn notify_enqueued_public_function_call_wrapper(\n contract_address: AztecAddress,\n calldata_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n) {\n notify_enqueued_public_function_call_oracle(\n contract_address,\n calldata_hash,\n side_effect_counter,\n is_static_call,\n )\n}\n\npub fn notify_enqueued_public_function_call(\n contract_address: AztecAddress,\n calldata_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n) {\n // Safety: Notifies the simulator that a public call has been enqueued, allowing it to prepare hints for the AVM to process this call.\n unsafe {\n notify_enqueued_public_function_call_wrapper(\n contract_address,\n calldata_hash,\n side_effect_counter,\n is_static_call,\n )\n }\n}\n\n#[oracle(privateNotifySetPublicTeardownFunctionCall)]\nunconstrained fn notify_set_public_teardown_function_call_oracle(\n _contract_address: AztecAddress,\n _calldata_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n) {}\n\nunconstrained fn notify_set_public_teardown_function_call_wrapper(\n contract_address: AztecAddress,\n calldata_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n) {\n notify_set_public_teardown_function_call_oracle(\n contract_address,\n calldata_hash,\n side_effect_counter,\n is_static_call,\n )\n}\n\npub fn notify_set_public_teardown_function_call(\n contract_address: AztecAddress,\n calldata_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n) {\n // Safety: Notifies the simulator that a teardown call has been set, allowing it to prepare hints for the AVM to process this call.\n unsafe {\n notify_set_public_teardown_function_call_wrapper(\n contract_address,\n calldata_hash,\n side_effect_counter,\n is_static_call,\n )\n }\n}\n\npub fn notify_set_min_revertible_side_effect_counter(counter: u32) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe { notify_set_min_revertible_side_effect_counter_oracle_wrapper(counter) };\n}\n\npub unconstrained fn notify_set_min_revertible_side_effect_counter_oracle_wrapper(counter: u32) {\n notify_set_min_revertible_side_effect_counter_oracle(counter);\n}\n\n#[oracle(privateNotifySetMinRevertibleSideEffectCounter)]\nunconstrained fn notify_set_min_revertible_side_effect_counter_oracle(_counter: u32) {}\n" - }, - "155": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/execution.nr", - "source": "use dep::protocol_types::address::AztecAddress;\n\n#[oracle(utilityGetContractAddress)]\nunconstrained fn get_contract_address_oracle() -> AztecAddress {}\n\n#[oracle(utilityGetBlockNumber)]\nunconstrained fn get_block_number_oracle() -> u32 {}\n\n#[oracle(utilityGetTimestamp)]\nunconstrained fn get_timestamp_oracle() -> u64 {}\n\n#[oracle(utilityGetChainId)]\nunconstrained fn get_chain_id_oracle() -> Field {}\n\n#[oracle(utilityGetVersion)]\nunconstrained fn get_version_oracle() -> Field {}\n\npub unconstrained fn get_contract_address() -> AztecAddress {\n get_contract_address_oracle()\n}\n\npub unconstrained fn get_block_number() -> u32 {\n get_block_number_oracle()\n}\n\npub unconstrained fn get_timestamp() -> u64 {\n get_timestamp_oracle()\n}\n\npub unconstrained fn get_chain_id() -> Field {\n get_chain_id_oracle()\n}\n\npub unconstrained fn get_version() -> Field {\n get_version_oracle()\n}\n" - }, - "156": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/execution_cache.nr", - "source": "/// Stores values represented as slice in execution cache to be later obtained by its hash.\npub fn store(values: [Field], hash: Field) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call. When loading the values, however, the caller must check that the values are indeed the preimage.\n unsafe { store_in_execution_cache_oracle_wrapper(values, hash) };\n}\n\nunconstrained fn store_in_execution_cache_oracle_wrapper(values: [Field], hash: Field) {\n store_in_execution_cache_oracle(values, hash);\n}\n\npub unconstrained fn load(hash: Field) -> [Field; N] {\n load_from_execution_cache_oracle(hash)\n}\n\n#[oracle(privateStoreInExecutionCache)]\nunconstrained fn store_in_execution_cache_oracle(_values: [Field], _hash: Field) {}\n\n#[oracle(privateLoadFromExecutionCache)]\nunconstrained fn load_from_execution_cache_oracle(_hash: Field) -> [Field; N] {}\n" - }, - "157": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr", - "source": "use protocol_types::{\n address::AztecAddress, contract_class_id::ContractClassId, contract_instance::ContractInstance,\n traits::FromField,\n};\n\n// NOTE: this is for use in private only\n#[oracle(utilityGetContractInstance)]\nunconstrained fn get_contract_instance_oracle(_address: AztecAddress) -> ContractInstance {}\n\n// NOTE: this is for use in private only\nunconstrained fn get_contract_instance_internal(address: AztecAddress) -> ContractInstance {\n get_contract_instance_oracle(address)\n}\n\n// NOTE: this is for use in private only\npub fn get_contract_instance(address: AztecAddress) -> ContractInstance {\n // Safety: The to_address function combines all values in the instance object to produce an address,\n // so by checking that we get the expected address we validate the entire struct.\n let instance = unsafe { get_contract_instance_internal(address) };\n assert_eq(instance.to_address(), address);\n\n instance\n}\n\nstruct GetContractInstanceResult {\n exists: bool,\n member: Field,\n}\n\n// These oracles each return a ContractInstance member\n// plus a boolean indicating whether the instance was found.\n#[oracle(avmOpcodeGetContractInstanceDeployer)]\nunconstrained fn get_contract_instance_deployer_oracle_avm(\n _address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {}\n#[oracle(avmOpcodeGetContractInstanceClassId)]\nunconstrained fn get_contract_instance_class_id_oracle_avm(\n _address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {}\n#[oracle(avmOpcodeGetContractInstanceInitializationHash)]\nunconstrained fn get_contract_instance_initialization_hash_oracle_avm(\n _address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {}\n\nunconstrained fn get_contract_instance_deployer_internal_avm(\n address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {\n get_contract_instance_deployer_oracle_avm(address)\n}\nunconstrained fn get_contract_instance_class_id_internal_avm(\n address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {\n get_contract_instance_class_id_oracle_avm(address)\n}\nunconstrained fn get_contract_instance_initialization_hash_internal_avm(\n address: AztecAddress,\n) -> [GetContractInstanceResult; 1] {\n get_contract_instance_initialization_hash_oracle_avm(address)\n}\n\npub fn get_contract_instance_deployer_avm(address: AztecAddress) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let GetContractInstanceResult { exists, member } =\n unsafe { get_contract_instance_deployer_internal_avm(address)[0] };\n if exists {\n Option::some(AztecAddress::from_field(member))\n } else {\n Option::none()\n }\n}\npub fn get_contract_instance_class_id_avm(address: AztecAddress) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let GetContractInstanceResult { exists, member } =\n unsafe { get_contract_instance_class_id_internal_avm(address)[0] };\n if exists {\n Option::some(ContractClassId::from_field(member))\n } else {\n Option::none()\n }\n}\npub fn get_contract_instance_initialization_hash_avm(address: AztecAddress) -> Option {\n // Safety: AVM opcodes are constrained by the AVM itself\n let GetContractInstanceResult { exists, member } =\n unsafe { get_contract_instance_initialization_hash_internal_avm(address)[0] };\n if exists {\n Option::some(member)\n } else {\n Option::none()\n }\n}\n" - }, - "16": { - "path": "std/embedded_curve_ops.nr", - "source": "use crate::cmp::Eq;\nuse crate::hash::Hash;\nuse crate::ops::arith::{Add, Neg, Sub};\n\n/// A point on the embedded elliptic curve\n/// By definition, the base field of the embedded curve is the scalar field of the proof system curve, i.e the Noir Field.\n/// x and y denotes the Weierstrass coordinates of the point, if is_infinite is false.\npub struct EmbeddedCurvePoint {\n pub x: Field,\n pub y: Field,\n pub is_infinite: bool,\n}\n\nimpl EmbeddedCurvePoint {\n /// Elliptic curve point doubling operation\n /// returns the doubled point of a point P, i.e P+P\n pub fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n /// Returns the null element of the curve; 'the point at infinity'\n pub fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n\n /// Returns the curve's generator point.\n pub fn generator() -> EmbeddedCurvePoint {\n // Generator point for the grumpkin curve (y^2 = x^3 - 17)\n EmbeddedCurvePoint {\n x: 1,\n y: 17631683881184975370165255887551781615748388533673675138860, // sqrt(-16)\n is_infinite: false,\n }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n /// Adds two points P+Q, using the curve addition formula, and also handles point at infinity\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n /// Points subtraction operation, using addition and negation\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint {\n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n /// Negates a point P, i.e returns -P, by negating the y coordinate.\n /// If the point is at infinity, then the result is also at infinity.\n fn neg(self) -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: self.x, y: -self.y, is_infinite: self.is_infinite }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n /// Checks whether two points are equal\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite)\n | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\nimpl Hash for EmbeddedCurvePoint {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n if self.is_infinite {\n self.is_infinite.hash(state);\n } else {\n self.x.hash(state);\n self.y.hash(state);\n }\n }\n}\n\n/// Scalar for the embedded curve represented as low and high limbs\n/// By definition, the scalar field of the embedded curve is base field of the proving system curve.\n/// It may not fit into a Field element, so it is represented with two Field elements; its low and high limbs.\npub struct EmbeddedCurveScalar {\n pub lo: Field,\n pub hi: Field,\n}\n\nimpl EmbeddedCurveScalar {\n pub fn new(lo: Field, hi: Field) -> Self {\n EmbeddedCurveScalar { lo, hi }\n }\n\n #[field(bn254)]\n pub fn from_field(scalar: Field) -> EmbeddedCurveScalar {\n let (a, b) = crate::field::bn254::decompose(scalar);\n EmbeddedCurveScalar { lo: a, hi: b }\n }\n\n //Bytes to scalar: take the first (after the specified offset) 16 bytes of the input as the lo value, and the next 16 bytes as the hi value\n #[field(bn254)]\n pub(crate) fn from_bytes(bytes: [u8; 64], offset: u32) -> EmbeddedCurveScalar {\n let mut v = 1;\n let mut lo = 0 as Field;\n let mut hi = 0 as Field;\n for i in 0..16 {\n lo = lo + (bytes[offset + 31 - i] as Field) * v;\n hi = hi + (bytes[offset + 15 - i] as Field) * v;\n v = v * 256;\n }\n let sig_s = crate::embedded_curve_ops::EmbeddedCurveScalar { lo, hi };\n sig_s\n }\n}\n\nimpl Eq for EmbeddedCurveScalar {\n fn eq(self, other: Self) -> bool {\n (other.hi == self.hi) & (other.lo == self.lo)\n }\n}\n\nimpl Hash for EmbeddedCurveScalar {\n fn hash(self, state: &mut H)\n where\n H: crate::hash::Hasher,\n {\n self.hi.hash(state);\n self.lo.hash(state);\n }\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// docs:start:multi_scalar_mul\npub fn multi_scalar_mul(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n) -> EmbeddedCurvePoint\n// docs:end:multi_scalar_mul\n{\n multi_scalar_mul_array_return(points, scalars, true)[0]\n}\n\n#[foreign(multi_scalar_mul)]\npub(crate) fn multi_scalar_mul_array_return(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N],\n predicate: bool,\n) -> [EmbeddedCurvePoint; 1] {}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint\n// docs:end:fixed_base_scalar_mul\n{\n multi_scalar_mul([EmbeddedCurvePoint::generator()], [scalar])\n}\n\n/// This function only assumes that the points are on the curve\n/// It handles corner cases around the infinity point causing some overhead compared to embedded_curve_add_not_nul and embedded_curve_add_unsafe\n// docs:start:embedded_curve_add\npub fn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n // docs:end:embedded_curve_add\n if crate::runtime::is_unconstrained() {\n // `embedded_curve_add_unsafe` requires the inputs not to be the infinity point, so we check it here.\n // This is because `embedded_curve_add_unsafe` uses the `embedded_curve_add` opcode.\n // For efficiency, the backend does not check the inputs for the infinity point, but it assumes that they are not the infinity point\n // so that it can apply the ec addition formula directly.\n if point1.is_infinite {\n point2\n } else if point2.is_infinite {\n point1\n } else {\n embedded_curve_add_unsafe(point1, point2)\n }\n } else {\n // In a constrained context, we also need to check the inputs are not the infinity point because we also use `embedded_curve_add_unsafe`\n // However we also need to identify the case where the two inputs are the same, because then\n // the addition formula does not work and we need to use the doubling formula instead.\n // In unconstrained context, we can check directly if the input values are the same when solving the opcode, so it is not an issue.\n\n // x_coordinates_match is true if both abscissae are the same\n let x_coordinates_match = point1.x == point2.x;\n // y_coordinates_match is true if both ordinates are the same\n let y_coordinates_match = point1.y == point2.y;\n // double_predicate is true if both abscissae and ordinates are the same\n let double_predicate = (x_coordinates_match & y_coordinates_match);\n // If the abscissae are the same, but not the ordinates, then one point is the opposite of the other\n let infinity_predicate = (x_coordinates_match & !y_coordinates_match);\n let point1_1 = EmbeddedCurvePoint {\n x: point1.x + (x_coordinates_match as Field),\n y: point1.y,\n is_infinite: false,\n };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n // point1_1 is guaranteed to have a different abscissa than point2:\n // - if x_coordinates_match is 0, that means point1.x != point2.x, and point1_1.x = point1.x + 0\n // - if x_coordinates_match is 1, that means point1.x = point2.x, but point1_1.x = point1.x + 1 in this case\n // Because the abscissa is different, the addition formula is guaranteed to succeed, so we can safely use `embedded_curve_add_unsafe`\n // Note that this computation may be garbage: if x_coordinates_match is 1, or if one of the input is the point at infinity.\n let mut result = embedded_curve_add_unsafe(point1_1, point2_1);\n\n // `embedded_curve_add_unsafe` is doing a doubling if the input is the same variable, because in this case it is guaranteed (at 'compile time') that the input is the same.\n let double = embedded_curve_add_unsafe(point1, point1);\n // `embedded_curve_add_unsafe` would not perform doubling, even if the inputs point1 and point2 are the same, because it cannot know this without adding some logic (and some constraints)\n // However we did this logic when we computed `double_predicate`, so we set the result to 2*point1 if point1 and point2 are the same\n result = if double_predicate { double } else { result };\n\n // Same logic as above for unconstrained context, we set the proper result when one of the inputs is the infinity point\n if point1.is_infinite {\n result = point2;\n }\n if point2.is_infinite {\n result = point1;\n }\n\n // Finally, we set the is_infinity flag of the result:\n // Opposite points should sum into the infinity point, however, if one of them is point at infinity, their coordinates are not meaningful\n // so we should not use the fact that the inputs are opposite in this case:\n let mut result_is_infinity =\n infinity_predicate & (!point1.is_infinite & !point2.is_infinite);\n // However, if both of them are at infinity, then the result is also at infinity\n result.is_infinite = result_is_infinity | (point1.is_infinite & point2.is_infinite);\n result\n }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(\n _point1: EmbeddedCurvePoint,\n _point2: EmbeddedCurvePoint,\n _predicate: bool,\n) -> [EmbeddedCurvePoint; 1] {}\n\n/// This function assumes that:\n/// The points are on the curve, and\n/// The points don't share an x-coordinate, and\n/// Neither point is the infinity point.\n/// If it is used with correct input, the function ensures the correct non-zero result is returned.\n/// Except for points on the curve, the other assumptions are checked by the function. It will cause assertion failure if they are not respected.\npub fn embedded_curve_add_not_nul(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n assert(point1.x != point2.x);\n assert(!point1.is_infinite);\n assert(!point2.is_infinite);\n // Ensure is_infinite is comptime\n let point1_1 = EmbeddedCurvePoint { x: point1.x, y: point1.y, is_infinite: false };\n let point2_1 = EmbeddedCurvePoint { x: point2.x, y: point2.y, is_infinite: false };\n embedded_curve_add_unsafe(point1_1, point2_1)\n}\n\n/// Unsafe ec addition\n/// If the inputs are the same, it will perform a doubling, but only if point1 and point2 are the same variable.\n/// If they have the same value but are different variables, the result will be incorrect because in this case\n/// it assumes (but does not check) that the points' x-coordinates are not equal.\n/// It also assumes neither point is the infinity point.\npub fn embedded_curve_add_unsafe(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint,\n) -> EmbeddedCurvePoint {\n embedded_curve_add_array_return(point1, point2, true)[0]\n}\n" - }, - "162": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr", - "source": "use protocol_types::abis::validation_requests::KeyValidationRequest;\n\n#[oracle(utilityGetKeyValidationRequest)]\nunconstrained fn get_key_validation_request_oracle(\n _pk_m_hash: Field,\n _key_index: Field,\n) -> KeyValidationRequest {}\n\npub unconstrained fn get_key_validation_request(\n pk_m_hash: Field,\n key_index: Field,\n) -> KeyValidationRequest {\n get_key_validation_request_oracle(pk_m_hash, key_index)\n}\n" - }, - "163": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/keys.nr", - "source": "use dep::protocol_types::{\n address::{AztecAddress, PartialAddress},\n point::Point,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, TpkM},\n};\n\n#[oracle(utilityGetPublicKeysAndPartialAddress)]\nunconstrained fn get_public_keys_and_partial_address_oracle(_address: AztecAddress) -> [Field; 13] {}\n\npub unconstrained fn get_public_keys_and_partial_address(\n address: AztecAddress,\n) -> (PublicKeys, PartialAddress) {\n let result = get_public_keys_and_partial_address_oracle(address);\n\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: result[0], y: result[1], is_infinite: result[2] != 0 } },\n ivpk_m: IvpkM { inner: Point { x: result[3], y: result[4], is_infinite: result[5] != 0 } },\n ovpk_m: OvpkM { inner: Point { x: result[6], y: result[7], is_infinite: result[8] != 0 } },\n tpk_m: TpkM { inner: Point { x: result[9], y: result[10], is_infinite: result[11] != 0 } },\n };\n\n let partial_address = PartialAddress::from_field(result[12]);\n\n (keys, partial_address)\n}\n" - }, - "165": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/message_processing.nr", - "source": "use protocol_types::address::AztecAddress;\n\n/// Finds new private logs that may have been sent to all registered accounts in PXE in the current contract and makes\n/// them available for later processing in Noir by storing them in a capsule array.\npub unconstrained fn fetch_tagged_logs(pending_tagged_log_array_base_slot: Field) {\n fetch_tagged_logs_oracle(pending_tagged_log_array_base_slot);\n}\n\n#[oracle(utilityFetchTaggedLogs)]\nunconstrained fn fetch_tagged_logs_oracle(pending_tagged_log_array_base_slot: Field) {}\n\n// This must be a single oracle and not one for notes and one for events because the entire point is to validate\n// all notes and events in one go, minimizing node round-trips.\npub(crate) unconstrained fn validate_enqueued_notes_and_events(\n contract_address: AztecAddress,\n note_validation_requests_array_base_slot: Field,\n event_validation_requests_array_base_slot: Field,\n) {\n validate_enqueued_notes_and_events_oracle(\n contract_address,\n note_validation_requests_array_base_slot,\n event_validation_requests_array_base_slot,\n );\n}\n\n#[oracle(utilityValidateEnqueuedNotesAndEvents)]\nunconstrained fn validate_enqueued_notes_and_events_oracle(\n contract_address: AztecAddress,\n note_validation_requests_array_base_slot: Field,\n event_validation_requests_array_base_slot: Field,\n) {}\n\npub(crate) unconstrained fn bulk_retrieve_logs(\n contract_address: AztecAddress,\n log_retrieval_requests_array_base_slot: Field,\n log_retrieval_responses_array_base_slot: Field,\n) {\n bulk_retrieve_logs_oracle(\n contract_address,\n log_retrieval_requests_array_base_slot,\n log_retrieval_responses_array_base_slot,\n );\n}\n\n#[oracle(utilityBulkRetrieveLogs)]\nunconstrained fn bulk_retrieve_logs_oracle(\n contract_address: AztecAddress,\n log_retrieval_requests_array_base_slot: Field,\n log_retrieval_responses_array_base_slot: Field,\n) {}\n" - }, - "167": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/notes.nr", - "source": "use crate::note::{note_interface::NoteType, retrieved_note::RetrievedNote};\n\nuse dep::protocol_types::{\n address::AztecAddress, indexed_tagging_secret::IndexedTaggingSecret, traits::Packable,\n};\n\n/// Notifies the simulator that a note has been created, so that it can be returned in future read requests in the same\n/// transaction. This note should only be added to the non-volatile database if found in an actual block.\npub fn notify_created_note(\n storage_slot: Field,\n note_type_id: Field,\n packed_note: [Field; N],\n note_hash: Field,\n counter: u32,\n) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe {\n notify_created_note_oracle_wrapper(\n storage_slot,\n note_type_id,\n packed_note,\n note_hash,\n counter,\n )\n };\n}\n\n/// Notifies the simulator that a note has been nullified, so that it is no longer returned in future read requests in\n/// the same transaction. This note should only be removed to the non-volatile database if its nullifier is found in an\n/// actual block.\npub fn notify_nullified_note(nullifier: Field, note_hash: Field, counter: u32) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to\n // call.\n unsafe { notify_nullified_note_oracle_wrapper(nullifier, note_hash, counter) };\n}\n\n/// Notifies the simulator that a non-note nullifier has been created, so that it can be used for note nonces.\npub fn notify_created_nullifier(nullifier: Field) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to\n // call.\n unsafe { notify_created_nullifier_oracle_wrapper(nullifier) };\n}\n\nunconstrained fn notify_created_note_oracle_wrapper(\n storage_slot: Field,\n note_type_id: Field,\n packed_note: [Field; N],\n note_hash: Field,\n counter: u32,\n) {\n notify_created_note_oracle(storage_slot, note_type_id, packed_note, note_hash, counter);\n}\n\n#[oracle(privateNotifyCreatedNote)]\nunconstrained fn notify_created_note_oracle(\n _storage_slot: Field,\n _note_type_id: Field,\n _packed_note: [Field; N],\n _note_hash: Field,\n _counter: u32,\n) {}\n\nunconstrained fn notify_nullified_note_oracle_wrapper(\n nullifier: Field,\n note_hash: Field,\n counter: u32,\n) {\n notify_nullified_note_oracle(nullifier, note_hash, counter);\n}\n\n#[oracle(privateNotifyNullifiedNote)]\nunconstrained fn notify_nullified_note_oracle(_nullifier: Field, _note_hash: Field, _counter: u32) {}\n\nunconstrained fn notify_created_nullifier_oracle_wrapper(nullifier: Field) {\n notify_created_nullifier_oracle(nullifier);\n}\n\n#[oracle(privateNotifyCreatedNullifier)]\nunconstrained fn notify_created_nullifier_oracle(_nullifier: Field) {}\n\n#[oracle(utilityGetNotes)]\nunconstrained fn get_notes_oracle(\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 // This is always set to MAX_NOTES. We need to pass it to TS in order to correctly construct the BoundedVec\n _max_notes: u32,\n // This is always set to as Packable>::N. We need to pass it to TS in order to be able to\n // correctly construct the BoundedVec there.\n _packed_retrieved_note_length: u32,\n) -> BoundedVec<[Field; as Packable>::N], MaxNotes>\nwhere\n // TODO(https://github.com/noir-lang/noir/issues/9399): `Note: Packable` should work here.\n RetrievedNote: Packable,\n{}\n\npub unconstrained 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) -> [Option>; MaxNotes]\nwhere\n Note: NoteType + Packable,\n{\n let packed_retrieved_notes: BoundedVec<[Field; as Packable>::N], MaxNotes>\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 MaxNotes,\n as Packable>::N,\n );\n\n let mut notes = BoundedVec::<_, MaxNotes>::new();\n for i in 0..packed_retrieved_notes.len() {\n let retrieved_note = RetrievedNote::unpack(packed_retrieved_notes.get(i));\n notes.push(retrieved_note);\n }\n\n // At last we convert the bounded vector to an array of options. We do this because that is what the filter\n // function needs to have on the output and we've decided to have the same type on the input and output of\n // the filter and preprocessor functions.\n //\n // We have decided to have the same type on the input and output of the filter and preprocessor functions because\n // it allows us to chain multiple filters and preprocessors together.\n //\n // So why do we want the array of options on the output of the filter function?\n //\n // Filter returns an array of options rather than a BoundedVec for performance reasons. Using an array of options\n // allows setting values at known indices in the output array which is much more efficient than pushing to a\n // BoundedVec where the write position depends on previous iterations. The array can then be efficiently converted\n // to a BoundedVec using utils/array/collapse.nr::collapse function from Aztec.nr. This avoids expensive dynamic\n // memory access patterns that would be required when building up a BoundedVec incrementally. For preprocessor\n // functions we could use BoundedVec return value as there the optimization does not matter since it is applied in\n // an unconstrained context. We, however, use the same return value type to be able to use the same function as\n // both a preprocessor and a filter.\n let mut notes_array = [Option::none(); MaxNotes];\n for i in 0..notes.len() {\n if i < notes.len() {\n notes_array[i] = Option::some(notes.get_unchecked(i));\n }\n }\n\n notes_array\n}\n\n/// Returns true if the nullifier exists. Note that a `true` value can be constrained by proving existence of the\n/// nullifier, but a `false` value should not be relied upon since other transactions may emit this nullifier before the\n/// current transaction is included in a block. While this might seem of little use at first, certain design patterns\n/// benefit from this abstraction (see e.g. `PrivateMutable`).\npub unconstrained fn check_nullifier_exists(inner_nullifier: Field) -> bool {\n check_nullifier_exists_oracle(inner_nullifier)\n}\n\n#[oracle(utilityCheckNullifierExists)]\nunconstrained fn check_nullifier_exists_oracle(_inner_nullifier: Field) -> bool {}\n\n// TODO: Oracles below are generic private log oracles and are not specific to notes. Move them somewhere else.\n\n/// Returns the derived app tagging secret ready to be included in a log for a given sender and recipient pair,\n/// siloed for the current contract address.\npub unconstrained fn get_app_tag_as_sender(sender: AztecAddress, recipient: AztecAddress) -> Field {\n get_indexed_tagging_secret_as_sender_oracle(sender, recipient).compute_tag(recipient)\n}\n\n#[oracle(utilityGetIndexedTaggingSecretAsSender)]\nunconstrained fn get_indexed_tagging_secret_as_sender_oracle(\n _sender: AztecAddress,\n _recipient: AztecAddress,\n) -> IndexedTaggingSecret {}\n\n/// Notifies the simulator that a tag has been used in a note, and to therefore increment the associated index so that\n/// future notes get a different tag and can be discovered by the recipient.\n/// This change should only be persisted in a non-volatile database if the tagged log is found in an actual block -\n/// otherwise e.g. a reverting transaction can cause the sender to accidentally skip indices and later produce notes\n/// that are not found by the recipient.\npub fn increment_app_tagging_secret_index_as_sender(sender: AztecAddress, recipient: AztecAddress) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe {\n increment_app_tagging_secret_index_as_sender_wrapper(sender, recipient);\n }\n}\n\nunconstrained fn increment_app_tagging_secret_index_as_sender_wrapper(\n sender: AztecAddress,\n recipient: AztecAddress,\n) {\n increment_app_tagging_secret_index_as_sender_oracle(sender, recipient);\n}\n\n#[oracle(privateIncrementAppTaggingSecretIndexAsSender)]\nunconstrained fn increment_app_tagging_secret_index_as_sender_oracle(\n _sender: AztecAddress,\n _recipient: AztecAddress,\n) {}\n\n/// Gets the sender for tags.\n///\n/// This unconstrained value is used as the sender when computing an unconstrained shared secret\n/// for a tag in order to emit a log. Constrained tagging should not use this as there is no\n/// guarantee that the recipient knows about the sender, and hence about the shared secret.\n///\n/// The value persists through nested calls, meaning all calls down the stack will use the same\n/// 'senderForTags' value (unless it is replaced).\npub unconstrained fn get_sender_for_tags() -> Option {\n get_sender_for_tags_oracle()\n}\n\n#[oracle(privateGetSenderForTags)]\nunconstrained fn get_sender_for_tags_oracle() -> Option {}\n\n/// Sets the sender for tags.\n///\n/// This unconstrained value is used as the sender when computing an unconstrained shared secret\n/// for a tag in order to emit a log. Constrained tagging should not use this as there is no\n/// guarantee that the recipient knows about the sender, and hence about the shared secret.\n///\n/// Account contracts typically set this value before calling other contracts. The value persists\n/// through nested calls, meaning all calls down the stack will use the same 'senderForTags'\n/// value (unless it is replaced by another call to this setter).\npub unconstrained fn set_sender_for_tags(sender_for_tags: AztecAddress) {\n set_sender_for_tags_oracle(sender_for_tags);\n}\n\n#[oracle(privateSetSenderForTags)]\nunconstrained fn set_sender_for_tags_oracle(_sender_for_tags: AztecAddress) {}\n" - }, - "17": { - "path": "std/field/bn254.nr", - "source": "use crate::field::field_less_than;\nuse crate::runtime::is_unconstrained;\n\n// The low and high decomposition of the field modulus\nglobal PLO: Field = 53438638232309528389504892708671455233;\nglobal PHI: Field = 64323764613183177041862057485226039389;\n\npub(crate) global TWO_POW_128: Field = 0x100000000000000000000000000000000;\n\n// Decomposes a single field into two 16 byte fields.\nfn compute_decomposition(x: Field) -> (Field, Field) {\n // Here's we're taking advantage of truncating 128 bit limbs from the input field\n // and then subtracting them from the input such the field division is equivalent to integer division.\n let low = (x as u128) as Field;\n let high = (x - low) / TWO_POW_128;\n\n (low, high)\n}\n\npub(crate) unconstrained fn decompose_hint(x: Field) -> (Field, Field) {\n compute_decomposition(x)\n}\n\nunconstrained fn lte_hint(x: Field, y: Field) -> bool {\n if x == y {\n true\n } else {\n field_less_than(x, y)\n }\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 // Safety: borrow is enforced to be boolean due to its type.\n // if borrow is 0, it asserts that (alo > blo && ahi >= bhi)\n // if borrow is 1, it asserts that (alo <= blo && ahi > bhi)\n unsafe {\n let borrow = lte_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\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 // Safety: decomposition is properly checked below\n unsafe {\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}\n\npub fn assert_gt(a: Field, b: Field) {\n if is_unconstrained() {\n assert(\n // Safety: already unconstrained\n unsafe { field_less_than(b, a) },\n );\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 // Safety: unsafe in unconstrained\n unsafe {\n field_less_than(b, a)\n }\n } else if a == b {\n false\n } else {\n // Safety: Take a hint of the comparison and verify it\n unsafe {\n if field_less_than(a, b) {\n assert_gt(b, a);\n false\n } else {\n assert_gt(a, b);\n true\n }\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::{assert_gt, decompose, gt, lte_hint, PHI, PLO, TWO_POW_128};\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 unconstrained fn check_lte_hint() {\n assert(lte_hint(0, 1));\n assert(lte_hint(0, 0x100));\n assert(lte_hint(0x100, TWO_POW_128 - 1));\n assert(!lte_hint(0 - 1, 0));\n\n assert(lte_hint(0, 0));\n assert(lte_hint(0x100, 0x100));\n assert(lte_hint(0 - 1, 0 - 1));\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" - }, - "170": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/shared_secret.nr", - "source": "use protocol_types::{address::aztec_address::AztecAddress, point::Point};\n\n// TODO(#12656): return an app-siloed secret + document this\n#[oracle(utilityGetSharedSecret)]\nunconstrained fn get_shared_secret_oracle(address: AztecAddress, ephPk: Point) -> Point {}\n\n/// Returns an app-siloed shared secret between `address` and someone who knows the secret key behind an\n/// ephemeral public key `ephPk`. The app-siloing means that contracts cannot retrieve secrets that belong to\n/// other contracts, and therefore cannot e.g. decrypt their messages. This is an important security consideration\n/// given that both the `address` and `ephPk` are public information.\n///\n/// The shared secret `S` is computed as:\n/// `let S = (ivsk + h) * ephPk`\n/// where `ivsk + h` is the 'preaddress' i.e. the preimage of the address, also called the address secret.\n/// TODO(#12656): app-silo this secret\npub unconstrained fn get_shared_secret(address: AztecAddress, ephPk: Point) -> Point {\n get_shared_secret_oracle(address, ephPk)\n}\n" - }, - "172": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/storage.nr", - "source": "use dep::protocol_types::{address::AztecAddress, traits::{Packable, ToField}};\n\n#[oracle(utilityStorageRead)]\nunconstrained fn storage_read_oracle(\n address: Field,\n storage_slot: Field,\n block_number: u32,\n length: u32,\n) -> [Field; N] {}\n\npub unconstrained fn raw_storage_read(\n address: AztecAddress,\n storage_slot: Field,\n block_number: u32,\n) -> [Field; N] {\n storage_read_oracle(address.to_field(), storage_slot, block_number, N)\n}\n\npub unconstrained fn storage_read(\n address: AztecAddress,\n storage_slot: Field,\n block_number: u32,\n) -> T\nwhere\n T: Packable,\n{\n T::unpack(raw_storage_read(address, storage_slot, block_number))\n}\n\nmod tests {\n use crate::oracle::storage::{raw_storage_read, storage_read};\n use dep::protocol_types::{address::AztecAddress, traits::{FromField, Packable}};\n\n use crate::test::mocks::mock_struct::MockStruct;\n use std::test::OracleMock;\n\n global address: AztecAddress = AztecAddress::from_field(29);\n global slot: Field = 7;\n global block_number: u32 = 17;\n\n #[test]\n unconstrained fn test_raw_storage_read() {\n let written = MockStruct { a: 13, b: 42 };\n\n let _ = OracleMock::mock(\"utilityStorageRead\").returns(written.pack());\n\n let read: [Field; 2] = raw_storage_read(address, slot, block_number);\n assert_eq(read[0], 13);\n assert_eq(read[1], 42);\n }\n\n #[test]\n unconstrained fn test_storage_read() {\n let written = MockStruct { a: 13, b: 42 };\n\n let _ = OracleMock::mock(\"utilityStorageRead\").returns(written.pack());\n\n let read: MockStruct = storage_read(address, slot, block_number);\n assert_eq(read.a, 13);\n assert_eq(read.b, 42);\n }\n}\n" - }, - "173": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/oracle/version.nr", - "source": "/// The ORACLE_VERSION constant is used to check that the oracle interface is in sync between PXE and Aztec.nr. We need\n/// to version the oracle interface to ensure that developers get a reasonable error message if they use incompatible\n/// versions of Aztec.nr and PXE. The TypeScript counterpart is in `oracle_version.ts`.\n///\n/// @dev Whenever a contract function or Noir test is run, the `utilityAssertCompatibleOracleVersion` oracle is called and\n/// if the oracle version is incompatible an error is thrown.\npub global ORACLE_VERSION: Field = 1;\n\n/// Asserts that the version of the oracle is compatible with the version expected by the contract.\npub fn assert_compatible_oracle_version() {\n // Safety: This oracle call returns nothing: we only call it to check Aztec.nr and Oracle interface versions are\n // compatible. It is therefore always safe to call.\n unsafe {\n assert_compatible_oracle_version_wrapper();\n }\n}\n\nunconstrained fn assert_compatible_oracle_version_wrapper() {\n assert_compatible_oracle_version_oracle(ORACLE_VERSION);\n}\n\n#[oracle(utilityAssertCompatibleOracleVersion)]\nunconstrained fn assert_compatible_oracle_version_oracle(version: Field) {}\n\nmod test {\n use super::{assert_compatible_oracle_version_oracle, ORACLE_VERSION};\n\n #[test]\n unconstrained fn compatible_oracle_version() {\n assert_compatible_oracle_version_oracle(ORACLE_VERSION);\n }\n\n #[test(should_fail_with = \"Incompatible oracle version. PXE is using version '1', but got a request for '318183437'.\")]\n unconstrained fn incompatible_oracle_version() {\n let arbitrary_incorrect_version = 318183437;\n assert_compatible_oracle_version_oracle(arbitrary_incorrect_version);\n }\n}\n" - }, - "177": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/state_vars/map.nr", - "source": "use crate::state_vars::storage::HasStorageSlot;\nuse dep::protocol_types::{storage::map::derive_storage_slot_in_map, traits::ToField};\n\n/// Map\n///\n/// A key-value storage container that maps keys to state variables, similar\n/// to Solidity mappings.\n///\n/// `Map` enables you to associate keys (like addresses or other identifiers)\n/// with state variables in your Aztec smart contract. This is conceptually\n/// similar to Solidity's `mapping(K => V)` syntax, where you can store and\n/// retrieve values by their associated keys.\n///\n/// You can declare a state variable contained within a Map in your contract's\n/// #[storage] struct.\n///\n/// For example, you might use\n/// `Map, Context>` to track\n/// token balances for different users, similar to how you'd use\n/// `mapping(address => uint256)` in Solidity.\n///\n/// > Aside: the verbose `Context` in the declaration is a consequence of\n/// > leveraging Noir's regular syntax for generics to ensure that certain\n/// > state variable methods can only be called in some contexts (private,\n/// > public, utility).\n///\n/// The methods of Map are:\n/// - `at` (access state variable for a given key)\n/// (see the method's own doc comments for more info).\n///\n/// ## Generic Parameters\n/// - `K`: The key type (must implement `ToField` trait for hashing)\n/// - `V`: The value type:\n/// - any Aztec state variable:\n/// - `PublicMutable`\n/// - `PublicImmutable`\n/// - `PrivateMutable`\n/// - `PrivateImmutable`\n/// - `PrivateSet`\n/// - `DelayedPublicMutable`\n/// - `Map`\n/// - `Context`: The execution context (handles private/public function\n/// contexts)\n///\n/// ## Usage\n/// Maps are typically declared in your contract's #[storage] struct and\n/// accessed\n/// using the `at(key)` method to get the state variable for a specific key.\n/// The resulting state variable can then be read from or written to using its\n/// own methods.\n///\n/// ## Advanced\n/// Internally, `Map` uses a single base storage slot to represent the\n/// mapping\n/// itself, similar to Solidity's approach. Individual key-value pairs are\n/// stored at derived storage slots computed by hashing the base storage\n/// slot\n/// with the key using Poseidon2. This ensures:\n/// - No storage slot collisions between different keys\n/// - Uniform distribution of storage slots across the storage space\n/// - Compatibility with Aztec's storage tree structure\n/// - Gas-efficient storage access patterns similar to Solidity mappings\n///\n/// The storage slot derivation uses `derive_storage_slot_in_map(base_slot,\n/// key)` which computes `poseidon2_hash([base_slot, key.to_field()])`,\n/// ensuring cryptographically secure slot separation.\n///\n/// docs:start:map\npub struct Map {\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V,\n}\n// docs:end:map\n\n// Map reserves a single storage slot regardless of what it stores because\n// nothing is stored at said slot: it is only used to derive the storage slots\n// of nested state variables, which is expected to never result in collisions\n// or slots being close to one another due to these being hashes. This mirrors\n// the strategy adopted by Solidity mappings.\nimpl HasStorageSlot<1> for Map {\n fn get_storage_slot(self) -> Field {\n self.storage_slot\n }\n}\n\nimpl Map {\n /// Initializes a new Map state variable.\n ///\n /// This function is usually automatically called within the #[storage]\n /// macro.\n /// You typically don't need to call this directly when writing smart contracts.\n ///\n /// # Arguments\n ///\n /// * `context` - One of `PrivateContext`/`PublicContext`/`UtilityContext`.\n /// The Context determines which methods of this struct will\n /// be made available to the calling smart contract function.\n /// * `storage_slot` - A unique identifier for this Map within the contract.\n /// Usually, the #[storage] macro will determine an\n /// appropriate storage_slot automatically. A smart\n /// contract dev shouldn't have to worry about this, as\n /// it's managed behind the scenes.\n /// * `state_var_constructor` - A function that creates the value type (V)\n /// given a context and storage slot. This is\n /// typically the constructor of the state\n /// variable type being stored in the Map.\n ///\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 /// Returns the state variable associated with the given key.\n ///\n /// This is equivalent to accessing `mapping[key]` in Solidity. It returns\n /// the state variable instance for the specified key, which can then be\n /// used to read or write the value at that key.\n ///\n /// Unlike Solidity mappings which return the value directly, this returns\n /// the state variable wrapper (like PrivateMutable, PublicMutable, etc.)\n /// that you then call methods on to interact with the actual value.\n ///\n /// # Arguments\n ///\n /// * `key` - The key to look up in the map. Must implement the ToField\n /// trait (which most basic Noir & Aztec types do).\n ///\n /// # Returns\n ///\n /// * `V` - The state variable instance for this key. You can then call\n /// methods like `.read()`, `.write()`, `.get_note()`, etc. on this\n /// depending on the specific state variable type.\n ///\n /// # Example\n ///\n /// ```noir\n /// // Get a user's balance (assuming PrivateMutable)\n /// let user_balance = storage.balances.at(user_address);\n /// let current_note = user_balance.get_note();\n ///\n /// // Update the balance\n /// user_balance.replace(new_note);\n /// ```\n ///\n // docs:start:at\n pub fn at(self, key: K) -> V\n where\n K: ToField,\n {\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" - }, - "18": { - "path": "std/field/mod.nr", - "source": "pub mod bn254;\nuse crate::{runtime::is_unconstrained, static_assert};\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n /// Asserts that `self` can be represented in `bit_size` bits.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^{bit_size}`.\n // docs:start:assert_max_bit_size\n pub fn assert_max_bit_size(self) {\n // docs:end:assert_max_bit_size\n static_assert(\n BIT_SIZE < modulus_num_bits() as u32,\n \"BIT_SIZE must be less than modulus_num_bits\",\n );\n __assert_max_bit_size(self, BIT_SIZE);\n }\n\n /// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n /// This slice will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_le_bits\n pub fn to_le_bits(self: Self) -> [u1; N] {\n // docs:end:to_le_bits\n let bits = __to_le_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[N - 1 - i] != p[N - 1 - i]) {\n assert(p[N - 1 - i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_be_bits\n pub fn to_be_bits(self: Self) -> [u1; N] {\n // docs:end:to_be_bits\n let bits = __to_be_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the decomposition does not overflow the modulus\n let p = modulus_be_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[i] != p[i]) {\n assert(p[i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its little endian byte decomposition as a `[u8;N]` array\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_le_bytes\n pub fn to_le_bytes(self: Self) -> [u8; N] {\n // docs:end:to_le_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_le_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[N - 1 - i] != p[N - 1 - i]) {\n assert(bytes[N - 1 - i] < p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n /// Decomposes `self` into its big endian byte decomposition as a `[u8;N]` array of length required to represent the field modulus\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_be_bytes\n pub fn to_be_bytes(self: Self) -> [u8; N] {\n // docs:end:to_be_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_be_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_be_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[i] != p[i]) {\n assert(bytes[i] < p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n fn to_le_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_le_radix(self, radix)\n }\n\n fn to_be_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_be_radix(self, radix)\n }\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: [u1; 32] = exponent.to_le_bits();\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 `elem` {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 /// Convert a little endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_le_bytes(bytes: [u8; N]) -> Field {\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[i] as Field) * v;\n v = v * 256;\n }\n result\n }\n\n /// Convert a big endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_be_bytes(bytes: [u8; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[N - 1 - i] as Field) * v;\n v = v * 256;\n }\n result\n }\n}\n\n#[builtin(apply_range_constraint)]\nfn __assert_max_bit_size(value: Field, bit_size: u32) {}\n\n// `_radix` must be less than 256\n#[builtin(to_le_radix)]\nfn __to_le_radix(value: Field, radix: u32) -> [u8; N] {}\n\n// `_radix` must be less than 256\n#[builtin(to_be_radix)]\nfn __to_be_radix(value: Field, radix: u32) -> [u8; N] {}\n\n/// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n/// This slice will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_le_bits)]\nfn __to_le_bits(value: Field) -> [u1; N] {}\n\n/// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n/// This array will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_be_bits)]\nfn __to_be_bits(value: Field) -> [u1; N] {}\n\n#[builtin(modulus_num_bits)]\npub comptime fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub comptime fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub comptime fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub comptime fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub comptime fn modulus_le_bytes() -> [u8] {}\n\n/// An unconstrained only built in to efficiently compare fields.\n#[builtin(field_less_than)]\nunconstrained fn __field_less_than(x: Field, y: Field) -> bool {}\n\npub(crate) unconstrained fn field_less_than(x: Field, y: Field) -> bool {\n __field_less_than(x, y)\n}\n\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 if is_unconstrained() {\n // Safety: unconstrained context\n unsafe {\n field_less_than(x, y)\n }\n } else {\n let x_bytes: [u8; 32] = x.to_le_bytes();\n let y_bytes: [u8; 32] = y.to_le_bytes();\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..32 {\n if (!done) {\n let x_byte = x_bytes[32 - 1 - i] as u8;\n let y_byte = y_bytes[32 - 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\nmod tests {\n use crate::{panic::panic, runtime};\n use super::field_less_than;\n\n #[test]\n // docs:start:to_be_bits_example\n fn test_to_be_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_be_bits();\n assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]);\n }\n // docs:end:to_be_bits_example\n\n #[test]\n // docs:start:to_le_bits_example\n fn test_to_le_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_le_bits();\n assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]);\n }\n // docs:end:to_le_bits_example\n\n #[test]\n // docs:start:to_be_bytes_example\n fn test_to_be_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_be_bytes();\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_bytes_example\n\n #[test]\n // docs:start:to_le_bytes_example\n fn test_to_le_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_le_bytes();\n assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_bytes_example\n\n #[test]\n // docs:start:to_be_radix_example\n fn test_to_be_radix() {\n // 259, in base 256, big endian, is [1, 3].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_be_radix(256);\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 1, 3]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_radix_example\n\n #[test]\n // docs:start:to_le_radix_example\n fn test_to_le_radix() {\n // 259, in base 256, little endian, is [3, 1].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_le_radix(256);\n assert_eq(bytes, [3, 1, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_radix_example\n\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n // TODO: Update this test to account for the Brillig restriction that the radix must be greater than 2\n //#[test]\n //fn test_to_le_radix_brillig_1() {\n // // this test should only fail in constrained mode\n // if runtime::is_unconstrained() {\n // let field = 1;\n // let out: [u8; 8] = field.to_le_radix(1);\n // crate::println(out);\n // let expected = [0; 8];\n // assert(out == expected, \"unexpected result\");\n // }\n //}\n\n #[test(should_fail_with = \"radix must be a power of 2\")]\n fn test_to_le_radix_3() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(3);\n } else {\n panic(f\"radix must be a power of 2\");\n }\n }\n\n #[test]\n fn test_to_le_radix_brillig_3() {\n // this test should only fail in constrained mode\n if runtime::is_unconstrained() {\n let field = 1;\n let out: [u8; 8] = field.to_le_radix(3);\n let mut expected = [0; 8];\n expected[0] = 1;\n assert(out == expected, \"unexpected result\");\n }\n }\n\n #[test(should_fail_with = \"radix must be less than or equal to 256\")]\n fn test_to_le_radix_512() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(512);\n } else {\n panic(f\"radix must be less than or equal to 256\")\n }\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n unconstrained fn not_enough_limbs_brillig() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n fn not_enough_limbs() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n // TODO: Update this test to account for the Brillig restriction that the radix must be less than 512\n //#[test]\n //fn test_to_le_radix_brillig_512() {\n // // this test should only fail in constrained mode\n // if runtime::is_unconstrained() {\n // let field = 1;\n // let out: [u8; 8] = field.to_le_radix(512);\n // let mut expected = [0; 8];\n // expected[0] = 1;\n // assert(out == expected, \"unexpected result\");\n // }\n //}\n\n #[test]\n unconstrained fn test_field_less_than() {\n assert(field_less_than(0, 1));\n assert(field_less_than(0, 0x100));\n assert(field_less_than(0x100, 0 - 1));\n assert(!field_less_than(0 - 1, 0));\n }\n}\n" - }, - "185": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr", - "source": "use crate::{\n context::{PrivateContext, PublicContext, UtilityContext},\n state_vars::storage::HasStorageSlot,\n utils::with_hash::WithHash,\n};\nuse protocol_types::{\n constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, hash::poseidon2_hash_with_separator,\n traits::Packable,\n};\n\n/// # PublicImmutable\n///\n/// PublicImmutable is a public state variable type for values that are set once\n/// during initialization and remain permanently unchanged.\n///\n/// You can declare a state variable of type PublicImmutable within your contract's\n/// #[storage] struct:\n///\n/// E.g.:\n/// `your_variable: PublicImmutable`\n///\n/// PublicImmutable stores an immutable value in public state which can be _read_\n/// from public, utility and even _private_ execution contexts.\n///\n/// The methods of PublicImmutable are:\n/// - `initialize`\n/// - `read`\n/// (see the methods' own doc comments for more info).\n///\n/// # Generic Parameters:\n///\n/// * `T` - The type of value stored (must implement Packable).\n/// * `Context` - The execution context (PublicContext, PrivateContext, or UtilityContext).\n///\n/// # Advanced\n///\n/// PublicImmutable leverages `WithHash` to enable efficient private reads of\n/// public storage. The `WithHash` wrapper optimizes reads by hashing values that would\n/// be larger than a single field into a single field, then proving inclusion of only\n/// the hash in public storage.\n///\n/// This optimization is particularly valuable when T packs to multiple fields,\n/// as it maintains \"almost constant\" verification overhead regardless of the\n/// original data size.\n///\n/// ## Optimizing private reads in your contract\n/// Since reading T from public immutable storage in private contexts has \"almost\n/// constant\" constraint costs regardless of T's size, it's recommended to group\n/// multiple values into a single struct when they are to be read together. This is\n/// typically useful for configuration data set during contract initialization. E.g.:\n///\n/// ```noir\n/// use dep::aztec::protocol_types::{address::AztecAddress, traits::Packable};\n/// use std::meta::derive;\n///\n/// #[derive(Eq, Packable)]\n/// pub struct Config \\{\n/// pub address_1: AztecAddress,\n/// pub value_1: u128,\n/// pub value_2: u64,\n/// ...\n/// }\n/// ```\n///\n// docs:start:public_immutable_struct\npub struct PublicImmutable {\n context: Context,\n storage_slot: Field,\n}\n// docs:end:public_immutable_struct\n\n/// `WithHash` stores both the packed value (using O fields) and its hash (1 field), requiring O = M + 1 total\n/// fields.\nimpl HasStorageSlot for PublicImmutable\nwhere\n WithHash: Packable,\n{\n fn get_storage_slot(self) -> Field {\n self.storage_slot\n }\n}\n\nimpl PublicImmutable {\n /// Initializes a new PublicImmutable state variable.\n ///\n /// This function is usually automatically called within the #[storage] macro.\n /// You typically don't need to call this directly when writing smart contracts.\n ///\n /// # Arguments\n ///\n /// * `context` - One of `PublicContext`/`PrivateContext`/`UtilityContext`. The\n /// Context determines which methods of this struct will be made\n /// available to the calling smart contract function.\n /// * `storage_slot` - A unique identifier for this state variable within the\n /// contract. Usually, the #[storage] macro will determine an\n /// appropriate storage_slot automatically. A smart contract\n /// dev shouldn't have to worry about this, as it's managed\n /// behind the scenes.\n ///\n /// docs:start:public_immutable_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 PublicImmutable { context, storage_slot }\n }\n // docs:end:public_immutable_struct_new\n\n pub fn compute_initialization_nullifier(self) -> Field {\n poseidon2_hash_with_separator(\n [self.storage_slot],\n GENERATOR_INDEX__INITIALIZATION_NULLIFIER,\n )\n }\n}\n\nimpl PublicImmutable {\n /// Initializes a PublicImmutable state variable instance with a permanent value.\n ///\n /// This function sets the immutable value for this state variable. It can only\n /// be called once per PublicImmutable. Subsequent calls will fail because the\n /// initialization nullifier will already exist.\n ///\n /// # Arguments\n /// * `value` - The permanent value to store in this PublicImmutable.\n ///\n /// # Panics\n /// Panics if the value is already initialized.\n ///\n /// # Advanced\n ///\n /// This function performs the following operations:\n /// - Creates and emits an initialization nullifier to mark this storage slot\n /// as initialized. This prevents double-initialization.\n /// - Wraps the value in `WithHash` for efficient private reads.\n /// - Stores the wrapped value in Aztec's public data tree.\n ///\n /// docs:start:public_immutable_struct_write\n pub fn initialize(self, value: T)\n where\n T: Packable + Eq,\n {\n // We emit an initialization nullifier to indicate that the struct is initialized. This also prevents\n // the value from being initialized again as a nullifier can be included only once.\n let nullifier = self.compute_initialization_nullifier();\n self.context.push_nullifier(nullifier);\n\n self.context.storage_write(self.storage_slot, WithHash::new(value));\n }\n // docs:end:public_immutable_struct_write\n\n /// Reads the permanent value stored in this PublicImmutable state variable.\n ///\n /// # Returns\n /// * `T` - The permanent value stored in this PublicImmutable.\n ///\n /// # Panics\n /// Panics if the value is not initialized.\n ///\n /// # Advanced\n ///\n /// This function performs the following operations:\n /// - Checks that the state variable has been initialized by verifying the\n /// initialization nullifier exists\n /// - Reads the `WithHash` wrapper from public storage\n /// - Extracts and returns the original value T\n ///\n /// The function will panic if called on an uninitialized PublicImmutable.\n ///\n /// docs:start:public_immutable_struct_read\n pub fn read(self) -> T\n where\n T: Packable + Eq,\n {\n assert(self.is_initialized(), \"Trying to read from uninitialized PublicImmutable\");\n WithHash::public_storage_read(*self.context, self.storage_slot)\n }\n // docs:end:public_immutable_struct_read\n\n /// Reads the value stored in this PublicImmutable without checking if the value\n /// is initialized.\n ///\n /// This function bypasses the initialization check and directly reads from\n /// storage.\n /// If the PublicImmutable has not been initialized, this will return a\n /// zeroed value.\n /// However, if the variable is _known_ to be initialized, this is cheaper\n /// to call than `read`.\n ///\n /// # Returns\n ///\n /// * `T` - The value stored in this PublicImmutable, or empty/default values if\n /// uninitialized.\n ///\n pub fn read_unsafe(self) -> T\n where\n T: Packable + Eq,\n {\n WithHash::public_storage_read(*self.context, self.storage_slot)\n }\n\n fn is_initialized(self) -> bool {\n let nullifier = self.compute_initialization_nullifier();\n self.context.nullifier_exists(nullifier, self.context.this_address())\n }\n}\n\nimpl PublicImmutable {\n /// Reads the permanent value stored in this PublicImmutable state variable.\n ///\n /// Notice that this function is executable only within a UtilityContext, which\n /// is an unconstrained environment on the user's local device.\n ///\n /// # Returns\n ///\n /// * `T` - The permanent value stored in this PublicImmutable.\n ///\n pub unconstrained fn read(self) -> T\n where\n T: Packable + Eq,\n {\n // TODO(#15703): this fn should fail if the variable is not initialized\n WithHash::utility_public_storage_read(self.context, self.storage_slot)\n }\n}\n\nimpl PublicImmutable {\n /// Reads the permanent value stored in this PublicImmutable from the anchor\n /// block.\n ///\n /// Private functions execute asynchronously and offchain. When a user begins\n /// private execution, their view of the chain 'branches off' from the current\n /// public state, since public state continues to advance while they execute\n /// privately. Therefore, private functions read from a historical snapshot of\n /// public state rather than the current state.\n ///\n /// # Returns\n ///\n /// * `T` - The permanent value stored in this PublicImmutable at the historical\n /// block referenced by the private context.\n ///\n /// # Advanced\n ///\n /// This function performs a historical read using the block header from the private\n /// context. The `WithHash` optimization is particularly valuable here because it\n /// reduces the number of required inclusion proofs by proving membership of\n /// only the hash instead of the full packed value.\n ///\n /// The historical read mechanism:\n /// - Uses an oracle to obtain the value from the historical block\n /// - Proves inclusion of the value's hash in the public data tree\n /// - Proves that the root of this public data tree is correct, relative to the\n /// historical block header that is being referenced by this private function.\n /// - Verifies that the oracle-provided value matches the stored hash\n ///\n pub fn read(self) -> T\n where\n T: Packable + Eq,\n {\n // TODO(#15703): this fn should fail if the variable is not initialized\n WithHash::historical_public_storage_read(\n self.context.get_block_header(),\n self.context.this_address(),\n self.storage_slot,\n )\n }\n}\n" - }, - "187": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr", - "source": "use crate::context::{PublicContext, UtilityContext};\nuse crate::state_vars::storage::HasStorageSlot;\nuse dep::protocol_types::traits::Packable;\n\n/// # PublicMutable\n///\n/// PublicMutable is a public state variable type for values that can be read\n/// and written within #[public] functions of your smart contract.\n///\n/// You can declare a state variable of type PublicMutable within your contract's\n/// #[storage] struct:\n///\n/// E.g.:\n/// `your_variable: PublicMutable`\n/// or:\n/// `your_mapping: Map>`\n///\n/// The methods of PublicMutable are:\n/// - `read`\n/// - `write`\n/// (see the methods' own doc comments for more info).\n///\n/// ## Example.\n///\n/// A voting contract's proposal count can be represented as a PublicMutable.\n/// The count can be read by anyone to see how many proposals exist, and incremented\n/// when new proposals are submitted.\n///\n/// # Generic Parameters:\n///\n/// * `T` - The type of value stored (must implement Packable).\n/// * `Context` - The execution context (PublicContext or UtilityContext).\n///\n/// # Advanced\n///\n/// Unlike private state variables which use notes, PublicMutable stores values\n/// directly in Aztec's public data tree. This enables direct read and write\n/// access to the current state during public function execution.\n///\n/// docs:start:public_mutable_struct\npub struct PublicMutable {\n context: Context,\n storage_slot: Field,\n}\n// docs:end:public_mutable_struct\n\nimpl HasStorageSlot for PublicMutable\nwhere\n T: Packable,\n{\n fn get_storage_slot(self) -> Field {\n self.storage_slot\n }\n}\n\nimpl PublicMutable {\n /// Initializes a new PublicMutable state variable.\n ///\n /// This function is usually automatically called within the #[storage] macro.\n /// You typically don't need to call this directly when writing smart contracts.\n ///\n /// # Arguments\n ///\n /// * `context` - One of `PublicContext`/`UtilityContext`. The Context determines\n /// which methods of this struct will be made available to the calling\n /// smart contract function.\n /// * `storage_slot` - A unique identifier for this state variable within the\n /// contract. Usually, the #[storage] macro will determine an\n /// appropriate storage_slot automatically. A smart contract\n /// dev shouldn't have to worry about this, as it's managed\n /// behind the scenes.\n ///\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 /// Reads the current value stored in this PublicMutable state variable.\n ///\n /// # Returns\n ///\n /// * `T` - The current value stored in this PublicMutable.\n ///\n /// docs:start:public_mutable_struct_read\n pub fn read(self) -> T\n where\n T: Packable,\n {\n self.context.storage_read(self.storage_slot)\n }\n // docs:end:public_mutable_struct_read\n\n /// Writes a new value to this PublicMutable state variable.\n ///\n /// # Arguments\n ///\n /// * `value` - The new value to store in this PublicMutable.\n ///\n /// # Advanced\n ///\n /// This function updates the value stored in Aztec's public data tree.\n /// The new value becomes immediately available to subsequent reads within\n /// the same transaction.\n ///\n /// docs:start:public_mutable_struct_write\n pub fn write(self, value: T)\n where\n T: Packable,\n {\n self.context.storage_write(self.storage_slot, value);\n }\n // docs:end:public_mutable_struct_write\n}\n\nimpl PublicMutable {\n /// Reads the current value stored in this PublicMutable state variable.\n ///\n /// Notice that this function is executable only within a UtilityContext, which\n /// is an unconstrained environment on the user's local device.\n ///\n /// # Returns\n ///\n /// * `T` - The current value stored in this PublicMutable.\n ///\n pub unconstrained fn read(self) -> T\n where\n T: Packable,\n {\n self.context.storage_read(self.storage_slot)\n }\n}\n" - }, - "19": { - "path": "std/hash/mod.nr", - "source": "// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3(input: [u8; N]) -> [u8; 32] {}\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#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\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#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\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.)\npub trait 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.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n type H = H;\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)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\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)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\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)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\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\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n" - }, - "203": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/array/append.nr", - "source": "/// Appends the elements of the second `BoundedVec` to the end of the first one. The resulting `BoundedVec` can have any arbitrary maximum length, but it must be\n/// large enough to fit all of the elements of both the first and second vectors.\npub fn append(\n a: BoundedVec,\n b: BoundedVec,\n) -> BoundedVec {\n let mut dst = BoundedVec::new();\n\n dst.extend_from_bounded_vec(a);\n dst.extend_from_bounded_vec(b);\n\n dst\n}\n\nmod test {\n use super::append;\n\n #[test]\n unconstrained fn append_empty_vecs() {\n let a: BoundedVec<_, 3> = BoundedVec::new();\n let b: BoundedVec<_, 14> = BoundedVec::new();\n\n let result: BoundedVec = append(a, b);\n\n assert_eq(result.len(), 0);\n assert_eq(result.storage(), std::mem::zeroed());\n }\n\n #[test]\n unconstrained fn append_non_empty_vecs() {\n let a: BoundedVec<_, 3> = BoundedVec::from_array([1, 2, 3]);\n let b: BoundedVec<_, 14> = BoundedVec::from_array([4, 5, 6]);\n\n let result: BoundedVec = append(a, b);\n\n assert_eq(result.len(), 6);\n assert_eq(result.storage(), [1, 2, 3, 4, 5, 6, std::mem::zeroed(), std::mem::zeroed()]);\n }\n\n #[test(should_fail_with = \"out of bounds\")]\n unconstrained fn append_non_empty_vecs_insufficient_max_len() {\n let a: BoundedVec<_, 3> = BoundedVec::from_array([1, 2, 3]);\n let b: BoundedVec<_, 14> = BoundedVec::from_array([4, 5, 6]);\n\n let _: BoundedVec = append(a, b);\n }\n}\n" - }, - "206": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/array/subarray.nr", - "source": "/// Returns `DstLen` elements from a source array, starting at `offset`. `DstLen` must not be larger than the number\n/// of elements past `offset`.\n///\n/// Examples:\n/// ```\n/// let foo: [Field; 2] = subarray([1, 2, 3, 4, 5], 2);\n/// assert_eq(foo, [3, 4]);\n///\n/// let bar: [Field; 5] = subarray([1, 2, 3, 4, 5], 2); // fails - we can't return 5 elements since only 3 remain\n/// ```\npub fn subarray(src: [T; SrcLen], offset: u32) -> [T; DstLen] {\n assert(offset + DstLen <= SrcLen, \"DstLen too large for offset\");\n\n let mut dst: [T; DstLen] = std::mem::zeroed();\n for i in 0..DstLen {\n dst[i] = src[i + offset];\n }\n\n dst\n}\n\nmod test {\n use super::subarray;\n\n #[test]\n unconstrained fn subarray_into_empty() {\n // In all of these cases we're setting DstLen to be 0, so we always get back an empty array.\n assert_eq(subarray::([], 0), []);\n assert_eq(subarray([1, 2, 3, 4, 5], 0), []);\n assert_eq(subarray([1, 2, 3, 4, 5], 2), []);\n }\n\n #[test]\n unconstrained fn subarray_complete() {\n assert_eq(subarray::([], 0), []);\n assert_eq(subarray([1, 2, 3, 4, 5], 0), [1, 2, 3, 4, 5]);\n }\n\n #[test]\n unconstrained fn subarray_different_end_sizes() {\n // We implicitly select how many values to read in the size of the return array\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2, 3, 4, 5]);\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2, 3, 4]);\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2, 3]);\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [2]);\n }\n\n #[test(should_fail_with = \"DstLen too large for offset\")]\n unconstrained fn subarray_offset_too_large() {\n // With an offset of 1 we can only request up to 4 elements\n let _: [_; 5] = subarray([1, 2, 3, 4, 5], 1);\n }\n\n #[test(should_fail)]\n unconstrained fn subarray_bad_return_value() {\n assert_eq(subarray([1, 2, 3, 4, 5], 1), [3, 3, 4, 5]);\n }\n}\n" - }, - "207": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/array/subbvec.nr", - "source": "use crate::utils::array;\n\n/// Returns `DstMaxLen` elements from a source BoundedVec, starting at `offset`. `offset` must not be larger than the\n/// original length, and `DstLen` must not be larger than the total number of elements past `offset` (including the\n/// zeroed elements past `len()`).\n///\n/// Only elements at the beginning of the vector can be removed: it is not possible to also remove elements at the end\n/// of the vector by passing a value for `DstLen` that is smaller than `len() - offset`.\n///\n/// Examples:\n/// ```\n/// let foo = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n/// assert_eq(subbvec(foo, 2), BoundedVec::<_, 8>::from_array([3, 4, 5]));\n///\n/// let bar: BoundedVec<_, 1> = subbvec(foo, 2); // fails - we can't return just 1 element since 3 remain\n/// let baz: BoundedVec<_, 10> = subbvec(foo, 3); // fails - we can't return 10 elements since only 7 remain\n/// ```\npub fn subbvec(\n bvec: BoundedVec,\n offset: u32,\n) -> BoundedVec {\n // from_parts_unchecked does not verify that the elements past len are zeroed, but that is not an issue in our case\n // because we're constructing the new storage array as a subarray of the original one (which should have zeroed\n // storage past len), guaranteeing correctness. This is because `subarray` does not allow extending arrays past\n // their original length.\n BoundedVec::from_parts_unchecked(array::subarray(bvec.storage(), offset), bvec.len() - offset)\n}\n\nmod test {\n use super::subbvec;\n\n #[test]\n unconstrained fn subbvec_empty() {\n let bvec = BoundedVec::::from_array([]);\n assert_eq(subbvec(bvec, 0), bvec);\n }\n\n #[test]\n unconstrained fn subbvec_complete() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n assert_eq(subbvec(bvec, 0), bvec);\n\n let smaller_capacity = BoundedVec::<_, 5>::from_array([1, 2, 3, 4, 5]);\n assert_eq(subbvec(bvec, 0), smaller_capacity);\n }\n\n #[test]\n unconstrained fn subbvec_partial() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n assert_eq(subbvec(bvec, 2), BoundedVec::<_, 8>::from_array([3, 4, 5]));\n assert_eq(subbvec(bvec, 2), BoundedVec::<_, 3>::from_array([3, 4, 5]));\n }\n\n #[test]\n unconstrained fn subbvec_into_empty() {\n let bvec: BoundedVec<_, 10> = BoundedVec::from_array([1, 2, 3, 4, 5]);\n assert_eq(subbvec(bvec, 5), BoundedVec::<_, 5>::from_array([]));\n }\n\n #[test(should_fail)]\n unconstrained fn subbvec_offset_past_len() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n let _: BoundedVec<_, 1> = subbvec(bvec, 6);\n }\n\n #[test(should_fail)]\n unconstrained fn subbvec_insufficient_dst_len() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n // We're not providing enough space to hold all of the items inside the original BoundedVec. subbvec can cause\n // for the capacity to reduce, but not the length (other than by len - offset).\n let _: BoundedVec<_, 1> = subbvec(bvec, 2);\n }\n\n #[test(should_fail_with = \"DstLen too large for offset\")]\n unconstrained fn subbvec_dst_len_causes_enlarge() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n // subbvec does not supprt capacity increases\n let _: BoundedVec<_, 11> = subbvec(bvec, 0);\n }\n\n #[test(should_fail_with = \"DstLen too large for offset\")]\n unconstrained fn subbvec_dst_len_too_large_for_offset() {\n let bvec = BoundedVec::<_, 10>::from_array([1, 2, 3, 4, 5]);\n\n // This effectively requests a capacity increase, since there'd be just one element plus the 5 empty slots,\n // which is less than 7.\n let _: BoundedVec<_, 7> = subbvec(bvec, 4);\n }\n}\n" - }, - "209": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/conversion/bytes_to_fields.nr", - "source": "use std::static_assert;\n\n// These functions are used to facilitate the conversion of log ciphertext between byte and field representations.\n//\n// `bytes_to_fields` uses fixed-size arrays since encryption contexts have compile-time size information.\n// `bytes_from_fields` uses BoundedVec for flexibility in unconstrained contexts where sizes are dynamic.\n//\n// Together they provide bidirectional conversion between bytes and fields when processing encrypted logs.\n\n/// Converts the input bytes into an array of fields. A Field is ~254 bits meaning that each field can store 31 whole\n/// bytes. Use `bytes_from_fields` to obtain the original bytes array.\n///\n/// The input bytes are chunked into chunks of 31 bytes. Each 31-byte chunk is viewed as big-endian, and is converted\n/// into a Field.\n/// For example, [1, 10, 3, ..., 0] (31 bytes) is encoded as [1 * 256^30 + 10 * 256^29 + 3 * 256^28 + ... + 0]\n/// Note: N must be a multiple of 31 bytes\npub fn bytes_to_fields(bytes: [u8; N]) -> [Field; N / 31] {\n // Assert that N is a multiple of 31\n static_assert(N % 31 == 0, \"N must be a multiple of 31\");\n\n let mut fields = [0; N / 31];\n\n // Since N is a multiple of 31, we can simply process all chunks fully\n for i in 0..N / 31 {\n let mut field = 0;\n for j in 0..31 {\n // Shift the existing value left by 8 bits and add the new byte\n field = field * 256 + bytes[i * 31 + j] as Field;\n }\n fields[i] = field;\n }\n\n fields\n}\n\n/// Converts an input BoundedVec of fields into a BoundedVec of bytes in big-endian order. Arbitrary Field arrays\n/// are not allowed: this is assumed to be an array obtained via `bytes_to_fields`, i.e. one that actually represents\n/// bytes. To convert a Field array into bytes, use `fields_to_bytes`.\n///\n/// Each input field must contain at most 31 bytes (this is constrained to be so).\n/// Each field is converted into 31 big-endian bytes, and the resulting 31-byte chunks are concatenated\n/// back together in the order of the original fields.\npub fn bytes_from_fields(fields: BoundedVec) -> BoundedVec {\n let mut bytes = BoundedVec::new();\n\n for i in 0..fields.len() {\n let field = fields.get(i);\n\n // We expect that the field contains at most 31 bytes of information.\n field.assert_max_bit_size::<248>();\n\n // Now we can safely convert the field to 31 bytes.\n let field_as_bytes: [u8; 31] = field.to_be_bytes();\n\n for j in 0..31 {\n bytes.push(field_as_bytes[j]);\n }\n }\n\n bytes\n}\n\nmod tests {\n use crate::utils::array::subarray;\n use super::{bytes_from_fields, bytes_to_fields};\n\n #[test]\n unconstrained fn random_bytes_to_fields_and_back(input: [u8; 93]) {\n let fields = bytes_to_fields(input);\n\n // At this point in production, the log flies through the system and we get a BoundedVec on the other end.\n // So we need to convert the field array to a BoundedVec to be able to feed it to the `bytes_from_fields`\n // function.\n let fields_as_bounded_vec = BoundedVec::<_, 6>::from_array(fields);\n\n let bytes_back = bytes_from_fields(fields_as_bounded_vec);\n\n // Compare the original input with the round-tripped result\n assert_eq(bytes_back.len(), input.len());\n assert_eq(subarray(bytes_back.storage(), 0), input);\n }\n\n #[test(should_fail_with = \"N must be a multiple of 31\")]\n unconstrained fn bytes_to_fields_input_length_not_multiple_of_31() {\n // Try to convert 32 bytes (not a multiple of 31) to fields\n let _fields = bytes_to_fields([0; 32]);\n }\n\n}\n" - }, - "210": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/conversion/fields_to_bytes.nr", - "source": "// These functions are used to facilitate the conversion of log plaintext represented as fields into bytes and back.\n//\n// `fields_to_bytes` uses fixed-size arrays since encryption contexts have compile-time size information.\n// `fields_from_bytes` uses BoundedVec for flexibility in unconstrained contexts where sizes are dynamic.\n//\n// Together they provide bidirectional conversion between fields and bytes.\n\n/// Converts an input array of fields into a single array of bytes. Use `fields_from_bytes` to obtain the original\n/// field array.\n/// Each field is converted to a 32-byte big-endian array.\n///\n/// For example, if you have a field array [123, 456], it will be converted to a 64-byte array:\n/// [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,123, // First field (32 bytes)\n/// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,200] // Second field (32 bytes)\n///\n/// Since a field is ~254 bits, you'll end up with a subtle 2-bit \"gap\" at the big end, every 32 bytes. Be careful\n/// that such a gap doesn't leak information! This could happen if you for example expected the output to be\n/// indistinguishable from random bytes.\npub fn fields_to_bytes(fields: [Field; N]) -> [u8; 32 * N] {\n let mut bytes = [0; 32 * N];\n\n for i in 0..N {\n let field_as_bytes: [u8; 32] = fields[i].to_be_bytes();\n\n for j in 0..32 {\n bytes[i * 32 + j] = field_as_bytes[j];\n }\n }\n\n bytes\n}\n\n/// Converts an input BoundedVec of bytes into a BoundedVec of fields. Arbitrary byte arrays are not allowed: this\n/// is assumed to be an array obtained via `fields_to_bytes`, i.e. one that actually represents fields. To convert\n/// a byte array into Fields, use `bytes_to_fields`.\n///\n/// The input bytes are chunked into chunks of 32 bytes. Each 32-byte chunk is viewed as big-endian, and is converted\n/// into a Field.\n/// For example, [1, 10, 3, ..., 0] (32 bytes) is encoded as [1 * 256^31 + 10 * 256^30 + 3 * 256^29 + ... + 0]\n/// Note 1: N must be a multiple of 32 bytes\n/// Note 2: The max value check code was taken from std::field::to_be_bytes function.\npub fn fields_from_bytes(bytes: BoundedVec) -> BoundedVec {\n // Assert that input length is a multiple of 32\n assert(bytes.len() % 32 == 0, \"Input length must be a multiple of 32\");\n\n let mut fields = BoundedVec::new();\n\n let p = std::field::modulus_be_bytes();\n\n // Since input length is a multiple of 32, we can simply process all chunks fully\n for i in 0..bytes.len() / 32 {\n let mut field = 0;\n\n // Process each byte in the 32-byte chunk\n let mut ok = false;\n\n for j in 0..32 {\n let next_byte = bytes.get(i * 32 + j);\n field = field * 256 + next_byte as Field;\n\n if !ok {\n if next_byte != p[j] {\n assert(next_byte < p[j], \"Value does not fit in field\");\n ok = true;\n }\n }\n }\n assert(ok, \"Value does not fit in field\");\n\n fields.push(field);\n }\n\n fields\n}\n\nmod tests {\n use crate::utils::array::subarray;\n use super::{fields_from_bytes, fields_to_bytes};\n\n #[test]\n unconstrained fn random_fields_to_bytes_and_back(input: [Field; 3]) {\n // Convert to bytes\n let bytes = fields_to_bytes(input);\n\n // At this point in production, the log flies through the system and we get a BoundedVec on the other end.\n // So we need to convert the field array to a BoundedVec to be able to feed it to the `fields_from_bytes`\n // function.\n // 113 is an arbitrary max length that is larger than the input length of 96.\n let bytes_as_bounded_vec = BoundedVec::<_, 113>::from_array(bytes);\n\n // Convert back to fields\n let fields_back = fields_from_bytes(bytes_as_bounded_vec);\n\n // Compare the original input with the round-tripped result\n assert_eq(fields_back.len(), input.len());\n assert_eq(subarray(fields_back.storage(), 0), input);\n }\n\n #[test(should_fail_with = \"Input length must be a multiple of 32\")]\n unconstrained fn to_fields_assert() {\n // 143 is an arbitrary max length that is larger than 33\n let input = BoundedVec::<_, 143>::from_array([\n 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n 25, 26, 27, 28, 29, 30, 31, 32, 33,\n ]);\n\n // This should fail since 33 is not a multiple of 32\n let _fields = fields_from_bytes(input);\n }\n\n #[test]\n unconstrained fn fields_from_bytes_max_value() {\n let max_field_as_bytes: [u8; 32] = (-1).to_be_bytes();\n let input = BoundedVec::<_, 32>::from_array(max_field_as_bytes);\n\n let fields = fields_from_bytes(input);\n\n // The result should be a largest value storable in a field (-1 since we are modulo-ing)\n assert_eq(fields.get(0), -1);\n }\n\n // In this test we verify that overflow check works by taking the max allowed value, bumping a random byte\n // and then feeding it to `fields_from_bytes` as input.\n #[test(should_fail_with = \"Value does not fit in field\")]\n unconstrained fn fields_from_bytes_overflow(random_value: u8) {\n let index_of_byte_to_bump = random_value % 32;\n\n // Obtain the byte representation of the maximum field value\n let max_field_value_as_bytes: [u8; 32] = (-1).to_be_bytes();\n\n let byte_to_bump = max_field_value_as_bytes[index_of_byte_to_bump as u32];\n\n // Skip test execution if the selected byte is already at maximum value (255).\n // This is acceptable since we are using fuzz testing to generate many test cases.\n if byte_to_bump != 255 {\n let mut input = BoundedVec::<_, 32>::from_array(max_field_value_as_bytes);\n\n // Increment the selected byte to exceed the field's maximum value\n input.set(index_of_byte_to_bump as u32, byte_to_bump + 1);\n\n // Attempt the conversion, which should fail due to the value exceeding the field's capacity\n let _fields = fields_from_bytes(input);\n }\n }\n\n}\n" - }, - "212": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/field.nr", - "source": "use std::option::Option;\n\nglobal KNOWN_NON_RESIDUE: Field = 5; // This is a non-residue in Noir's native Field.\n\nglobal C1: u32 = 28;\nglobal C3: Field = 40770029410420498293352137776570907027550720424234931066070132305055;\nglobal C5: Field = 19103219067921713944291392827692070036145651957329286315305642004821462161904;\n\n// Power function of two Field arguments of arbitrary size.\n// Adapted from std::field::pow_32.\npub fn pow(x: Field, y: Field) -> Field {\n let mut r = 1 as Field;\n let b: [u1; 254] = y.to_le_bits();\n\n for i in 0..254 {\n r *= r;\n r *= (b[254 - 1 - i] as Field) * x + (1 - b[254 - 1 - i] as Field);\n }\n\n r\n}\n\n// Boolean indicating whether Field element is a square, i.e. whether there exists a y in Field s.t. x = y*y.\nunconstrained fn is_square(x: Field) -> bool {\n let v = pow(x, -1 / 2);\n v * (v - 1) == 0\n}\n\n// Tonelli-Shanks algorithm for computing the square root of a Field element.\n// Requires C1 = max{c: 2^c divides (p-1)}, where p is the order of Field\n// as well as C3 = (C2 - 1)/2, where C2 = (p-1)/(2^c1),\n// and C5 = ZETA^C2, where ZETA is a non-square element of Field.\n// These are pre-computed above as globals.\nunconstrained fn tonelli_shanks_sqrt(x: Field) -> Field {\n let mut z = pow(x, C3);\n let mut t = z * z * x;\n z *= x;\n let mut b = t;\n let mut c = C5;\n\n for i in 0..(C1 - 1) {\n for _j in 1..(C1 - i - 1) {\n b *= b;\n }\n\n z *= if b == 1 { 1 } else { c };\n\n c *= c;\n\n t *= if b == 1 { 1 } else { c };\n\n b = t;\n }\n\n z\n}\n\n// NB: this doesn't return an option, because in the case of there _not_ being a square root, we still want to return a field element that allows us to then assert in the _constrained_ sqrt function that there is no sqrt.\npub unconstrained fn __sqrt(x: Field) -> (bool, Field) {\n let is_sq = is_square(x);\n if is_sq {\n let sqrt = tonelli_shanks_sqrt(x);\n (true, sqrt)\n } else {\n // Demonstrate that x is not a square (a.k.a. a \"quadratic non-residue\").\n // Facts:\n // The Legendre symbol (\"LS\") of x, is x^((p-1)/2) (mod p).\n // - If x is a square, LS(x) = 1\n // - If x is not a square, LS(x) = -1\n // - If x = 0, LS(x) = 0.\n //\n // Hence:\n // sq * sq = sq // 1 * 1 = 1\n // non-sq * non-sq = sq // -1 * -1 = 1\n // sq * non-sq = non-sq // -1 * 1 = -1\n //\n // See: https://en.wikipedia.org/wiki/Legendre_symbol\n let demo_x_not_square = x * KNOWN_NON_RESIDUE;\n let not_sqrt = tonelli_shanks_sqrt(demo_x_not_square);\n (false, not_sqrt)\n }\n}\n\n// Returns (false, 0) if there is no square root.\n// Returns (true, sqrt) if there is a square root.\npub fn sqrt(x: Field) -> Option {\n // Safety: if the hint returns the square root of x, then we simply square it\n // check the result equals x. If x is not square, we return a value that\n // enables us to prove that fact (see the `else` clause below).\n let (is_sq, maybe_sqrt) = unsafe { __sqrt(x) };\n\n if is_sq {\n let sqrt = maybe_sqrt;\n validate_sqrt_hint(x, sqrt);\n Option::some(sqrt)\n } else {\n let not_sqrt_hint = maybe_sqrt;\n validate_not_sqrt_hint(x, not_sqrt_hint);\n Option::none()\n }\n}\n\nfn validate_sqrt_hint(x: Field, hint: Field) {\n assert(hint * hint == x, f\"The claimed_sqrt {hint} is not the sqrt of x {x}\");\n}\n\nfn validate_not_sqrt_hint(x: Field, hint: Field) {\n // We need this assertion, because x = 0 would pass the other assertions in this\n // function, and we don't want people to be able to prove that 0 is not square!\n assert(x != 0, \"0 has a square root; you cannot claim it is not square\");\n // Demonstrate that x is not a square (a.k.a. a \"quadratic non-residue\").\n //\n // Facts:\n // The Legendre symbol (\"LS\") of x, is x^((p-1)/2) (mod p).\n // - If x is a square, LS(x) = 1\n // - If x is not a square, LS(x) = -1\n // - If x = 0, LS(x) = 0.\n //\n // Hence:\n // 1. sq * sq = sq // 1 * 1 = 1\n // 2. non-sq * non-sq = sq // -1 * -1 = 1\n // 3. sq * non-sq = non-sq // -1 * 1 = -1\n //\n // See: https://en.wikipedia.org/wiki/Legendre_symbol\n //\n // We want to demonstrate that this below multiplication falls under bullet-point (2):\n let demo_x_not_square = x * KNOWN_NON_RESIDUE;\n // I.e. we want to demonstrate that `demo_x_not_square` has Legendre symbol 1\n // (i.e. that it is a square), so we prove that it is square below.\n // Why do we want to prove that it has LS 1?\n // Well, since it was computed with a known-non-residue, its squareness implies we're\n // in case 2 (something multiplied by a known-non-residue yielding a result which\n // has a LS of 1), which implies that x must be a non-square. The unconstrained\n // function gave us the sqrt of demo_x_not_square, so all we need to do is\n // assert its squareness:\n assert(\n hint * hint == demo_x_not_square,\n f\"The hint {hint} does not demonstrate that {x} is not a square\",\n );\n}\n\n#[test]\nfn test_sqrt() {\n let x = 9;\n let maybe_sqrt = sqrt(x);\n assert(maybe_sqrt.is_some());\n let sqrt = maybe_sqrt.unwrap_unchecked();\n assert((sqrt == 3) | (sqrt == -3));\n}\n\n#[test]\nfn test_non_square() {\n let x = 5;\n let maybe_sqrt = sqrt(x);\n assert(maybe_sqrt.is_none());\n}\n\n#[test]\nunconstrained fn test_known_non_residue_is_actually_a_non_residue_in_the_field() {\n assert(!is_square(KNOWN_NON_RESIDUE));\n}\n\n#[test]\nfn test_sqrt_0() {\n let x = 0;\n let sqrt = sqrt(x).unwrap();\n assert(sqrt == 0);\n}\n\n#[test]\nfn test_sqrt_1() {\n let x = 1;\n let sqrt = sqrt(x).unwrap();\n assert((sqrt == 1) | (sqrt == -1));\n}\n\n#[test(should_fail_with = \"The claimed_sqrt 0x04 is not the sqrt of x 0x09\")]\nfn test_bad_sqrt_hint_fails() {\n validate_sqrt_hint(9, 4);\n}\n\n#[test(should_fail_with = \"The hint 0x04 does not demonstrate that 0x0a is not a square\")]\nfn test_bad_not_sqrt_hint_fails() {\n validate_not_sqrt_hint(10, 4);\n}\n\n#[test(should_fail_with = \"0 has a square root; you cannot claim it is not square\")]\nfn test_0_not_sqrt_hint_fails() {\n validate_not_sqrt_hint(0, 0);\n}\n\n#[test]\nunconstrained fn test_is_square() {\n assert(is_square(25));\n}\n\n#[test]\nunconstrained fn test_is_not_square() {\n assert(!is_square(10));\n}\n" - }, - "214": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/point.nr", - "source": "use crate::utils::field::sqrt;\nuse dep::protocol_types::point::Point;\n\n// I am storing the modulus minus 1 divided by 2 here because full modulus would throw \"String literal too large\" error\n// Full modulus is 21888242871839275222246405745257275088548364400416034343698204186575808495617\nglobal BN254_FR_MODULUS_DIV_2: Field =\n 10944121435919637611123202872628637544274182200208017171849102093287904247808;\n\n/// Converts a point to a byte array.\n///\n/// We don't serialize the point at infinity flag because this function is used in situations where we do not want\n/// to waste the extra byte (encrypted log).\npub fn point_to_bytes(p: Point) -> [u8; 32] {\n // Note that there is 1 more free bit in the 32 bytes (254 bits currently occupied by the x coordinate, 1 bit for\n // the \"sign\") so it's possible to use that last bit as an \"is_infinite\" flag if desired in the future.\n assert(!p.is_infinite, \"Cannot serialize point at infinity as bytes.\");\n\n let mut result: [u8; 32] = p.x.to_be_bytes();\n\n if get_sign_of_point(p) {\n // y is <= (modulus - 1) / 2 so we set the sign bit to 1\n // Here we leverage that field fits into 254 bits (log2(Fr.MODULUS) < 254) and given that we serialize Fr to 32\n // bytes and we use big-endian the 2 most significant bits are never populated. Hence we can use one of\n // the bits as a sign bit.\n result[0] += 128;\n }\n\n result\n}\n\n/**\n * Returns: true if p.y <= MOD_DIV_2, else false.\n */\npub fn get_sign_of_point(p: Point) -> bool {\n // We store only a \"sign\" of the y coordinate because the rest can be derived from the x coordinate. To get\n // the sign we check if the y coordinate is less or equal than the curve's order minus 1 divided by 2.\n // Ideally we'd do `y <= MOD_DIV_2`, but there's no `lte` function, so instead we do `!(y > MOD_DIV_2)`, which is\n // equivalent, and then rewrite that as `!(MOD_DIV_2 < y)`, since we also have no `gt` function.\n !BN254_FR_MODULUS_DIV_2.lt(p.y)\n}\n\npub fn point_from_x_coord(x: Field) -> Point {\n // y ^ 2 = x ^ 3 - 17\n let rhs = x * x * x - 17;\n let y = sqrt(rhs).unwrap();\n Point { x, y, is_infinite: false }\n}\n\n/// Uses the x coordinate and sign flag (+/-) to reconstruct the point.\n/// The y coordinate can be derived from the x coordinate and the \"sign\" flag by solving the grumpkin curve\n/// equation for y.\n/// @param x - The x coordinate of the point\n/// @param sign - The \"sign\" of the y coordinate - determines whether y <= (Fr.MODULUS - 1) / 2\npub fn point_from_x_coord_and_sign(x: Field, sign: bool) -> Point {\n // y ^ 2 = x ^ 3 - 17\n let rhs = x * x * x - 17;\n let y = sqrt(rhs).unwrap();\n\n // If y > MOD_DIV_2 and we want positive sign (or vice versa), negate y\n let y_is_positive = !BN254_FR_MODULUS_DIV_2.lt(y);\n let final_y = if y_is_positive == sign { y } else { -y };\n\n Point { x, y: final_y, is_infinite: false }\n}\n\nmod test {\n use crate::utils::point::{point_from_x_coord_and_sign, point_to_bytes};\n use dep::protocol_types::point::Point;\n\n #[test]\n unconstrained fn test_point_to_bytes_positive_sign() {\n let p = Point {\n x: 0x1af41f5de96446dc3776a1eb2d98bb956b7acd9979a67854bec6fa7c2973bd73,\n y: 0x07fc22c7f2c7057571f137fe46ea9c95114282bc95d37d71ec4bfb88de457d4a,\n is_infinite: false,\n };\n\n let compressed_point = point_to_bytes(p);\n\n let expected_compressed_point_positive_sign = [\n 154, 244, 31, 93, 233, 100, 70, 220, 55, 118, 161, 235, 45, 152, 187, 149, 107, 122,\n 205, 153, 121, 166, 120, 84, 190, 198, 250, 124, 41, 115, 189, 115,\n ];\n assert_eq(expected_compressed_point_positive_sign, compressed_point);\n }\n\n #[test]\n unconstrained fn test_point_to_bytes_negative_sign() {\n let p = Point {\n x: 0x247371652e55dd74c9af8dbe9fb44931ba29a9229994384bd7077796c14ee2b5,\n y: 0x26441aec112e1ae4cee374f42556932001507ad46e255ffb27369c7e3766e5c0,\n is_infinite: false,\n };\n\n let compressed_point = point_to_bytes(p);\n\n let expected_compressed_point_negative_sign = [\n 36, 115, 113, 101, 46, 85, 221, 116, 201, 175, 141, 190, 159, 180, 73, 49, 186, 41, 169,\n 34, 153, 148, 56, 75, 215, 7, 119, 150, 193, 78, 226, 181,\n ];\n\n assert_eq(expected_compressed_point_negative_sign, compressed_point);\n }\n\n #[test]\n unconstrained fn test_point_from_x_coord_and_sign() {\n // Test positive y coordinate\n let x = 0x1af41f5de96446dc3776a1eb2d98bb956b7acd9979a67854bec6fa7c2973bd73;\n let sign = true;\n let p = point_from_x_coord_and_sign(x, sign);\n\n assert_eq(p.x, x);\n assert_eq(p.y, 0x07fc22c7f2c7057571f137fe46ea9c95114282bc95d37d71ec4bfb88de457d4a);\n assert_eq(p.is_infinite, false);\n\n // Test negative y coordinate\n let x2 = 0x247371652e55dd74c9af8dbe9fb44931ba29a9229994384bd7077796c14ee2b5;\n let sign2 = false;\n let p2 = point_from_x_coord_and_sign(x2, sign2);\n\n assert_eq(p2.x, x2);\n assert_eq(p2.y, 0x26441aec112e1ae4cee374f42556932001507ad46e255ffb27369c7e3766e5c0);\n assert_eq(p2.is_infinite, false);\n }\n}\n" - }, - "219": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/utils/with_hash.nr", - "source": "use crate::{\n context::{PublicContext, UtilityContext},\n history::public_storage::PublicStorageHistoricalRead,\n oracle,\n};\nuse dep::protocol_types::{\n abis::block_header::BlockHeader, address::AztecAddress, hash::poseidon2_hash, traits::Packable,\n};\n\n/// A struct that allows for efficient reading of value `T` from public storage in private.\n///\n/// The efficient reads are achieved by verifying large values through a single hash check\n/// and then proving inclusion only of the hash in public storage. This reduces the number\n/// of required tree inclusion proofs from `M` to 1.\n///\n/// # Type Parameters\n/// - `T`: The underlying type being wrapped, must implement `Packable`\n/// - `M`: The number of field elements required to pack values of type `T`\npub struct WithHash {\n value: T,\n packed: [Field; M],\n hash: Field,\n}\n\nimpl WithHash\nwhere\n T: Packable + Eq,\n{\n pub fn new(value: T) -> Self {\n let packed = value.pack();\n Self { value, packed, hash: poseidon2_hash(packed) }\n }\n\n pub fn get_value(self) -> T {\n self.value\n }\n\n pub fn get_hash(self) -> Field {\n self.hash\n }\n\n pub fn public_storage_read(context: PublicContext, storage_slot: Field) -> T {\n context.storage_read(storage_slot)\n }\n\n pub unconstrained fn utility_public_storage_read(\n context: UtilityContext,\n storage_slot: Field,\n ) -> T {\n context.storage_read(storage_slot)\n }\n\n pub fn historical_public_storage_read(\n header: BlockHeader,\n address: AztecAddress,\n storage_slot: Field,\n ) -> T {\n let historical_block_number = header.global_variables.block_number;\n\n // We could simply produce historical inclusion proofs for each field in `packed`, but that would require one\n // full sibling path per storage slot (since due to kernel siloing the storage is not contiguous). Instead, we\n // get an oracle to provide us the values, and instead we prove inclusion of their hash, which is both a much\n // smaller proof (a single slot), and also independent of the size of T (except in that we need to pack and hash T).\n let hint = WithHash::new(\n // Safety: We verify that a hash of the hint/packed data matches the stored hash.\n unsafe {\n oracle::storage::storage_read(address, storage_slot, historical_block_number)\n },\n );\n\n let hash = header.public_storage_historical_read(storage_slot + M as Field, address);\n\n if hash != 0 {\n assert_eq(hash, hint.get_hash(), \"Hint values do not match hash\");\n } else {\n // The hash slot can only hold a zero if it is uninitialized. Therefore, the hints must then be zero\n // (i.e. the default value for public storage) as well.\n assert_eq(\n hint.get_value(),\n T::unpack(std::mem::zeroed()),\n \"Non-zero hint for zero hash\",\n );\n };\n\n hint.get_value()\n }\n}\n\n// Note: I don't derive Packable on `WithHash` because `derive_serialize` function does not support setting \"N = M\"\n// as I do here 3 lines below. This could be worked around by placing the \"where\" clause directly on the `WithHash`\n// struct, but Jake mentioned that the syntax is not expected to be supported at least until Noir 1.0.\n// Relevant discussion on Slack:\n// https://aztecprotocol.slack.com/archives/C04QF64EDNV/p1752593876160699?thread_ts=1752589887.955379&cid=C04QF64EDNV\nimpl Packable for WithHash\nwhere\n T: Packable,\n{\n let N: u32 = M + 1;\n\n fn pack(self) -> [Field; Self::N] {\n let mut result: [Field; Self::N] = std::mem::zeroed();\n for i in 0..M {\n result[i] = self.packed[i];\n }\n result[M] = self.hash;\n\n result\n }\n\n fn unpack(packed: [Field; Self::N]) -> Self {\n let mut value_packed = [0; M];\n for i in 0..M {\n value_packed[i] = packed[i];\n }\n let hash = packed[M];\n\n Self { value: T::unpack(value_packed), packed: value_packed, hash }\n }\n}\n\nmod test {\n use crate::{\n test::{helpers::test_environment::TestEnvironment, mocks::mock_struct::MockStruct},\n utils::with_hash::WithHash,\n };\n use dep::protocol_types::hash::poseidon2_hash;\n use dep::protocol_types::traits::{Packable, ToField};\n use dep::std::test::OracleMock;\n\n global STORAGE_SLOT: Field = 47;\n\n #[test]\n unconstrained fn create_and_recover() {\n let value = MockStruct { a: 5, b: 3 };\n let value_with_hash = WithHash::new(value);\n let recovered = WithHash::unpack(value_with_hash.pack());\n\n assert_eq(recovered.value, value);\n assert_eq(recovered.packed, value.pack());\n assert_eq(recovered.hash, poseidon2_hash(value.pack()));\n }\n\n #[test]\n unconstrained fn read_uninitialized_value() {\n let env = TestEnvironment::new();\n\n env.private_context(|context| {\n let result = WithHash::::historical_public_storage_read(\n context.historical_header,\n context.this_address(),\n STORAGE_SLOT,\n );\n\n assert_eq(result, std::mem::zeroed());\n });\n }\n\n #[test]\n unconstrained fn read_initialized_value() {\n let env = TestEnvironment::new();\n\n let value = MockStruct { a: 5, b: 3 };\n let value_with_hash = WithHash::new(value);\n\n env.public_context(|context| { context.storage_write(STORAGE_SLOT, value_with_hash); });\n\n env.private_context(|context| {\n let result = WithHash::::historical_public_storage_read(\n context.historical_header,\n context.this_address(),\n STORAGE_SLOT,\n );\n assert_eq(result, value);\n });\n }\n\n #[test(should_fail_with = \"Non-zero hint for zero hash\")]\n unconstrained fn bad_hint_uninitialized_value() {\n let env = TestEnvironment::new();\n\n env.private_context(|context| {\n let block_header = context.historical_header;\n let address = context.this_address();\n\n // Mock the oracle to return a non-zero hint/packed value\n let value_packed = MockStruct { a: 1, b: 1 }.pack();\n let _ = OracleMock::mock(\"utilityStorageRead\")\n .with_params((\n address.to_field(), STORAGE_SLOT, block_header.global_variables.block_number,\n value_packed.len(),\n ))\n .returns(value_packed)\n .times(1);\n\n // This should fail because the hint value is non-zero and the hash is zero (default value of storage)\n let _ = WithHash::::historical_public_storage_read(\n block_header,\n address,\n STORAGE_SLOT,\n );\n });\n }\n\n #[test(should_fail_with = \"Hint values do not match hash\")]\n unconstrained fn bad_hint_initialized_value() {\n let env = TestEnvironment::new();\n\n env.public_context(|context| {\n // Write the value and hash separately so that the hash is wrong\n let value = MockStruct { a: 5, b: 3 };\n context.storage_write(STORAGE_SLOT, value);\n\n let incorrect_hash = 13;\n let hash_storage_slot = STORAGE_SLOT + (value.pack().len() as Field);\n context.storage_write(hash_storage_slot, [incorrect_hash]);\n });\n\n env.private_context(|context| {\n let _ = WithHash::::historical_public_storage_read(\n context.historical_header,\n context.this_address(),\n STORAGE_SLOT,\n );\n });\n }\n}\n" - }, - "226": { - "path": "/home/josh/nargo/github.com/noir-lang/poseidon/v0.1.1/src/poseidon2.nr", - "source": "use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct 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 #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n 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) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\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 }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> 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\npub struct 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 { _state: &[] }\n }\n}\n" - }, - "245": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr", - "source": "use crate::traits::{Deserialize, Empty, FromField, Serialize, ToField};\nuse std::meta::derive;\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct FunctionSelector {\n // 1st 4-bytes (big-endian leftmost) of abi-encoding of an event.\n pub inner: u32,\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 = crate::hash::poseidon2_hash_bytes(bytes);\n\n // `hash` is automatically truncated to fit within 32 bits.\n FunctionSelector::from_field(hash)\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n\n#[test]\nfn test_is_valid_selector() {\n let selector = FunctionSelector::from_signature(\"IS_VALID()\");\n assert_eq(selector.to_field(), 0x73cdda47);\n}\n\n#[test]\nfn test_long_selector() {\n let selector =\n FunctionSelector::from_signature(\"foo_and_bar_and_baz_and_foo_bar_baz_and_bar_foo\");\n assert_eq(selector.to_field(), 0x7590a997);\n}\n" - }, - "291": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr", - "source": "use crate::{\n address::{\n partial_address::PartialAddress, salted_initialization_hash::SaltedInitializationHash,\n },\n constants::{\n AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1, MAX_FIELD_VALUE,\n MAX_PROTOCOL_CONTRACTS,\n },\n contract_class_id::ContractClassId,\n hash::poseidon2_hash_with_separator,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, ToPoint, TpkM},\n traits::{Deserialize, Empty, FromField, Packable, Serialize, ToField},\n utils::field::{pow, sqrt},\n};\n\n// We do below because `use crate::point::Point;` does not work\nuse dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\n\nuse crate::public_keys::AddressPoint;\nuse std::{\n embedded_curve_ops::{EmbeddedCurveScalar, fixed_base_scalar_mul as derive_public_key},\n ops::Add,\n};\nuse std::meta::derive;\n\n// Aztec address\n#[derive(Deserialize, Eq, Packable, Serialize)]\npub struct AztecAddress {\n pub inner: Field,\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self { inner: 0 }\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 AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn to_address_point(self) -> AddressPoint {\n // We compute the address point by taking our address, setting it to x, and then solving for y in the\n // equation which defines our bn curve:\n // y^2 = x^3 - 17; x = address\n let x = self.inner;\n let y_squared = pow(x, 3) - 17;\n\n // TODO (#8970): Handle cases where we cannot recover a point from an address\n let mut y = sqrt(y_squared);\n\n // If we get a negative y coordinate (any y where y > MAX_FIELD_VALUE / 2), we pin it to the\n // positive one (any value where y <= MAX_FIELD_VALUE / 2) by subtracting it from the Field modulus\n // note: The field modulus is MAX_FIELD_VALUE + 1\n if (!(y.lt(MAX_FIELD_VALUE / 2) | y.eq(MAX_FIELD_VALUE / 2))) {\n y = (MAX_FIELD_VALUE + 1) - y;\n }\n\n AddressPoint { inner: Point { x: self.inner, y, is_infinite: false } }\n }\n\n pub fn compute(public_keys: PublicKeys, partial_address: PartialAddress) -> AztecAddress {\n let public_keys_hash = public_keys.hash();\n\n let pre_address = poseidon2_hash_with_separator(\n [public_keys_hash.to_field(), partial_address.to_field()],\n GENERATOR_INDEX__CONTRACT_ADDRESS_V1,\n );\n\n let address_point = derive_public_key(EmbeddedCurveScalar::from_field(pre_address)).add(\n public_keys.ivpk_m.to_point(),\n );\n\n // Note that our address is only the x-coordinate of the full address_point. This is okay because when people want to encrypt something and send it to us\n // they can recover our full point using the x-coordinate (our address itself). To do this, they recompute the y-coordinate according to the equation y^2 = x^3 - 17.\n // When they do this, they may get a positive y-coordinate (a value that is less than or equal to MAX_FIELD_VALUE / 2) or\n // a negative y-coordinate (a value that is more than MAX_FIELD_VALUE), and we cannot dictate which one they get and hence the recovered point may sometimes be different than the one\n // our secret can decrypt. Regardless though, they should and will always encrypt using point with the positive y-coordinate by convention.\n // This ensures that everyone encrypts to the same point given an arbitrary x-coordinate (address). This is allowed because even though our original point may not have a positive y-coordinate,\n // with our original secret, we will be able to derive the secret to the point with the flipped (and now positive) y-coordinate that everyone encrypts to.\n AztecAddress::from_field(address_point.x)\n }\n\n pub fn compute_from_class_id(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash,\n public_keys: PublicKeys,\n ) -> Self {\n let partial_address = PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n salted_initialization_hash,\n );\n\n AztecAddress::compute(public_keys, partial_address)\n }\n\n pub fn is_protocol_contract(self) -> bool {\n self.inner.lt(MAX_PROTOCOL_CONTRACTS as 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\n#[test]\nfn compute_address_from_partial_and_pub_keys() {\n let public_keys = PublicKeys {\n npk_m: NpkM {\n inner: Point {\n x: 0x22f7fcddfa3ce3e8f0cc8e82d7b94cdd740afa3e77f8e4a63ea78a239432dcab,\n y: 0x0471657de2b6216ade6c506d28fbc22ba8b8ed95c871ad9f3e3984e90d9723a7,\n is_infinite: false,\n },\n },\n ivpk_m: IvpkM {\n inner: Point {\n x: 0x111223493147f6785514b1c195bb37a2589f22a6596d30bb2bb145fdc9ca8f1e,\n y: 0x273bbffd678edce8fe30e0deafc4f66d58357c06fd4a820285294b9746c3be95,\n is_infinite: false,\n },\n },\n ovpk_m: OvpkM {\n inner: Point {\n x: 0x09115c96e962322ffed6522f57194627136b8d03ac7469109707f5e44190c484,\n y: 0x0c49773308a13d740a7f0d4f0e6163b02c5a408b6f965856b6a491002d073d5b,\n is_infinite: false,\n },\n },\n tpk_m: TpkM {\n inner: Point {\n x: 0x00d3d81beb009873eb7116327cf47c612d5758ef083d4fda78e9b63980b2a762,\n y: 0x2f567d22d2b02fe1f4ad42db9d58a36afd1983e7e2909d1cab61cafedad6193a,\n is_infinite: false,\n },\n },\n };\n\n let partial_address = PartialAddress::from_field(\n 0x0a7c585381b10f4666044266a02405bf6e01fa564c8517d4ad5823493abd31de,\n );\n\n let address = AztecAddress::compute(public_keys, partial_address);\n\n // The following value was generated by `derivation.test.ts`.\n // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data.\n let expected_computed_address_from_partial_and_pubkeys =\n 0x24e4646f58b9fbe7d38e317db8d5636c423fbbdfbe119fc190fe9c64747e0c62;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkeys);\n}\n\n#[test]\nfn compute_preaddress_from_partial_and_pub_keys() {\n let pre_address = poseidon2_hash_with_separator([1, 2], GENERATOR_INDEX__CONTRACT_ADDRESS_V1);\n let expected_computed_preaddress_from_partial_and_pubkey =\n 0x23ce9be3fa3c846b0f9245cc796902e731d04f086e8a42473bb29e405fc98075;\n assert(pre_address == expected_computed_preaddress_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 // We use the AZTEC_ADDRESS_LENGTH constant to ensure that there is a match between the derived trait\n // implementation and the constant.\n let serialized: [Field; AZTEC_ADDRESS_LENGTH] = address.serialize();\n let deserialized = AztecAddress::deserialize(serialized);\n assert_eq(address, deserialized);\n}\n" - }, - "3": { - "path": "std/array/mod.nr", - "source": "use crate::cmp::{Eq, Ord};\nuse crate::convert::From;\nuse crate::runtime::is_unconstrained;\n\nmod check_shuffle;\nmod quicksort;\n\nimpl [T; N] {\n /// Returns the length of this array.\n ///\n /// ```noir\n /// fn len(self) -> Field\n /// ```\n ///\n /// example\n ///\n /// ```noir\n /// fn main() {\n /// let array = [42, 42];\n /// assert(array.len() == 2);\n /// }\n /// ```\n #[builtin(array_len)]\n pub fn len(self) -> u32 {}\n\n /// Returns this array as a slice.\n ///\n /// ```noir\n /// let array = [1, 2];\n /// let slice = array.as_slice();\n /// assert_eq(slice, &[1, 2]);\n /// ```\n #[builtin(as_slice)]\n pub fn as_slice(self) -> [T] {}\n\n /// Applies a function to each element of this array, returning a new array containing the mapped elements.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let b = a.map(|a| a * 2);\n /// assert_eq(b, [2, 4, 6]);\n /// ```\n pub fn map(self, f: fn[Env](T) -> U) -> [U; N] {\n let uninitialized = crate::mem::zeroed();\n let mut ret = [uninitialized; N];\n\n for i in 0..self.len() {\n ret[i] = f(self[i]);\n }\n\n ret\n }\n\n /// Applies a function to each element of this array along with its index,\n /// returning a new array containing the mapped elements.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let b = a.mapi(|i, a| i + a * 2);\n /// assert_eq(b, [2, 5, 8]);\n /// ```\n pub fn mapi(self, f: fn[Env](u32, T) -> U) -> [U; N] {\n let uninitialized = crate::mem::zeroed();\n let mut ret = [uninitialized; N];\n\n for i in 0..self.len() {\n ret[i] = f(i, self[i]);\n }\n\n ret\n }\n\n /// Applies a function to each element of this array.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let mut b = [0; 3];\n /// let mut i = 0;\n /// a.for_each(|x| {\n /// b[i] = x;\n /// i += 1;\n /// });\n /// assert_eq(a, b);\n /// ```\n pub fn for_each(self, f: fn[Env](T) -> ()) {\n for i in 0..self.len() {\n f(self[i]);\n }\n }\n\n /// Applies a function to each element of this array along with its index.\n ///\n /// Example:\n ///\n /// ```rust\n /// let a = [1, 2, 3];\n /// let mut b = [0; 3];\n /// a.for_eachi(|i, x| {\n /// b[i] = x;\n /// });\n /// assert_eq(a, b);\n /// ```\n pub fn for_eachi(self, f: fn[Env](u32, T) -> ()) {\n for i in 0..self.len() {\n f(i, self[i]);\n }\n }\n\n /// Applies a function to each element of the array, returning the final accumulated value. The first\n /// parameter is the initial value.\n ///\n /// This is a left fold, so the given function will be applied to the accumulator and first element of\n /// the array, then the second, and so on. For a given call the expected result would be equivalent to:\n ///\n /// ```rust\n /// let a1 = [1];\n /// let a2 = [1, 2];\n /// let a3 = [1, 2, 3];\n ///\n /// let f = |a, b| a - b;\n /// a1.fold(10, f); //=> f(10, 1)\n /// a2.fold(10, f); //=> f(f(10, 1), 2)\n /// a3.fold(10, f); //=> f(f(f(10, 1), 2), 3)\n ///\n /// assert_eq(a3.fold(10, f), 10 - 1 - 2 - 3);\n /// ```\n pub fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U {\n for elem in self {\n accumulator = f(accumulator, elem);\n }\n accumulator\n }\n\n /// Same as fold, but uses the first element as the starting element.\n ///\n /// Requires the input array to be non-empty.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr = [1, 2, 3, 4];\n /// let reduced = arr.reduce(|a, b| a + b);\n /// assert(reduced == 10);\n /// }\n /// ```\n pub fn reduce(self, f: fn[Env](T, T) -> T) -> T {\n let mut accumulator = self[0];\n for i in 1..self.len() {\n accumulator = f(accumulator, self[i]);\n }\n accumulator\n }\n\n /// Returns true if all the elements in this array satisfy the given predicate.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr = [2, 2, 2, 2, 2];\n /// let all = arr.all(|a| a == 2);\n /// assert(all);\n /// }\n /// ```\n pub fn all(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = true;\n for elem in self {\n ret &= predicate(elem);\n }\n ret\n }\n\n /// Returns true if any of the elements in this array satisfy the given predicate.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr = [2, 2, 2, 2, 5];\n /// let any = arr.any(|a| a == 5);\n /// assert(any);\n /// }\n /// ```\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n for elem in self {\n ret |= predicate(elem);\n }\n ret\n }\n\n /// Concatenates this array with another array.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn main() {\n /// let arr1 = [1, 2, 3, 4];\n /// let arr2 = [6, 7, 8, 9, 10, 11];\n /// let concatenated_arr = arr1.concat(arr2);\n /// assert(concatenated_arr == [1, 2, 3, 4, 6, 7, 8, 9, 10, 11]);\n /// }\n /// ```\n pub fn concat(self, array2: [T; M]) -> [T; N + M] {\n let mut result = [crate::mem::zeroed(); N + M];\n for i in 0..N {\n result[i] = self[i];\n }\n for i in 0..M {\n result[i + N] = array2[i];\n }\n result\n }\n}\n\nimpl [T; N]\nwhere\n T: Ord + Eq,\n{\n /// Returns a new sorted array. The original array remains untouched. Notice that this function will\n /// only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting\n /// logic it uses internally is optimized specifically for these values. If you need a sort function to\n /// sort any type, you should use the `sort_via` function.\n ///\n /// Example:\n ///\n /// ```rust\n /// fn main() {\n /// let arr = [42, 32];\n /// let sorted = arr.sort();\n /// assert(sorted == [32, 42]);\n /// }\n /// ```\n pub fn sort(self) -> Self {\n self.sort_via(|a, b| a <= b)\n }\n}\n\nimpl [T; N]\nwhere\n T: Eq,\n{\n /// Returns a new sorted array by sorting it with a custom comparison function.\n /// The original array remains untouched.\n /// The ordering function must return true if the first argument should be sorted to be before the second argument or is equal to the second argument.\n ///\n /// Using this method with an operator like `<` that does not return `true` for equal values will result in an assertion failure for arrays with equal elements.\n ///\n /// Example:\n ///\n /// ```rust\n /// fn main() {\n /// let arr = [42, 32]\n /// let sorted_ascending = arr.sort_via(|a, b| a <= b);\n /// assert(sorted_ascending == [32, 42]); // verifies\n ///\n /// let sorted_descending = arr.sort_via(|a, b| a >= b);\n /// assert(sorted_descending == [32, 42]); // does not verify\n /// }\n /// ```\n pub fn sort_via(self, ordering: fn[Env](T, T) -> bool) -> Self {\n // Safety: `sorted` array is checked to be:\n // a. a permutation of `input`'s elements\n // b. satisfying the predicate `ordering`\n let sorted = unsafe { quicksort::quicksort(self, ordering) };\n\n if !is_unconstrained() {\n for i in 0..N - 1 {\n assert(\n ordering(sorted[i], sorted[i + 1]),\n \"Array has not been sorted correctly according to `ordering`.\",\n );\n }\n check_shuffle::check_shuffle(self, sorted);\n }\n sorted\n }\n}\n\nimpl [u8; N] {\n /// Converts a byte array of type `[u8; N]` to a string. Note that this performs no UTF-8 validation -\n /// the given array is interpreted as-is as a string.\n ///\n /// Example:\n ///\n /// ```rust\n /// fn main() {\n /// let hi = [104, 105].as_str_unchecked();\n /// assert_eq(hi, \"hi\");\n /// }\n /// ```\n #[builtin(array_as_str_unchecked)]\n pub fn as_str_unchecked(self) -> str {}\n}\n\nimpl From> for [u8; N] {\n /// Returns an array of the string bytes.\n fn from(s: str) -> Self {\n s.as_bytes()\n }\n}\n\nmod test {\n #[test]\n fn map_empty() {\n assert_eq([].map(|x| x + 1), []);\n }\n\n global arr_with_100_values: [u32; 100] = [\n 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2, 54,\n 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41, 19, 98,\n 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21, 43, 86, 35,\n 21, 62, 82, 0, 108, 120, 72, 72, 62, 80, 12, 71, 70, 86, 116, 73, 38, 15, 127, 81, 30, 8,\n 125, 28, 26, 69, 114, 63, 27, 28, 61, 42, 13, 32,\n ];\n global expected_with_100_values: [u32; 100] = [\n 0, 0, 2, 3, 5, 6, 8, 12, 13, 13, 15, 19, 19, 19, 21, 21, 26, 26, 27, 28, 28, 28, 29, 30, 32,\n 32, 35, 37, 38, 41, 42, 42, 42, 43, 44, 44, 45, 47, 48, 48, 50, 50, 53, 54, 54, 58, 61, 62,\n 62, 63, 64, 66, 66, 68, 69, 70, 70, 71, 71, 72, 72, 73, 74, 80, 80, 81, 81, 82, 84, 84, 86,\n 86, 87, 89, 89, 89, 93, 95, 96, 98, 100, 104, 105, 106, 107, 108, 109, 114, 114, 116, 118,\n 119, 120, 121, 123, 123, 123, 125, 126, 127,\n ];\n fn sort_u32(a: u32, b: u32) -> bool {\n a <= b\n }\n\n #[test]\n fn test_sort() {\n let mut arr: [u32; 7] = [3, 6, 8, 10, 1, 2, 1];\n\n let sorted = arr.sort();\n\n let expected: [u32; 7] = [1, 1, 2, 3, 6, 8, 10];\n assert(sorted == expected);\n }\n\n #[test]\n fn test_sort_100_values() {\n let mut arr: [u32; 100] = [\n 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2,\n 54, 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41,\n 19, 98, 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21,\n 43, 86, 35, 21, 62, 82, 0, 108, 120, 72, 72, 62, 80, 12, 71, 70, 86, 116, 73, 38, 15,\n 127, 81, 30, 8, 125, 28, 26, 69, 114, 63, 27, 28, 61, 42, 13, 32,\n ];\n\n let sorted = arr.sort();\n\n let expected: [u32; 100] = [\n 0, 0, 2, 3, 5, 6, 8, 12, 13, 13, 15, 19, 19, 19, 21, 21, 26, 26, 27, 28, 28, 28, 29, 30,\n 32, 32, 35, 37, 38, 41, 42, 42, 42, 43, 44, 44, 45, 47, 48, 48, 50, 50, 53, 54, 54, 58,\n 61, 62, 62, 63, 64, 66, 66, 68, 69, 70, 70, 71, 71, 72, 72, 73, 74, 80, 80, 81, 81, 82,\n 84, 84, 86, 86, 87, 89, 89, 89, 93, 95, 96, 98, 100, 104, 105, 106, 107, 108, 109, 114,\n 114, 116, 118, 119, 120, 121, 123, 123, 123, 125, 126, 127,\n ];\n assert(sorted == expected);\n }\n\n #[test]\n fn test_sort_100_values_comptime() {\n let sorted = arr_with_100_values.sort();\n assert(sorted == expected_with_100_values);\n }\n\n #[test]\n fn test_sort_via() {\n let mut arr: [u32; 7] = [3, 6, 8, 10, 1, 2, 1];\n\n let sorted = arr.sort_via(sort_u32);\n\n let expected: [u32; 7] = [1, 1, 2, 3, 6, 8, 10];\n assert(sorted == expected);\n }\n\n #[test]\n fn test_sort_via_100_values() {\n let mut arr: [u32; 100] = [\n 42, 123, 87, 93, 48, 80, 50, 5, 104, 84, 70, 47, 119, 66, 71, 121, 3, 29, 42, 118, 2,\n 54, 89, 44, 81, 0, 26, 106, 68, 96, 84, 48, 95, 54, 45, 32, 89, 100, 109, 19, 37, 41,\n 19, 98, 53, 114, 107, 66, 6, 74, 13, 19, 105, 64, 123, 28, 44, 50, 89, 58, 123, 126, 21,\n 43, 86, 35, 21, 62, 82, 0, 108, 120, 72, 72, 62, 80, 12, 71, 70, 86, 116, 73, 38, 15,\n 127, 81, 30, 8, 125, 28, 26, 69, 114, 63, 27, 28, 61, 42, 13, 32,\n ];\n\n let sorted = arr.sort_via(sort_u32);\n\n let expected: [u32; 100] = [\n 0, 0, 2, 3, 5, 6, 8, 12, 13, 13, 15, 19, 19, 19, 21, 21, 26, 26, 27, 28, 28, 28, 29, 30,\n 32, 32, 35, 37, 38, 41, 42, 42, 42, 43, 44, 44, 45, 47, 48, 48, 50, 50, 53, 54, 54, 58,\n 61, 62, 62, 63, 64, 66, 66, 68, 69, 70, 70, 71, 71, 72, 72, 73, 74, 80, 80, 81, 81, 82,\n 84, 84, 86, 86, 87, 89, 89, 89, 93, 95, 96, 98, 100, 104, 105, 106, 107, 108, 109, 114,\n 114, 116, 118, 119, 120, 121, 123, 123, 123, 125, 126, 127,\n ];\n assert(sorted == expected);\n }\n\n #[test]\n fn mapi_empty() {\n assert_eq([].mapi(|i, x| i * x + 1), []);\n }\n\n #[test]\n fn for_each_empty() {\n let empty_array: [Field; 0] = [];\n empty_array.for_each(|_x| assert(false));\n }\n\n #[test]\n fn for_eachi_empty() {\n let empty_array: [Field; 0] = [];\n empty_array.for_eachi(|_i, _x| assert(false));\n }\n\n #[test]\n fn map_example() {\n let a = [1, 2, 3];\n let b = a.map(|a| a * 2);\n assert_eq(b, [2, 4, 6]);\n }\n\n #[test]\n fn mapi_example() {\n let a = [1, 2, 3];\n let b = a.mapi(|i, a| i + a * 2);\n assert_eq(b, [2, 5, 8]);\n }\n\n #[test]\n fn for_each_example() {\n let a = [1, 2, 3];\n let mut b = [0, 0, 0];\n let b_ref = &mut b;\n let mut i = 0;\n let i_ref = &mut i;\n a.for_each(|x| {\n b_ref[*i_ref] = x * 2;\n *i_ref += 1;\n });\n assert_eq(b, [2, 4, 6]);\n assert_eq(i, 3);\n }\n\n #[test]\n fn for_eachi_example() {\n let a = [1, 2, 3];\n let mut b = [0, 0, 0];\n let b_ref = &mut b;\n a.for_eachi(|i, a| { b_ref[i] = i + a * 2; });\n assert_eq(b, [2, 5, 8]);\n }\n\n #[test]\n fn concat() {\n let arr1 = [1, 2, 3, 4];\n let arr2 = [6, 7, 8, 9, 10, 11];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, [1, 2, 3, 4, 6, 7, 8, 9, 10, 11]);\n }\n\n #[test]\n fn concat_zero_length_with_something() {\n let arr1 = [];\n let arr2 = [1];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, [1]);\n }\n\n #[test]\n fn concat_something_with_zero_length() {\n let arr1 = [1];\n let arr2 = [];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, [1]);\n }\n\n #[test]\n fn concat_zero_lengths() {\n let arr1: [Field; 0] = [];\n let arr2: [Field; 0] = [];\n let concatenated_arr = arr1.concat(arr2);\n assert_eq(concatenated_arr, []);\n }\n}\n" - }, - "307": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr", - "source": "/// Utility function to console.log data in the acir simulator.\n/// Example:\n/// debug_log(\"blah blah this is a debug string\");\npub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n\n/// Utility function to console.log data in the acir simulator. This variant receives a format string in which the\n/// `${k}` tokens will be replaced with the k-eth value in the `args` array.\n/// Examples:\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]);\npub fn debug_log_format(msg: str, args: [Field; N]) {\n // Safety: This oracle call returns nothing: we only call it for its side effects. It is therefore always safe\n // to call.\n unsafe { debug_log_oracle_wrapper(msg, args) };\n}\n\npub unconstrained fn debug_log_oracle_wrapper(\n msg: str,\n args: [Field; N],\n) {\n debug_log_oracle(msg, args.as_slice());\n}\n\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#[oracle(utilityDebugLog)]\nunconstrained fn debug_log_oracle(_msg: str, args: [Field]) {}\n" - }, - "316": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/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,\n note_hash::ScopedNoteHash,\n nullifier::ScopedNullifier,\n private_log::{PrivateLog, PrivateLogData},\n side_effect::{OrderedValue, scoped::Scoped},\n },\n address::{AztecAddress, EthAddress},\n constants::{\n CONTRACT_CLASS_LOG_SIZE_IN_FIELDS, FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__NOTE_HASH_NONCE,\n GENERATOR_INDEX__OUTER_NULLIFIER, GENERATOR_INDEX__SILOED_NOTE_HASH,\n GENERATOR_INDEX__UNIQUE_NOTE_HASH, TWO_POW_64,\n },\n merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::L2ToL1Message,\n poseidon2::Poseidon2Sponge,\n traits::{FromField, Hash, ToField},\n utils::field::{field_from_bytes, field_from_bytes_32_trunc},\n};\nuse std::embedded_curve_ops::EmbeddedCurveScalar;\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256::digest(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(\n function_leaf,\n function_leaf_index,\n function_leaf_sibling_path,\n )\n}\n\npub fn compute_note_hash_nonce(first_nullifier_in_tx: Field, note_index_in_tx: u32) -> Field {\n // Hashing the first nullifier with note index in tx is guaranteed to be unique (because all nullifiers are also\n // unique).\n poseidon2_hash_with_separator(\n [first_nullifier_in_tx, note_index_in_tx as Field],\n GENERATOR_INDEX__NOTE_HASH_NONCE,\n )\n}\n\npub fn compute_unique_note_hash(note_nonce: Field, siloed_note_hash: Field) -> Field {\n let inputs = [note_nonce, siloed_note_hash];\n poseidon2_hash_with_separator(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_nonce_and_unique_note_hash(\n siloed_note_hash: Field,\n first_nullifier: Field,\n note_index_in_tx: u32,\n) -> Field {\n let note_nonce = compute_note_hash_nonce(first_nullifier, note_index_in_tx);\n compute_unique_note_hash(note_nonce, siloed_note_hash)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, note_hash: Field) -> Field {\n poseidon2_hash_with_separator(\n [app.to_field(), note_hash],\n GENERATOR_INDEX__SILOED_NOTE_HASH,\n )\n}\n\n/// Computes unique note hashes from siloed note hashes\npub fn compute_unique_siloed_note_hash(\n siloed_note_hash: Field,\n first_nullifier: Field,\n note_index_in_tx: u32,\n) -> Field {\n if siloed_note_hash == 0 {\n 0\n } else {\n compute_nonce_and_unique_note_hash(siloed_note_hash, first_nullifier, note_index_in_tx)\n }\n}\n\n/// Siloing in the context of Aztec refers to the process of hashing a note hash with a contract address (this way\n/// the note hash is scoped to a specific contract). This is used to prevent intermingling of notes between contracts.\npub fn silo_note_hash(note_hash: ScopedNoteHash) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_note_hash(note_hash.contract_address, note_hash.value())\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n poseidon2_hash_with_separator(\n [app.to_field(), nullifier],\n GENERATOR_INDEX__OUTER_NULLIFIER,\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n // Q: shouldn't we be checking whether the _whole_ nullifier is empty?\n // A: We don't have to. The init and inner circuits add contract address to non-empty nullifiers.\n // So we know we should silo it if the contract address is not empty.\n if nullifier.contract_address.is_zero() {\n // Q: I don't understand this comment. We could still compute a siloed nullifier from a zero contract address.\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_private_log_field(contract_address: AztecAddress, field: Field) -> Field {\n poseidon2_hash([contract_address.to_field(), field])\n}\n\npub fn silo_private_log(private_log: Scoped) -> PrivateLog {\n if private_log.contract_address.is_zero() {\n private_log.inner.log\n } else {\n let mut fields = private_log.inner.log.fields;\n fields[0] = compute_siloed_private_log_field(private_log.contract_address, fields[0]);\n PrivateLog::new(fields, private_log.inner.log.length)\n }\n}\n\npub fn compute_contract_class_log_hash(log: [Field; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS]) -> Field {\n poseidon2_hash(log)\n}\n\npub fn compute_app_secret_key(\n master_secret_key: EmbeddedCurveScalar,\n app_address: AztecAddress,\n app_secret_generator: Field,\n) -> Field {\n poseidon2_hash_with_separator(\n [master_secret_key.hi, master_secret_key.lo, app_address.to_field()],\n app_secret_generator,\n )\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n poseidon2_hash([left, right])\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 contract_address_bytes: [u8; 32] = contract_address.to_field().to_be_bytes();\n let recipient_bytes: [u8; 20] = recipient.to_be_bytes();\n let content_bytes: [u8; 32] = content.to_be_bytes();\n let rollup_version_id_bytes: [u8; 32] = rollup_version_id.to_be_bytes();\n let chain_id_bytes: [u8; 32] = chain_id.to_be_bytes();\n\n let mut bytes: [u8; 148] = std::mem::zeroed();\n for i in 0..32 {\n bytes[i] = contract_address_bytes[i];\n bytes[i + 32] = rollup_version_id_bytes[i];\n // 64 - 84 are for recipient.\n bytes[i + 84] = chain_id_bytes[i];\n bytes[i + 116] = content_bytes[i];\n }\n\n for i in 0..20 {\n bytes[64 + i] = recipient_bytes[i];\n }\n\n sha256_to_field(bytes)\n}\n\npub fn silo_l2_to_l1_message(\n msg: Scoped,\n rollup_version_id: Field,\n chain_id: Field,\n) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.inner.recipient,\n msg.inner.content,\n rollup_version_id,\n chain_id,\n )\n }\n}\n\n/// Computes sha256 hash of 2 input fields.\n///\n/// @returns A truncated field (i.e., the first byte is always 0).\npub fn accumulate_sha256(v0: Field, v1: Field) -> Field {\n // Concatenate two fields into 32 x 2 = 64 bytes\n let v0_as_bytes: [u8; 32] = v0.to_be_bytes();\n let v1_as_bytes: [u8; 32] = v1.to_be_bytes();\n let hash_input_flattened = v0_as_bytes.concat(v1_as_bytes);\n\n sha256_to_field(hash_input_flattened)\n}\n\n#[inline_always]\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n poseidon::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[no_predicates]\npub fn poseidon2_hash_with_separator(inputs: [Field; N], separator: T) -> Field\nwhere\n T: ToField,\n{\n let inputs_with_separator = [separator.to_field()].concat(inputs);\n poseidon2_hash(inputs_with_separator)\n}\n\n// Performs a fixed length hash with a subarray of the given input.\n// Useful for SpongeBlob in which we aborb M things and want to check it vs a hash of M elts of an N-len array.\n// Using stdlib poseidon, this will always absorb an extra 1 as a 'variable' hash, and not match spongeblob.squeeze()\n// or any ts implementation. Also checks that any remaining elts not hashed are empty.\n#[no_predicates]\npub fn poseidon2_hash_subarray(input: [Field; N], in_len: u32) -> Field {\n let mut sponge = poseidon2_absorb_chunks(input, in_len, false);\n sponge.squeeze()\n}\n\n// NB the below is the same as poseidon::poseidon2::Poseidon2::hash(), but replacing a range check with a bit check,\n// and absorbing in chunks of 3 below.\n#[no_predicates]\npub fn poseidon2_cheaper_variable_hash(input: [Field; N], in_len: u32) -> Field {\n let mut sponge = poseidon2_absorb_chunks(input, in_len, true);\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 in_len != N {\n sponge.absorb(1);\n }\n sponge.squeeze()\n}\n\n// The below fn reduces gates of a conditional poseidon2 hash by approx 3x (thank you ~* Giant Brain Dev @IlyasRidhuan *~ for the idea)\n// Why? Because when we call stdlib poseidon, we call absorb for each item. When absorbing is conditional, it seems the compiler does not know\n// what cache_size will be when calling absorb, so it assigns the permutation gates for /each i/ rather than /every 3rd i/, which is actually required.\n// The below code forces the compiler to:\n// - absorb normally up to 2 times to set cache_size to 1\n// - absorb in chunks of 3 to ensure perm. only happens every 3rd absorb\n// - absorb normally up to 2 times to add any remaining values to the hash\n// In fixed len hashes, the compiler is able to tell that it will only need to perform the permutation every 3 absorbs.\n// NB: it also replaces unnecessary range checks (i < thing) with a bit check (&= i != thing), which alone reduces the gates of a var. hash by half.\n\n#[no_predicates]\nfn poseidon2_absorb_chunks(\n input: [Field; N],\n in_len: u32,\n variable: bool,\n) -> Poseidon2Sponge {\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::new(iv);\n // Even though shift is always 1 here, if we input in_len = 0 we get an underflow\n // since we cannot isolate computation branches. The below is just to avoid that.\n let shift = if in_len == 0 { 0 } else { 1 };\n if in_len != 0 {\n // cache_size = 0, init absorb\n sponge.cache[0] = input[0];\n sponge.cache_size = 1;\n // shift = num elts already added to make cache_size 1 = 1 for a fresh sponge\n // M = max_chunks = (N - 1 - (N - 1) % 3) / 3: (must be written as a fn of N to compile)\n // max_remainder = (N - 1) % 3;\n // max_chunks = (N - 1 - max_remainder) / 3;\n sponge = poseidon2_absorb_chunks_loop::(\n sponge,\n input,\n in_len,\n variable,\n shift,\n );\n }\n sponge\n}\n\n// NB: If it's not required to check that the non-absorbed elts of 'input' are 0s, set skip_0_check=true\n#[no_predicates]\npub fn poseidon2_absorb_chunks_existing_sponge(\n in_sponge: Poseidon2Sponge,\n input: [Field; N],\n in_len: u32,\n skip_0_check: bool,\n) -> Poseidon2Sponge {\n let mut sponge = in_sponge;\n // 'shift' is to account for already added inputs\n let mut shift = 0;\n // 'stop' is to avoid an underflow when inputting in_len = 0\n let mut stop = false;\n for i in 0..3 {\n if shift == in_len {\n stop = true;\n }\n if (sponge.cache_size != 1) & (!stop) {\n sponge.absorb(input[i]);\n shift += 1;\n }\n }\n sponge = if stop {\n sponge\n } else {\n // max_chunks = (N - (N % 3)) / 3;\n poseidon2_absorb_chunks_loop::(\n sponge,\n input,\n in_len,\n skip_0_check,\n shift,\n )\n };\n sponge\n}\n\n// The below is the loop to absorb elts into a poseidon sponge in chunks of 3\n// shift - the num of elts already absorbed to ensure the sponge's cache_size = 1\n// M - the max number of chunks required to absorb N things (must be comptime to compile)\n// NB: The 0 checks ('Found non-zero field...') are messy, but having a separate loop over N to check\n// for 0s costs 3N gates. Current approach is approx 2N gates.\n#[no_predicates]\nfn poseidon2_absorb_chunks_loop(\n in_sponge: Poseidon2Sponge,\n input: [Field; N],\n in_len: u32,\n variable: bool,\n shift: u32,\n) -> Poseidon2Sponge {\n assert(in_len <= N, \"Given in_len to absorb is larger than the input array len\");\n // When we have an existing sponge, we may have a shift of 0, and the final 'k+2' below = N\n // The below avoids an overflow\n let skip_last = 3 * M == N;\n // Writing in_sponge: &mut does not compile\n let mut sponge = in_sponge;\n let mut should_add = true;\n // The num of things left over after absorbing in 3s\n let remainder = (in_len - shift) % 3;\n // The num of chunks of 3 to absorb (maximum M)\n let chunks = (in_len - shift - remainder) / 3;\n for i in 0..M {\n // Now we loop through cache size = 1 -> 3\n should_add &= i != chunks;\n // This is the index at the start of the chunk (for readability)\n let k = 3 * i + shift;\n if should_add {\n // cache_size = 1, 2 => just assign\n sponge.cache[1] = input[k];\n sponge.cache[2] = input[k + 1];\n // cache_size = 3 => duplex + perm\n for j in 0..3 {\n sponge.state[j] += sponge.cache[j];\n }\n sponge.state = std::hash::poseidon2_permutation(sponge.state, 4);\n sponge.cache[0] = input[k + 2];\n // cache_size is now 1 again, repeat loop\n } else if (!variable) & (i != chunks) {\n // if we are hashing a fixed len array which is a subarray, we check the remaining elts are 0\n // NB: we don't check at i == chunks, because that chunk contains elts to be absorbed or checked below\n let last_0 = if (i == M - 1) & (skip_last) {\n 0\n } else {\n input[k + 2]\n };\n let all_0 = (input[k] == 0) & (input[k + 1] == 0) & (last_0 == 0);\n assert(all_0, \"Found non-zero field after breakpoint\");\n }\n }\n // we have 'remainder' num of items left to absorb\n should_add = true;\n // below is to avoid overflows (i.e. if inlen is close to N)\n let mut should_check = !variable;\n for i in 0..3 {\n should_add &= i != remainder;\n should_check &= in_len - remainder + i != N;\n if should_add {\n // we want to absorb the final 'remainder' items\n sponge.absorb(input[in_len - remainder + i]);\n } else if should_check {\n assert_eq(input[in_len - remainder + i], 0, \"Found non-zero field after breakpoint\");\n }\n }\n sponge\n}\n\npub fn poseidon2_hash_with_separator_slice(inputs: [Field], separator: T) -> Field\nwhere\n T: ToField,\n{\n let in_len = inputs.len() + 1;\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::new(iv);\n sponge.absorb(separator.to_field());\n\n for i in 0..inputs.len() {\n sponge.absorb(inputs[i]);\n }\n\n sponge.squeeze()\n}\n\n// This function is unconstrained because it is intended to be used in unconstrained context only as\n// in constrained contexts it would be too inefficient.\npub unconstrained fn poseidon2_hash_with_separator_bounded_vec(\n inputs: BoundedVec,\n separator: T,\n) -> Field\nwhere\n T: ToField,\n{\n let in_len = inputs.len() + 1;\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::new(iv);\n sponge.absorb(separator.to_field());\n\n for i in 0..inputs.len() {\n sponge.absorb(inputs.get(i));\n }\n\n sponge.squeeze()\n}\n\n#[no_predicates]\npub fn poseidon2_hash_bytes(inputs: [u8; N]) -> Field {\n let mut fields = [0; (N + 30) / 31];\n let mut field_index = 0;\n let mut current_field = [0; 31];\n for i in 0..inputs.len() {\n let index = i % 31;\n current_field[index] = inputs[i];\n if index == 30 {\n fields[field_index] = field_from_bytes(current_field, false);\n current_field = [0; 31];\n field_index += 1;\n }\n }\n if field_index != fields.len() {\n fields[field_index] = field_from_bytes(current_field, false);\n }\n poseidon2_hash(fields)\n}\n\n#[test]\nfn poseidon_chunks_matches_fixed() {\n let in_len = 501;\n let mut input: [Field; 4096] = [0; 4096];\n let mut fixed_input = [3; 501];\n assert(in_len == fixed_input.len()); // sanity check\n for i in 0..in_len {\n input[i] = 3;\n }\n let sub_chunk_hash = poseidon2_hash_subarray(input, in_len);\n let fixed_len_hash = poseidon::poseidon2::Poseidon2::hash(fixed_input, fixed_input.len());\n assert(sub_chunk_hash == fixed_len_hash);\n}\n\n#[test]\nfn poseidon_chunks_matches_variable() {\n let in_len = 501;\n let mut input: [Field; 4096] = [0; 4096];\n for i in 0..in_len {\n input[i] = 3;\n }\n let variable_chunk_hash = poseidon2_cheaper_variable_hash(input, in_len);\n let variable_len_hash = poseidon::poseidon2::Poseidon2::hash(input, in_len);\n assert(variable_chunk_hash == variable_len_hash);\n}\n\n#[test]\nfn existing_sponge_poseidon_chunks_matches_fixed() {\n let in_len = 501;\n let mut input: [Field; 4096] = [0; 4096];\n let mut fixed_input = [3; 501];\n assert(in_len == fixed_input.len()); // sanity check\n for i in 0..in_len {\n input[i] = 3;\n }\n // absorb 250 of the 501 things\n let empty_sponge = Poseidon2Sponge::new((in_len as Field) * TWO_POW_64);\n let first_sponge = poseidon2_absorb_chunks_existing_sponge(empty_sponge, input, 250, true);\n // now absorb the final 251 (since they are all 3s, im being lazy and not making a new array)\n let mut final_sponge = poseidon2_absorb_chunks_existing_sponge(first_sponge, input, 251, true);\n let fixed_len_hash = Poseidon2Sponge::hash(fixed_input, fixed_input.len());\n assert(final_sponge.squeeze() == fixed_len_hash);\n}\n\n#[test]\nfn poseidon_chunks_empty_inputs() {\n let in_len = 0;\n let mut input: [Field; 4096] = [0; 4096];\n let mut constructed_empty_sponge = poseidon2_absorb_chunks(input, in_len, true);\n let mut first_sponge =\n poseidon2_absorb_chunks_existing_sponge(constructed_empty_sponge, input, in_len, true);\n assert(first_sponge.squeeze() == constructed_empty_sponge.squeeze());\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, 20, 21, 22, 23, 24,\n 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\n 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,\n 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,\n 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,\n 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,\n 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,\n 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::digest(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 =\n compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0x3b18c58c739716e76429634a61375c45b3b5cd470c22ab6d3e14cee23dd992);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(\n AztecAddress::from_field(1),\n EthAddress::from_field(3),\n 5,\n 2,\n 4,\n );\n assert(hash_result == 0xaab2a5828156782b12a1dc6f336e2bc627eb1b9514b02d511f66296990c050);\n}\n\n#[test]\nfn silo_l2_to_l1_message_matches_typescript() {\n let version = 4;\n let chainId = 5;\n\n let hash = silo_l2_to_l1_message(\n L2ToL1Message { recipient: EthAddress::from_field(1), content: 2 }.scope(\n AztecAddress::from_field(3),\n ),\n version,\n chainId,\n );\n\n // The following value was generated by `yarn-project/stdlib/src/hash/hash.test.ts`\n let hash_from_typescript = 0x0081edf209e087ad31b3fd24263698723d57190bd1d6e9fe056fc0c0a68ee661;\n\n assert_eq(hash, hash_from_typescript);\n}\n\n#[test]\nunconstrained fn poseidon2_hash_with_separator_bounded_vec_matches_non_bounded_vec_version() {\n let inputs = BoundedVec::::from_array([1, 2, 3]);\n let separator = 42;\n\n // Hash using bounded vec version\n let bounded_result = poseidon2_hash_with_separator_bounded_vec(inputs, separator);\n\n // Hash using regular version\n let regular_result = poseidon2_hash_with_separator([1, 2, 3], separator);\n\n // Results should match\n assert_eq(bounded_result, regular_result);\n}\n" - }, - "330": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/meta/mod.nr", - "source": "/// Generates the generic parameter declarations for a struct's trait implementation.\n///\n/// This function takes a struct type definition and generates the generic parameter declarations\n/// that go after the `impl` keyword. For example, given a struct with generics `N: u32` and `T`,\n/// it generates ``.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate generic declarations for\n///\n/// # Returns\n/// A quoted code block containing the generic parameter declarations, or an empty quote if the struct\n/// has no generic parameters\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Container {\n/// items: [T; N],\n/// count: u32\n/// }\n/// ```\n///\n/// This function generates:\n/// ```\n/// \n/// ```\ncomptime fn get_generics_declarations(s: TypeDefinition) -> Quoted {\n let generics = s.generics();\n\n if generics.len() > 0 {\n let generics_declarations_items = generics\n .map(|(name, maybe_integer_typ)| {\n // The second item in the generics tuple is an Option of an integer type that is Some only if\n // the generic is numeric.\n if maybe_integer_typ.is_some() {\n // The generic is numeric, so we return a quote defined as e.g. \"let N: u32\"\n let integer_type = maybe_integer_typ.unwrap();\n quote {let $name: $integer_type}\n } else {\n // The generic is not numeric, so we return a quote containing the name of the generic (e.g. \"T\")\n quote {$name}\n }\n })\n .join(quote {,});\n quote {<$generics_declarations_items>}\n } else {\n // The struct doesn't have any generics defined, so we just return an empty quote.\n quote {}\n }\n}\n\n/// Generates the `where` clause for a trait implementation that constrains non-numeric generic type parameters.\n///\n/// This function takes a struct type definition and a trait name, and generates a `where` clause that\n/// requires all non-numeric generic type parameters to implement the specified trait.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate the where clause for\n/// - `trait_name`: The name of the trait that non-numeric generic parameters must implement\n///\n/// # Returns\n/// A quoted code block containing the where clause, or an empty quote if the struct has no non-numeric\n/// generic parameters\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Container {\n/// items: [T; N],\n/// count: u32\n/// }\n/// ```\n///\n/// And trait name \"Serialize\", this function generates:\n/// ```\n/// where T: Serialize\n/// ```\ncomptime fn get_where_trait_clause(s: TypeDefinition, trait_name: Quoted) -> Quoted {\n let generics = s.generics();\n\n // The second item in the generics tuple is an Option of an integer type that is Some only if the generic is\n // numeric.\n let non_numeric_generics =\n generics.filter(|(_, maybe_integer_typ)| maybe_integer_typ.is_none());\n\n if non_numeric_generics.len() > 0 {\n let non_numeric_generics_declarations =\n non_numeric_generics.map(|(name, _)| quote {$name: $trait_name}).join(quote {,});\n quote {where $non_numeric_generics_declarations}\n } else {\n // There are no non-numeric generics, so we return an empty quote.\n quote {}\n }\n}\n\n/// Generates a `Serialize` trait implementation for a struct type.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A quoted code block containing the trait implementation\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Log {\n/// fields: [Field; N],\n/// length: u32\n/// }\n/// ```\n///\n/// This function generates code equivalent to:\n/// ```\n/// impl Serialize for Log {\n/// let N: u32 = <[Field; N] as Serialize>::N + ::N;\n///\n/// #[inline_always]\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut result = [0; _];\n/// let mut offset = 0;\n///\n/// let serialized_member = Serialize::serialize(self.fields);\n/// let serialized_member_len = <[Field; N] as Serialize>::N;\n/// for i in 0..serialized_member_len {\n/// result[i + offset] = serialized_member[i];\n/// }\n/// offset += serialized_member_len;\n///\n/// let serialized_member = Serialize::serialize(self.length);\n/// let serialized_member_len = ::N;\n/// for i in 0..serialized_member_len {\n/// result[i + offset] = serialized_member[i];\n/// }\n/// offset += serialized_member_len;\n///\n/// result\n/// }\n/// }\n/// ```\npub comptime fn derive_serialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.0.fields(nested_struct.1);\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Serialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_serialize_clause = get_where_trait_clause(s, quote {Serialize});\n\n // The following will give us ::N + ::N + ...\n let right_hand_side_of_definition_of_n = params\n .map(|(_, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n <$param_type as $crate::traits::Serialize>::N\n }\n })\n .join(quote {+});\n\n // For structs containing a single member, we can enhance performance by directly returning the serialized member,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let function_body = if params.len() > 1 {\n // For multiple struct members, generate serialization code that:\n // 1. Serializes each member\n // 2. Copies the serialized fields into the result array at the correct offset\n // 3. Updates the offset for the next member\n let serialization_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let serialized_member = $crate::traits::Serialize::serialize(self.$param_name);\n let serialized_member_len = <$param_type as $crate::traits::Serialize>::N;\n for i in 0..serialized_member_len {\n result[i + offset] = serialized_member[i];\n }\n offset += serialized_member_len;\n }\n })\n .join(quote {});\n\n quote {\n let mut result = [0; _];\n let mut offset = 0;\n\n $serialization_of_struct_members\n\n result\n }\n } else {\n let param_name = params[0].0;\n quote {\n $crate::traits::Serialize::serialize(self.$param_name)\n }\n };\n\n quote {\n impl$generics_declarations $crate::traits::Serialize for $typ\n $where_serialize_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n $function_body\n }\n }\n }\n}\n\n/// Generates a `Deserialize` trait implementation for a given struct `s`.\n///\n/// # Arguments\n/// * `s` - The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A `Quoted` block containing the generated trait implementation\n///\n/// # Requirements\n/// Each struct member type must implement the `Deserialize` trait (it gets used in the generated code).\n///\n/// # Example\n/// For a struct like:\n/// ```\n/// struct MyStruct {\n/// x: AztecAddress,\n/// y: Field,\n/// }\n/// ```\n///\n/// This generates:\n/// ```\n/// impl Deserialize for MyStruct {\n/// let N: u32 = ::N + ::N;\n///\n/// fn deserialize(serialized: [Field; Self::N]) -> Self {\n/// let mut offset = 0;\n/// let mut member_fields = [0; ::N];\n/// for i in 0..::N {\n/// member_fields[i] = serialized[i + offset];\n/// }\n/// let x = ::deserialize(member_fields);\n/// offset += ::N;\n///\n/// let mut member_fields = [0; ::N];\n/// for i in 0..::N {\n/// member_fields[i] = serialized[i + offset];\n/// }\n/// let y = ::deserialize(member_fields);\n/// offset += ::N;\n///\n/// Self { x, y }\n/// }\n/// }\n/// ```\npub(crate) comptime fn derive_deserialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.0.fields(nested_struct.1);\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Deserialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_deserialize_clause = get_where_trait_clause(s, quote {Deserialize});\n\n // The following will give us ::N + ::N + ...\n let right_hand_side_of_definition_of_n = params\n .map(|(_, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n <$param_type as $crate::traits::Deserialize>::N\n }\n })\n .join(quote {+});\n\n // For structs containing a single member, we can enhance performance by directly deserializing the input array,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let function_body = if params.len() > 1 {\n // This generates deserialization code for each struct member and concatenates them together.\n let deserialization_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let mut member_fields = [0; <$param_type as Deserialize>::N];\n for i in 0..<$param_type as Deserialize>::N {\n member_fields[i] = serialized[i + offset];\n }\n let $param_name = <$param_type as Deserialize>::deserialize(member_fields);\n offset += <$param_type as Deserialize>::N;\n }\n })\n .join(quote {});\n\n // We join the struct member names with a comma to be used in the `Self { ... }` syntax\n // This will give us e.g. `a, b, c` for a struct with three fields named `a`, `b`, and `c`.\n let struct_members = params\n .map(|(param_name, _, _): (Quoted, Type, Quoted)| quote { $param_name })\n .join(quote {,});\n\n quote {\n let mut offset = 0;\n\n $deserialization_of_struct_members\n\n Self { $struct_members }\n }\n } else {\n let param_name = params[0].0;\n quote {\n Self { $param_name: $crate::traits::Deserialize::deserialize(serialized) }\n }\n };\n\n quote {\n impl$generics_declarations $crate::traits::Deserialize for $typ\n $where_deserialize_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n #[inline_always]\n fn deserialize(serialized: [Field; Self::N]) -> Self {\n $function_body\n }\n }\n }\n}\n\n/// Generates a `Packable` trait implementation for a given struct `s`.\n///\n/// # Arguments\n/// * `s` - The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A `Quoted` block containing the generated trait implementation\n///\n/// # Requirements\n/// Each struct member type must implement the `Packable` trait (it gets used in the generated code).\n///\n/// # Example\n/// For a struct like:\n/// ```\n/// struct MyStruct {\n/// x: AztecAddress,\n/// y: Field,\n/// }\n/// ```\n///\n/// This generates:\n/// ```\n/// impl Packable for MyStruct {\n/// let N: u32 = 2;\n///\n/// fn pack(self) -> [Field; 2] {\n/// let mut result: [Field; 2] = [0_Field; 2];\n/// let mut offset: u32 = 0_u32;\n/// let packed_member: [Field; 1] = self.x.pack();\n/// let packed_member_len: u32 = ::N;\n/// for i in 0_u32..packed_member_len {\n/// {\n/// result[i + offset] = packed_member[i];\n/// }\n/// }\n/// offset = offset + packed_member_len;\n/// let packed_member: [Field; 1] = self.y.pack();\n/// let packed_member_len: u32 = ::N;\n/// for i in 0_u32..packed_member_len {\n/// {\n/// result[i + offset] = packed_member[i];\n/// }\n/// }\n/// offset = offset + packed_member_len;\n/// result\n/// }\n///\n/// fn unpack(packed: [Field; 2]) -> Self {\n/// let mut offset: u32 = 0_u32;\n/// let mut member_fields: [Field; 1] = [0_Field; 1];\n/// for i in 0_u32..::N {\n/// member_fields[i] = packed[i + offset];\n/// }\n/// let x: AztecAddress = ::unpack(member_fields);\n/// offset = offset + ::N;\n/// let mut member_fields: [Field; 1] = [0_Field; 1];\n/// for i in 0_u32..::N {\n/// member_fields[i] = packed[i + offset];\n/// }\n/// let y: Field = ::unpack(member_fields);\n/// offset = offset + ::N;\n/// Self { x: x, y: y }\n/// }\n/// }\n/// ```\npub comptime fn derive_packable(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.0.fields(nested_struct.1);\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Packable` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_packable_clause = get_where_trait_clause(s, quote {Packable});\n\n // The following will give us ::N + ::N + ...\n let right_hand_side_of_definition_of_n = params\n .map(|(_, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n <$param_type as $crate::traits::Packable>::N\n }\n })\n .join(quote {+});\n\n // For structs containing a single member, we can enhance performance by directly returning the packed member,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let pack_function_body = if params.len() > 1 {\n // For multiple struct members, generate packing code that:\n // 1. Packs each member\n // 2. Copies the packed fields into the result array at the correct offset\n // 3. Updates the offset for the next member\n let packing_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let packed_member = $crate::traits::Packable::pack(self.$param_name);\n let packed_member_len = <$param_type as $crate::traits::Packable>::N;\n for i in 0..packed_member_len {\n result[i + offset] = packed_member[i];\n }\n offset += packed_member_len;\n }\n })\n .join(quote {});\n\n quote {\n let mut result = [0; Self::N];\n let mut offset = 0;\n\n $packing_of_struct_members\n\n result\n }\n } else {\n let param_name = params[0].0;\n quote {\n $crate::traits::Packable::pack(self.$param_name)\n }\n };\n\n // For structs containing a single member, we can enhance performance by directly unpacking the input array,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let unpack_function_body = if params.len() > 1 {\n // For multiple struct members, generate unpacking code that:\n // 1. Unpacks each member\n // 2. Copies packed fields into member array at correct offset\n // 3. Updates offset for next member\n let unpacking_of_struct_members = params\n .map(|(param_name, param_type, _): (Quoted, Type, Quoted)| {\n quote {\n let mut member_fields = [0; <$param_type as $crate::traits::Packable>::N];\n for i in 0..<$param_type as $crate::traits::Packable>::N {\n member_fields[i] = packed[i + offset];\n }\n let $param_name = <$param_type as $crate::traits::Packable>::unpack(member_fields);\n offset += <$param_type as $crate::traits::Packable>::N;\n }\n })\n .join(quote {});\n\n // We join the struct member names with a comma to be used in the `Self { ... }` syntax\n let struct_members = params\n .map(|(param_name, _, _): (Quoted, Type, Quoted)| quote { $param_name })\n .join(quote {,});\n\n quote {\n let mut offset = 0;\n $unpacking_of_struct_members\n Self { $struct_members }\n }\n } else {\n let param_name = params[0].0;\n quote {\n Self { $param_name: $crate::traits::Packable::unpack(packed) }\n }\n };\n\n quote {\n impl$generics_declarations $crate::traits::Packable for $typ\n $where_packable_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n $pack_function_body\n }\n\n #[inline_always]\n fn unpack(packed: [Field; Self::N]) -> Self {\n $unpack_function_body\n }\n }\n }\n}\n\nmod test {\n use crate::traits::{Deserialize, Packable, Serialize};\n\n #[derive(Deserialize, Eq, Packable, Serialize)]\n pub struct Smol {\n a: Field,\n b: Field,\n }\n\n #[derive(Deserialize, Eq, Serialize)]\n pub struct HasArray {\n a: [Field; 2],\n b: bool,\n }\n\n #[derive(Deserialize, Eq, Serialize)]\n pub struct Fancier {\n a: Smol,\n b: [Field; 2],\n c: [u8; 3],\n d: str<16>,\n }\n\n #[derive(Deserialize, Eq, Packable, Serialize)]\n pub struct HasArrayWithGenerics {\n pub fields: [T; N],\n pub length: u32,\n }\n\n #[test]\n fn serde_on_smol() {\n let smol = Smol { a: 1, b: 2 };\n let serialized = smol.serialize();\n assert(serialized == [1, 2], serialized);\n let deserialized = Smol::deserialize(serialized);\n assert(deserialized == smol);\n\n // None of the struct members implements the `Packable` trait so the packed and serialized data should be the same\n let packed = smol.pack();\n assert_eq(packed, serialized, \"Packed does not match serialized\");\n }\n\n #[test]\n fn serde_on_has_array() {\n let has_array = HasArray { a: [1, 2], b: true };\n let serialized = has_array.serialize();\n assert(serialized == [1, 2, 1], serialized);\n let deserialized = HasArray::deserialize(serialized);\n assert(deserialized == has_array);\n }\n\n #[test]\n fn serde_on_fancier() {\n let fancier =\n Fancier { a: Smol { a: 1, b: 2 }, b: [0, 1], c: [1, 2, 3], d: \"metaprogramming!\" };\n let serialized = fancier.serialize();\n assert(\n serialized\n == [\n 1, 2, 0, 1, 1, 2, 3, 0x6d, 0x65, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61,\n 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x21,\n ],\n serialized,\n );\n let deserialized = Fancier::deserialize(serialized);\n assert(deserialized == fancier);\n }\n\n #[test]\n fn serde_on_contains_array_with_generics() {\n let struct_with_array_of_generics = HasArrayWithGenerics { fields: [1, 2, 3], length: 3 };\n let serialized = struct_with_array_of_generics.serialize();\n assert(serialized == [1, 2, 3, 3], serialized);\n let deserialized = HasArrayWithGenerics::deserialize(serialized);\n assert(deserialized == struct_with_array_of_generics);\n }\n\n #[test]\n fn packable_on_contains_array_with_generics() {\n let struct_with_array_of_generics = HasArrayWithGenerics { fields: [1, 2, 3], length: 3 };\n let packed = struct_with_array_of_generics.pack();\n assert(packed == [1, 2, 3, 3], packed);\n\n let unpacked = HasArrayWithGenerics::unpack(packed);\n assert(unpacked == struct_with_array_of_generics);\n }\n\n}\n" - }, - "331": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/point.nr", - "source": "pub use dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\nuse crate::{hash::poseidon2_hash, traits::{Deserialize, Empty, Hash, Packable, Serialize}};\n\npub global POINT_LENGTH: u32 = 3;\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl Serialize for Point {\n let N: u32 = POINT_LENGTH;\n\n fn serialize(self: Self) -> [Field; Self::N] {\n [self.x, self.y, self.is_infinite as Field]\n }\n}\n\nimpl Hash for Point {\n fn hash(self) -> Field {\n poseidon2_hash(self.serialize())\n }\n}\n\nimpl Empty for Point {\n /// Note: Does not return a valid point on curve - instead represents an empty/\"unpopulated\" point struct (e.g.\n /// empty/unpopulated value in an array of points).\n fn empty() -> Self {\n Point { x: 0, y: 0, is_infinite: false }\n }\n}\n\nimpl Deserialize for Point {\n let N: u32 = POINT_LENGTH;\n\n fn deserialize(serialized: [Field; Self::N]) -> Self {\n Point { x: serialized[0], y: serialized[1], is_infinite: serialized[2] != 0 }\n }\n}\n\n// TODO(#11356): use compact representation here.\nimpl Packable for Point {\n let N: u32 = POINT_LENGTH;\n\n fn pack(self) -> [Field; Self::N] {\n self.serialize()\n }\n\n fn unpack(packed: [Field; Self::N]) -> Self {\n Self::deserialize(packed)\n }\n}\n" - }, - "332": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/poseidon2.nr", - "source": "use crate::constants::TWO_POW_64;\nuse crate::traits::{Deserialize, Serialize};\nuse std::meta::derive;\n// NB: This is a clone of noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr\n// It exists as we sometimes need to perform custom absorption, but the stdlib version\n// has a private absorb() method (it's also designed to just be a hasher)\n// Can be removed when standalone noir poseidon lib exists: See noir#6679\n\ncomptime global RATE: u32 = 3;\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct Poseidon2Sponge {\n pub cache: [Field; 3],\n pub state: [Field; 4],\n pub cache_size: u32,\n pub squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2Sponge {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2Sponge::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2Sponge {\n let mut result =\n Poseidon2Sponge { 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) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = std::hash::poseidon2_permutation(self.state, 4);\n }\n\n pub fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\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 }\n }\n\n pub fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> Field {\n let iv: Field = (in_len as Field) * TWO_POW_64;\n let mut sponge = Poseidon2Sponge::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" - }, - "342": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/public_keys.nr", - "source": "use crate::{\n address::public_keys_hash::PublicKeysHash,\n constants::{\n DEFAULT_IVPK_M_X, DEFAULT_IVPK_M_Y, DEFAULT_NPK_M_X, DEFAULT_NPK_M_Y, DEFAULT_OVPK_M_X,\n DEFAULT_OVPK_M_Y, DEFAULT_TPK_M_X, DEFAULT_TPK_M_Y, GENERATOR_INDEX__PUBLIC_KEYS_HASH,\n },\n hash::poseidon2_hash_with_separator,\n traits::{Deserialize, Hash, Serialize},\n};\n\nuse dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\nuse std::{default::Default, meta::derive};\n\npub trait ToPoint {\n fn to_point(self) -> Point;\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct NpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for NpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n// Note: If we store npk_m_hash directly we can remove this trait implementation. See #8091\nimpl Hash for NpkM {\n fn hash(self) -> Field {\n self.inner.hash()\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct IvpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for IvpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct OvpkM {\n pub inner: Point,\n}\n\nimpl Hash for OvpkM {\n fn hash(self) -> Field {\n self.inner.hash()\n }\n}\n\nimpl ToPoint for OvpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct TpkM {\n pub inner: Point,\n}\n\nimpl ToPoint for TpkM {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct PublicKeys {\n pub npk_m: NpkM,\n pub ivpk_m: IvpkM,\n pub ovpk_m: OvpkM,\n pub tpk_m: TpkM,\n}\n\nimpl Default for PublicKeys {\n fn default() -> Self {\n PublicKeys {\n npk_m: NpkM {\n inner: Point { x: DEFAULT_NPK_M_X, y: DEFAULT_NPK_M_Y, is_infinite: false },\n },\n ivpk_m: IvpkM {\n inner: Point { x: DEFAULT_IVPK_M_X, y: DEFAULT_IVPK_M_Y, is_infinite: false },\n },\n ovpk_m: OvpkM {\n inner: Point { x: DEFAULT_OVPK_M_X, y: DEFAULT_OVPK_M_Y, is_infinite: false },\n },\n tpk_m: TpkM {\n inner: Point { x: DEFAULT_TPK_M_X, y: DEFAULT_TPK_M_Y, is_infinite: false },\n },\n }\n }\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(poseidon2_hash_with_separator(\n self.serialize(),\n GENERATOR_INDEX__PUBLIC_KEYS_HASH as Field,\n ))\n }\n}\n\npub struct AddressPoint {\n pub inner: Point,\n}\n\nimpl ToPoint for AddressPoint {\n fn to_point(self) -> Point {\n self.inner\n }\n}\n\nmod test {\n use crate::{\n point::POINT_LENGTH,\n public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, TpkM},\n traits::{Deserialize, Serialize},\n };\n use dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point;\n\n #[test]\n unconstrained fn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: 1, y: 2, is_infinite: false } },\n ivpk_m: IvpkM { inner: Point { x: 3, y: 4, is_infinite: false } },\n ovpk_m: OvpkM { inner: Point { x: 5, y: 6, is_infinite: false } },\n tpk_m: TpkM { inner: Point { x: 7, y: 8, is_infinite: false } },\n };\n\n let actual = keys.hash();\n let expected_public_keys_hash =\n 0x0fecd9a32db731fec1fded1b9ff957a1625c069245a3613a2538bd527068b0ad;\n\n assert(actual.to_field() == expected_public_keys_hash);\n }\n\n #[test]\n unconstrained fn compute_default_hash() {\n let keys = PublicKeys::default();\n\n let actual = keys.hash();\n let test_data_default_hash =\n 0x1d3bf1fb93ae0e9cda83b203dd91c3bfb492a9aecf30ec90e1057eced0f0e62d;\n\n assert(actual.to_field() == test_data_default_hash);\n }\n\n #[test]\n unconstrained fn serde() {\n let keys = PublicKeys {\n npk_m: NpkM { inner: Point { x: 1, y: 2, is_infinite: false } },\n ivpk_m: IvpkM { inner: Point { x: 3, y: 4, is_infinite: false } },\n ovpk_m: OvpkM { inner: Point { x: 5, y: 6, is_infinite: false } },\n tpk_m: TpkM { inner: Point { x: 7, y: 8, is_infinite: false } },\n };\n\n // We use the PUBLIC_KEYS_LENGTH constant to ensure that there is a match between the derived trait\n let serialized: [Field; POINT_LENGTH * 4] = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys, deserialized);\n }\n}\n" - }, - "344": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr", - "source": "use crate::{hash::poseidon2_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field\nwhere\n K: ToField,\n{\n poseidon2_hash([storage_slot, key.to_field()])\n}\n\nmod test {\n use crate::{address::AztecAddress, storage::map::derive_storage_slot_in_map, traits::FromField};\n\n #[test]\n fn test_derive_storage_slot_in_map_matches_typescript() {\n let map_slot = 0x132258fb6962c4387ba659d9556521102d227549a386d39f0b22d1890d59c2b5;\n let key = AztecAddress::from_field(\n 0x302dbc2f9b50a73283d5fb2f35bc01eae8935615817a0b4219a057b2ba8a5a3f,\n );\n\n let slot = derive_storage_slot_in_map(map_slot, key);\n\n // The following value was generated by `map_slot.test.ts`\n let slot_from_typescript =\n 0x15b9fe39449affd8b377461263e9d2b610b9ad40580553500b4e41d9cbd887ac;\n\n assert_eq(slot, slot_from_typescript);\n }\n}\n" - }, - "357": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr", - "source": "use crate::meta::{derive_deserialize, derive_packable, derive_serialize};\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.\npub trait Empty: Eq {\n fn empty() -> Self;\n\n fn is_empty(self) -> bool {\n self.eq(Self::empty())\n }\n\n // Requires this Noir fix: https://github.com/noir-lang/noir/issues/9002\n // fn assert_not_empty(self, msg: str) { // This msg version was failing with weird compiler errors.\n // // We provide a default impl but it's likely inefficient.\n // // The reason we include this function is because there's a lot of\n // // opportunity for optimisation on a per-struct basis.\n // // You only need to show one element is not empty to know that the whole thing\n // // is not empty.\n // // If you know an element of your struct which should always be nonempty,\n // // you can write an impl that solely checks that that element is nonempty.\n // assert(!self.is_empty(), msg);\n // }\n\n // This default impl is overwritten by types like arrays, because there's a much\n // more efficient approach.\n fn assert_empty(self, msg: str) {\n assert(self.is_empty(), msg);\n }\n}\n\nimpl Empty for Field {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\n\nimpl Empty for u1 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u8 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u16 {\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u32 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u64 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\nimpl Empty for u128 {\n #[inline_always]\n fn empty() -> Self {\n 0\n }\n}\n\nimpl Empty for [T; N]\nwhere\n T: Empty,\n{\n #[inline_always]\n fn empty() -> Self {\n [T::empty(); N]\n }\n\n fn is_empty(self) -> bool {\n self.all(|elem| elem.is_empty())\n }\n\n fn assert_empty(self, msg: str) -> () {\n self.for_each(|elem| elem.assert_empty(msg))\n }\n}\n\nimpl Empty for [T]\nwhere\n T: Empty,\n{\n #[inline_always]\n fn empty() -> Self {\n [T::empty()]\n }\n\n fn is_empty(self) -> bool {\n self.all(|elem| elem.is_empty())\n }\n\n fn assert_empty(self, msg: str) -> () {\n self.for_each(|elem| elem.assert_empty(msg))\n }\n}\nimpl Empty for (A, B)\nwhere\n A: Empty,\n B: Empty,\n{\n #[inline_always]\n fn empty() -> Self {\n (A::empty(), B::empty())\n }\n}\n\nimpl Empty for Option\nwhere\n T: Eq,\n{\n #[inline_always]\n fn empty() -> Self {\n Option::none()\n }\n}\n\n// pub fn is_empty(item: T) -> bool\n// where\n// T: Empty,\n// {\n// item.eq(T::empty())\n// }\n\n// pub fn is_empty_array(array: [T; N]) -> bool\n// where\n// T: Empty,\n// {\n// array.all(|elem| is_empty(elem))\n// }\n\n// pub fn assert_empty(item: T) -> ()\n// where\n// T: Empty,\n// {\n// assert(item.eq(T::empty()))\n// }\n\n// pub fn assert_empty_array(array: [T; N]) -> ()\n// where\n// T: Empty,\n// {\n// // A cheaper option than `is_empty_array` for if you don't need to gracefully\n// // handle a bool result.\n// // Avoids the `&` operator of `is_empty_array`'s `.all()` call.\n// for i in 0..N {\n// assert(is_empty(array[i]));\n// }\n// }\n\npub trait Hash {\n fn hash(self) -> Field;\n}\n\npub trait ToField {\n fn to_field(self) -> Field;\n}\n\nimpl ToField for Field {\n #[inline_always]\n fn to_field(self) -> Field {\n self\n }\n}\n\nimpl ToField for bool {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u1 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u8 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u16 {\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u32 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u64 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for u128 {\n #[inline_always]\n fn to_field(self) -> Field {\n self as Field\n }\n}\nimpl ToField for str {\n #[inline_always]\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\npub trait FromField {\n fn from_field(value: Field) -> Self;\n}\n\nimpl FromField for Field {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value\n }\n}\n\nimpl FromField for bool {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value != 0\n }\n}\nimpl FromField for u1 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u1\n }\n}\nimpl FromField for u8 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u8\n }\n}\nimpl FromField for u16 {\n fn from_field(value: Field) -> Self {\n value as u16\n }\n}\nimpl FromField for u32 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u32\n }\n}\nimpl FromField for u64 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u64\n }\n}\nimpl FromField for u128 {\n #[inline_always]\n fn from_field(value: Field) -> Self {\n value as u128\n }\n}\n\n// docs:start:serialize\n/// Trait for serializing Noir types into arrays of Fields.\n///\n/// An implementation of the Serialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait (and Deserialize) are\n/// typically used to communicate between Noir and TypeScript (via oracles and function arguments).\n///\n/// # On Following Noir's Intrinsic Serialization\n/// When calling a Noir function from TypeScript (TS), first the function arguments are serialized into an array\n/// of fields. This array is then included in the initial witness. Noir's intrinsic serialization is then used\n/// to deserialize the arguments from the witness. When the same Noir function is called from Noir this Serialize trait\n/// is used instead of the serialization in TS. For this reason we need to have a match between TS serialization,\n/// Noir's intrinsic serialization and the implementation of this trait. If there is a mismatch, the function calls\n/// fail with an arguments hash mismatch error message.\n///\n/// # Associated Constants\n/// * `N` - The length of the output Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl Serialize for str {\n/// let N: u32 = N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let bytes = self.as_bytes();\n/// let mut fields = [0; Self::N];\n/// for i in 0..bytes.len() {\n/// fields[i] = bytes[i] as Field; // Each byte gets its own Field\n/// }\n/// fields\n/// }\n/// }\n/// ```\n#[derive_via(derive_serialize)]\npub trait Serialize {\n let N: u32;\n\n fn serialize(self) -> [Field; N];\n}\n// docs:end:serialize\n\nimpl Serialize for str {\n let N: u32 = M;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let bytes = self.as_bytes();\n let mut fields = [0; Self::N];\n for i in 0..bytes.len() {\n fields[i] = bytes[i] as Field;\n }\n fields\n }\n}\n\n/// Implementation of Deserialize for BoundedVec.\n///\n/// This implementation deserializes a BoundedVec from an array of Fields. The array contains:\n/// 1. The serialized items, each taking up T::N Fields\n/// 2. The length of the BoundedVec as the last Field\n///\n/// # Type Parameters\n/// * `T` - The type of items stored in the BoundedVec, must implement Deserialize\n/// * `M` - The maximum length of the BoundedVec\n///\n/// # Fields Array Layout\n/// [item1_field1, item1_field2, ..., item2_field1, item2_field2, ..., length]\n/// Where:\n/// - itemN_fieldM: The M-th Field of the N-th item (T::N Fields per item)\n/// - length: The number of items in the BoundedVec (1 Field)\n///\n/// Total length N = T::N * M + 1, where:\n/// - T::N is the number of Fields needed to deserialize one item\n/// - M is the maximum length of the BoundedVec\n/// - +1 is for storing the length\n///\n/// # Note\n/// Not deriving this because it's not supported to call derive_deserialize on a \"remote\" struct (and it will never\n/// be supported).\nimpl Deserialize for BoundedVec\nwhere\n T: Deserialize,\n{\n let N: u32 = ::N * M + 1;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut new_bounded_vec: BoundedVec = BoundedVec::new();\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n let len = fields[::N * M] as u32;\n\n for i in 0..len {\n let mut nested_fields = [0; ::N];\n for j in 0..::N {\n nested_fields[j] = fields[i * ::N + j];\n }\n\n let item = T::deserialize(nested_fields);\n new_bounded_vec.push(item);\n }\n\n new_bounded_vec\n }\n}\n\n// This may cause issues if used as program input, because noir disallows empty arrays for program input.\n// I think this is okay because I don't foresee a unit type being used as input. But leaving this comment as a hint\n// if someone does run into this in the future.\nimpl Deserialize for () {\n let N: u32 = 0;\n\n fn deserialize(_fields: [Field; Self::N]) -> Self {\n ()\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl Serialize for BoundedVec\nwhere\n T: Serialize,\n{\n let N: u32 = ::N * M + 1; // +1 for the length of the BoundedVec\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let mut fields = [0; Self::N];\n\n let storage = self.storage();\n\n for i in 0..M {\n let serialized_item = storage[i].serialize();\n\n for j in 0..::N {\n fields[i * ::N + j] = serialized_item[j];\n }\n }\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n fields[::N * M] = self.len() as Field;\n\n fields\n }\n}\n\n// docs:start:deserialize\n/// Trait for deserializing Noir types from arrays of Fields.\n///\n/// An implementation of the Deserialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait is typically used when\n/// deserializing return values from function calls in Noir. Since the same function could be called from TypeScript\n/// (TS), in which case the TS deserialization would get used, we need to have a match between the 2.\n///\n/// # Associated Constants\n/// * `N` - The length of the input Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl Deserialize for str {\n/// let N: u32 = M;\n///\n/// #[inline_always]\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// str::::from(fields.map(|value| value as u8))\n/// }\n/// }\n/// ```\n#[derive_via(derive_deserialize)]\npub trait Deserialize {\n let N: u32;\n\n fn deserialize(fields: [Field; N]) -> Self;\n}\n// docs:end:deserialize\n\nimpl Deserialize for str {\n let N: u32 = M;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n str::::from(fields.map(|value| value as u8))\n }\n}\n\n/// Trait for efficiently packing and unpacking Noir types into and from arrays of Fields.\n///\n/// The `Packable` trait allows types to be serialized and deserialized with a focus on minimizing the size of\n/// the resulting Field array. This trait is used when storage efficiency is critical (e.g. when storing data\n/// in the contract's public storage).\n///\n/// # Associated Constants\n/// * `N` - The length of the Field array, known at compile time\n#[derive_via(derive_packable)]\npub trait Packable {\n let N: u32;\n\n /// Packs the current value into a compact array of `Field` elements.\n fn pack(self) -> [Field; N];\n\n /// Unpacks a compact array of `Field` elements into the original value.\n fn unpack(fields: [Field; N]) -> Self;\n}\n\n#[test]\nunconstrained fn bounded_vec_serialization() {\n // Test empty BoundedVec\n let empty_vec: BoundedVec = BoundedVec::from_array([]);\n let serialized = empty_vec.serialize();\n let deserialized = BoundedVec::::deserialize(serialized);\n assert_eq(empty_vec, deserialized);\n assert_eq(deserialized.len(), 0);\n\n // Test partially filled BoundedVec\n let partial_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2]]);\n let serialized = partial_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(partial_vec, deserialized);\n assert_eq(deserialized.len(), 1);\n assert_eq(deserialized.get(0), [1, 2]);\n\n // Test full BoundedVec\n let full_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2], [3, 4], [5, 6]]);\n let serialized = full_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(full_vec, deserialized);\n assert_eq(deserialized.len(), 3);\n assert_eq(deserialized.get(0), [1, 2]);\n assert_eq(deserialized.get(1), [3, 4]);\n assert_eq(deserialized.get(2), [5, 6]);\n}\n" - }, - "359": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/type_packing.nr", - "source": "use crate::traits::Packable;\n\nglobal BOOL_PACKED_LEN: u32 = 1;\nglobal U8_PACKED_LEN: u32 = 1;\nglobal U16_PACKED_LEN: u32 = 1;\nglobal U32_PACKED_LEN: u32 = 1;\nglobal U64_PACKED_LEN: u32 = 1;\nglobal U128_PACKED_LEN: u32 = 1;\nglobal FIELD_PACKED_LEN: u32 = 1;\nglobal I8_PACKED_LEN: u32 = 1;\nglobal I16_PACKED_LEN: u32 = 1;\nglobal I32_PACKED_LEN: u32 = 1;\nglobal I64_PACKED_LEN: u32 = 1;\n\nimpl Packable for bool {\n let N: u32 = BOOL_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> bool {\n (fields[0] as u1) != 0\n }\n}\n\nimpl Packable for u8 {\n let N: u32 = U8_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Packable for u16 {\n let N: u32 = U16_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u16\n }\n}\n\nimpl Packable for u32 {\n let N: u32 = U32_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Packable for u64 {\n let N: u32 = U64_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Packable for u128 {\n let N: u32 = U128_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u128\n }\n}\n\nimpl Packable for Field {\n let N: u32 = FIELD_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0]\n }\n}\n\nimpl Packable for i8 {\n let N: u32 = I8_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u8 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u8 as i8\n }\n}\n\nimpl Packable for i16 {\n let N: u32 = I16_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u16 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u16 as i16\n }\n}\n\nimpl Packable for i32 {\n let N: u32 = I32_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u32 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u32 as i32\n }\n}\n\nimpl Packable for i64 {\n let N: u32 = I64_PACKED_LEN;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n [self as u64 as Field]\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n fields[0] as u64 as i64\n }\n}\n\nimpl Packable for [T; M]\nwhere\n T: Packable,\n{\n let N: u32 = M * ::N;\n\n #[inline_always]\n fn pack(self) -> [Field; Self::N] {\n let mut result: [Field; Self::N] = std::mem::zeroed();\n for i in 0..M {\n let serialized = self[i].pack();\n for j in 0..::N {\n result[i * ::N + j] = serialized[j];\n }\n }\n result\n }\n\n #[inline_always]\n fn unpack(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::utils::reader::Reader::new(fields);\n let mut result: [T; M] = std::mem::zeroed();\n reader.read_struct_array::::N, M>(Packable::unpack, result)\n }\n}\n\n#[test]\nfn test_u16_packing() {\n let a: u16 = 10;\n assert_eq(a, u16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i8_packing() {\n let a: i8 = -10;\n assert_eq(a, i8::unpack(a.pack()));\n}\n\n#[test]\nfn test_i16_packing() {\n let a: i16 = -10;\n assert_eq(a, i16::unpack(a.pack()));\n}\n\n#[test]\nfn test_i32_packing() {\n let a: i32 = -10;\n assert_eq(a, i32::unpack(a.pack()));\n}\n\n#[test]\nfn test_i64_packing() {\n let a: i64 = -10;\n assert_eq(a, i64::unpack(a.pack()));\n}\n" - }, - "360": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/type_serialization.nr", - "source": "use crate::traits::{Deserialize, Serialize};\n\nglobal BOOL_SERIALIZED_LEN: u32 = 1;\nglobal U8_SERIALIZED_LEN: u32 = 1;\nglobal U16_SERIALIZED_LEN: u32 = 1;\nglobal U32_SERIALIZED_LEN: u32 = 1;\nglobal U64_SERIALIZED_LEN: u32 = 1;\nglobal U128_SERIALIZED_LEN: u32 = 1;\nglobal FIELD_SERIALIZED_LEN: u32 = 1;\nglobal I8_SERIALIZED_LEN: u32 = 1;\nglobal I16_SERIALIZED_LEN: u32 = 1;\nglobal I32_SERIALIZED_LEN: u32 = 1;\nglobal I64_SERIALIZED_LEN: u32 = 1;\n\nimpl Serialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> bool {\n fields[0] != 0\n }\n}\n\nimpl Serialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Serialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u16\n }\n}\n\nimpl Serialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Serialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Serialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u128\n }\n}\n\nimpl Serialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self]\n }\n}\n\nimpl Deserialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0]\n }\n}\n\nimpl Serialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u8 as Field]\n }\n}\n\nimpl Deserialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u8 as i8\n }\n}\n\nimpl Serialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u16 as Field]\n }\n}\n\nimpl Deserialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u16 as i16\n }\n}\n\nimpl Serialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u32 as Field]\n }\n}\n\nimpl Deserialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u32 as i32\n }\n}\n\nimpl Serialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n [self as u64 as Field]\n }\n}\n\nimpl Deserialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n fields[0] as u64 as i64\n }\n}\n\nimpl Serialize for [T; M]\nwhere\n T: Serialize,\n{\n let N: u32 = ::N * M;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let mut result: [Field; _] = std::mem::zeroed();\n for i in 0..M {\n let serialized_t = self[i].serialize();\n for j in 0..::N {\n result[i * ::N + j] = serialized_t[j];\n }\n }\n result\n }\n}\n\nimpl Deserialize for [T; M]\nwhere\n T: Deserialize,\n{\n let N: u32 = ::N * M;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::utils::reader::Reader::new(fields);\n let mut result: [T; M] = std::mem::zeroed();\n reader.read_struct_array::::N, M>(Deserialize::deserialize, result)\n }\n}\n\nimpl Serialize for Option\nwhere\n T: Serialize,\n{\n let N: u32 = ::N + 1;\n\n #[inline_always]\n fn serialize(self) -> [Field; Self::N] {\n let mut result: [Field; Self::N] = std::mem::zeroed();\n\n result[0] = if self.is_some() { 1 } else { 0 };\n\n let value_serialized = self.unwrap_unchecked().serialize();\n for i in 0..::N {\n result[1 + i] = value_serialized[i];\n }\n\n result\n }\n}\n\nimpl Deserialize for Option\nwhere\n T: Deserialize,\n{\n let N: u32 = ::N + 1;\n\n #[inline_always]\n fn deserialize(fields: [Field; Self::N]) -> Self {\n if fields[0] == 1 {\n let mut value_fields = [0; ::N];\n for i in 0..::N {\n value_fields[i] = fields[1 + i];\n }\n\n Option::some(T::deserialize(value_fields))\n } else {\n Option::none()\n }\n }\n}\n\nmod test {\n use crate::traits::{Deserialize, Serialize};\n\n #[test]\n fn u16_serialization() {\n let a: u16 = 10;\n assert_eq(a, u16::deserialize(a.serialize()));\n }\n\n #[test]\n fn i8_serialization() {\n let a: i8 = -10;\n assert_eq(a, i8::deserialize(a.serialize()));\n }\n\n #[test]\n fn i16_serialization() {\n let a: i16 = -10;\n assert_eq(a, i16::deserialize(a.serialize()));\n }\n\n #[test]\n fn i32_serialization() {\n let a: i32 = -10;\n assert_eq(a, i32::deserialize(a.serialize()));\n }\n\n #[test]\n fn i64_serialization() {\n let a: i64 = -10;\n assert_eq(a, i64::deserialize(a.serialize()));\n }\n\n #[test]\n fn option_field_serialization() {\n let opt_some = Option::some(5);\n assert_eq(Option::<_>::deserialize(opt_some.serialize()), opt_some);\n\n let opt_none = Option::none();\n assert_eq(Option::::deserialize(opt_none.serialize()), opt_none);\n }\n\n #[test]\n fn option_array_serialization() {\n let opt_some = Option::some([2, 5]);\n assert_eq(Option::<_>::deserialize(opt_some.serialize()), opt_some);\n\n let opt_none = Option::none();\n assert_eq(Option::::deserialize(opt_none.serialize()), opt_none);\n }\n}\n" - }, - "380": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr", - "source": "pub 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_u64(&mut self) -> u64 {\n self.read() as u64\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() != 0\n }\n\n pub fn read_array(&mut self) -> [Field; K] {\n let mut result = [0; 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 pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array());\n result\n }\n\n pub fn read_struct_array(\n &mut self,\n deserialise: fn([Field; K]) -> T,\n mut result: [T; C],\n ) -> [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_eq(self.offset, self.data.len(), \"Reader did not read all data\");\n }\n}\n" - }, - "42": { - "path": "std/option.nr", - "source": "use crate::cmp::{Eq, Ord, Ordering};\nuse crate::default::Default;\nuse crate::hash::{Hash, Hasher};\n\npub struct 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::mem::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 {\n self._value\n } else {\n default\n }\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 pub 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 {\n self\n } else {\n other\n }\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 {\n self\n } else {\n default()\n }\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 {\n Option::none()\n } else {\n self\n }\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\nwhere\n T: Eq,\n{\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\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\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\nwhere\n T: Ord,\n{\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 if other._is_some {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n" - }, - "43": { - "path": "std/panic.nr", - "source": "pub fn panic(message: fmtstr) -> U {\n assert(false, message);\n crate::mem::zeroed()\n}\n" - }, - "5": { - "path": "std/cmp.nr", - "source": "use crate::meta::derive_via;\n\n#[derive_via(derive_eq)]\n// docs:start:eq-trait\npub trait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\n// docs:start:derive_eq\ncomptime fn derive_eq(s: TypeDefinition) -> Quoted {\n let signature = quote { fn eq(_self: Self, _other: Self) -> bool };\n let for_each_field = |name| quote { (_self.$name == _other.$name) };\n let body = |fields| {\n if s.fields_as_written().len() == 0 {\n quote { true }\n } else {\n fields\n }\n };\n crate::meta::make_trait_impl(\n s,\n quote { $crate::cmp::Eq },\n signature,\n for_each_field,\n quote { & },\n body,\n )\n}\n// docs:end:derive_eq\n\nimpl Eq for Field {\n fn eq(self, other: Field) -> bool {\n self == other\n }\n}\n\nimpl Eq for u128 {\n fn eq(self, other: u128) -> bool {\n self == other\n }\n}\nimpl Eq for u64 {\n fn eq(self, other: u64) -> bool {\n self == other\n }\n}\nimpl Eq for u32 {\n fn eq(self, other: u32) -> bool {\n self == other\n }\n}\nimpl Eq for u16 {\n fn eq(self, other: u16) -> bool {\n self == other\n }\n}\nimpl Eq for u8 {\n fn eq(self, other: u8) -> bool {\n self == other\n }\n}\nimpl Eq for u1 {\n fn eq(self, other: u1) -> bool {\n self == other\n }\n}\n\nimpl Eq for i8 {\n fn eq(self, other: i8) -> bool {\n self == other\n }\n}\nimpl Eq for i16 {\n fn eq(self, other: i16) -> bool {\n self == other\n }\n}\nimpl Eq for i32 {\n fn eq(self, other: i32) -> bool {\n self == other\n }\n}\nimpl Eq for i64 {\n fn eq(self, other: i64) -> bool {\n self == other\n }\n}\n\nimpl Eq for () {\n fn eq(_self: Self, _other: ()) -> bool {\n true\n }\n}\nimpl Eq for bool {\n fn eq(self, other: bool) -> bool {\n self == other\n }\n}\n\nimpl Eq for [T; N]\nwhere\n T: Eq,\n{\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]\nwhere\n T: Eq,\n{\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n if result {\n for i in 0..self.len() {\n result &= self[i].eq(other[i]);\n }\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)\nwhere\n A: Eq,\n B: Eq,\n{\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)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n{\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)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n{\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)\nwhere\n A: Eq,\n B: Eq,\n C: Eq,\n D: Eq,\n E: Eq,\n{\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0)\n & self.1.eq(other.1)\n & self.2.eq(other.2)\n & self.3.eq(other.3)\n & 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.\npub struct 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#[derive_via(derive_ord)]\n// docs:start:ord-trait\npub trait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// docs:start:derive_ord\ncomptime fn derive_ord(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::cmp::Ord };\n let signature = quote { fn cmp(_self: Self, _other: Self) -> $crate::cmp::Ordering };\n let for_each_field = |name| quote {\n if result == $crate::cmp::Ordering::equal() {\n result = _self.$name.cmp(_other.$name);\n }\n };\n let body = |fields| quote {\n let mut result = $crate::cmp::Ordering::equal();\n $fields\n result\n };\n crate::meta::make_trait_impl(s, name, signature, for_each_field, quote {}, body)\n}\n// docs:end:derive_ord\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u128 {\n fn cmp(self, other: u128) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\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 u16 {\n fn cmp(self, other: u16) -> 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 i16 {\n fn cmp(self, other: i16) -> 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 if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for [T; N]\nwhere\n T: Ord,\n{\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 result = self[i].cmp(other[i]);\n }\n }\n result\n }\n}\n\nimpl Ord for [T]\nwhere\n T: Ord,\n{\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 self_len = self.len();\n let other_len = other.len();\n let min_len = if self_len < other_len {\n self_len\n } else {\n other_len\n };\n\n let mut result = Ordering::equal();\n for i in 0..min_len {\n if result == Ordering::equal() {\n result = self[i].cmp(other[i]);\n }\n }\n\n if result != Ordering::equal() {\n result\n } else {\n self_len.cmp(other_len)\n }\n }\n}\n\nimpl Ord for (A, B)\nwhere\n A: Ord,\n B: Ord,\n{\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)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n{\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)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n{\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)\nwhere\n A: Ord,\n B: Ord,\n C: Ord,\n D: Ord,\n E: Ord,\n{\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\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v1\n } else {\n v2\n }\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\nwhere\n T: Ord,\n{\n if v1 > v2 {\n v2\n } else {\n v1\n }\n}\n\nmod cmp_tests {\n use super::{Eq, max, min, Ord};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0_u64, 1), 0);\n assert_eq(min(0_u64, 0), 0);\n assert_eq(min(1_u64, 1), 1);\n assert_eq(min(255_u8, 0), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0_u64, 1), 1);\n assert_eq(max(0_u64, 0), 0);\n assert_eq(max(1_u64, 1), 1);\n assert_eq(max(255_u8, 0), 255);\n }\n\n #[test]\n fn correctly_handles_unequal_length_slices() {\n let slice_1 = &[0, 1, 2, 3];\n let slice_2 = &[0, 1, 2];\n assert(!slice_1.eq(slice_2));\n }\n\n #[test]\n fn lexicographic_ordering_for_slices() {\n assert(&[2_u32].cmp(&[1_u32, 1_u32, 1_u32]) == super::Ordering::greater());\n assert(&[1_u32, 2_u32].cmp(&[1_u32, 2_u32, 3_u32]) == super::Ordering::less());\n }\n}\n" - }, - "50": { - "path": "/home/josh/Documents/Github/aztec-web-starter/contracts/src/main.nr", - "source": "use dep::aztec::macros::aztec;\n\n#[aztec]\npub contract PrivateVoting {\n use dep::aztec::keys::getters::get_public_keys;\n use dep::aztec::macros::{\n functions::{initializer, internal, private, public, utility},\n storage::storage,\n };\n use dep::aztec::protocol_types::{address::AztecAddress, traits::{Hash, ToField}};\n use dep::aztec::state_vars::{Map, PublicImmutable, PublicMutable};\n\n #[storage]\n struct Storage {\n admin: PublicMutable, // admin can end vote\n tally: Map, Context>, // we will store candidate as key and number of votes as value\n vote_ended: PublicMutable, // vote_ended is boolean\n active_at_block: PublicImmutable, // when people can start voting\n }\n\n #[public]\n #[initializer]\n fn constructor(admin: AztecAddress) {\n storage.admin.write(admin);\n storage.vote_ended.write(false);\n storage.active_at_block.initialize(context.block_number());\n }\n\n #[private]\n fn cast_vote(candidate: Field) {\n let msg_sender_npk_m_hash = get_public_keys(context.msg_sender()).npk_m.hash();\n\n let secret = context.request_nsk_app(msg_sender_npk_m_hash); // get secret key of caller of function\n let nullifier = std::hash::pedersen_hash([context.msg_sender().to_field(), secret]); // derive nullifier from sender and secret\n context.push_nullifier(nullifier);\n PrivateVoting::at(context.this_address()).add_to_tally_public(candidate).enqueue(\n &mut context,\n );\n }\n\n #[public]\n #[internal]\n fn add_to_tally_public(candidate: Field) {\n assert(storage.vote_ended.read() == false, \"Vote has ended\"); // assert that vote has not ended\n let new_tally = storage.tally.at(candidate).read() + 1;\n storage.tally.at(candidate).write(new_tally);\n }\n\n #[public]\n fn end_vote() {\n assert(storage.admin.read().eq(context.msg_sender()), \"Only admin can end votes\"); // assert that caller is admin\n storage.vote_ended.write(true);\n }\n\n #[utility]\n unconstrained fn get_vote(candidate: Field) -> Field {\n storage.tally.at(candidate).read()\n }\n}\n" - }, - "6": { - "path": "std/collections/bounded_vec.nr", - "source": "use crate::{cmp::Eq, convert::From, runtime::is_unconstrained, static_assert};\n\n/// A `BoundedVec` is a growable storage similar to a `Vec` except that it\n/// is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented\n/// via slices and thus is not subject to the same restrictions slices are (notably, nested\n/// slices - and thus nested vectors as well - are disallowed).\n///\n/// Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by\n/// pushing an additional element is also more efficient - the length only needs to be increased\n/// by one.\n///\n/// For these reasons `BoundedVec` should generally be preferred over `Vec` when there\n/// is a reasonable maximum bound that can be placed on the vector.\n///\n/// Example:\n///\n/// ```noir\n/// let mut vector: BoundedVec = BoundedVec::new();\n/// for i in 0..5 {\n/// vector.push(i);\n/// }\n/// assert(vector.len() == 5);\n/// assert(vector.max_len() == 10);\n/// ```\npub struct BoundedVec {\n storage: [T; MaxLen],\n len: u32,\n}\n\nimpl BoundedVec {\n /// Creates a new, empty vector of length zero.\n ///\n /// Since this container is backed by an array internally, it still needs an initial value\n /// to give each element. To resolve this, each element is zeroed internally. This value\n /// is guaranteed to be inaccessible unless `get_unchecked` is used.\n ///\n /// Example:\n ///\n /// ```noir\n /// let empty_vector: BoundedVec = BoundedVec::new();\n /// assert(empty_vector.len() == 0);\n /// ```\n ///\n /// Note that whenever calling `new` the maximum length of the vector should always be specified\n /// via a type signature:\n ///\n /// ```noir\n /// fn good() -> BoundedVec {\n /// // Ok! MaxLen is specified with a type annotation\n /// let v1: BoundedVec = BoundedVec::new();\n /// let v2 = BoundedVec::new();\n ///\n /// // Ok! MaxLen is known from the type of `good`'s return value\n /// v2\n /// }\n ///\n /// fn bad() {\n /// // Error: Type annotation needed\n /// // The compiler can't infer `MaxLen` from the following code:\n /// let mut v3 = BoundedVec::new();\n /// v3.push(5);\n /// }\n /// ```\n ///\n /// This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions\n /// but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a\n /// constraint failure at runtime when the vec is pushed to.\n pub fn new() -> Self {\n let zeroed = crate::mem::zeroed();\n BoundedVec { storage: [zeroed; MaxLen], len: 0 }\n }\n\n /// Retrieves an element from the vector at the given index, starting from zero.\n ///\n /// If the given index is equal to or greater than the length of the vector, this\n /// will issue a constraint failure.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn foo(v: BoundedVec) {\n /// let first = v.get(0);\n /// let last = v.get(v.len() - 1);\n /// assert(first != last);\n /// }\n /// ```\n pub fn get(self, index: u32) -> T {\n assert(index < self.len, \"Attempted to read past end of BoundedVec\");\n self.get_unchecked(index)\n }\n\n /// Retrieves an element from the vector at the given index, starting from zero, without\n /// performing a bounds check.\n ///\n /// Since this function does not perform a bounds check on length before accessing the element,\n /// it is unsafe! Use at your own risk!\n ///\n /// Example:\n ///\n /// ```noir\n /// fn sum_of_first_three(v: BoundedVec) -> u32 {\n /// // Always ensure the length is larger than the largest\n /// // index passed to get_unchecked\n /// assert(v.len() > 2);\n /// let first = v.get_unchecked(0);\n /// let second = v.get_unchecked(1);\n /// let third = v.get_unchecked(2);\n /// first + second + third\n /// }\n /// ```\n pub fn get_unchecked(self, index: u32) -> T {\n self.storage[index]\n }\n\n /// Writes an element to the vector at the given index, starting from zero.\n ///\n /// If the given index is equal to or greater than the length of the vector, this will issue a constraint failure.\n ///\n /// Example:\n ///\n /// ```noir\n /// fn foo(v: BoundedVec) {\n /// let first = v.get(0);\n /// assert(first != 42);\n /// v.set(0, 42);\n /// let new_first = v.get(0);\n /// assert(new_first == 42);\n /// }\n /// ```\n pub fn set(&mut self, index: u32, value: T) {\n assert(index < self.len, \"Attempted to write past end of BoundedVec\");\n self.set_unchecked(index, value)\n }\n\n /// Writes an element to the vector at the given index, starting from zero, without performing a bounds check.\n ///\n /// Since this function does not perform a bounds check on length before accessing the element, it is unsafe! Use at your own risk!\n ///\n /// Example:\n ///\n /// ```noir\n /// fn set_unchecked_example() {\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_array([1, 2]);\n ///\n /// // Here we're safely writing within the valid range of `vec`\n /// // `vec` now has the value [42, 2]\n /// vec.set_unchecked(0, 42);\n ///\n /// // We can then safely read this value back out of `vec`.\n /// // Notice that we use the checked version of `get` which would prevent reading unsafe values.\n /// assert_eq(vec.get(0), 42);\n ///\n /// // We've now written past the end of `vec`.\n /// // As this index is still within the maximum potential length of `v`,\n /// // it won't cause a constraint failure.\n /// vec.set_unchecked(2, 42);\n /// println(vec);\n ///\n /// // This will write past the end of the maximum potential length of `vec`,\n /// // it will then trigger a constraint failure.\n /// vec.set_unchecked(5, 42);\n /// println(vec);\n /// }\n /// ```\n pub fn set_unchecked(&mut self, index: u32, value: T) {\n self.storage[index] = value;\n }\n\n /// Pushes an element to the end of the vector. This increases the length\n /// of the vector by one.\n ///\n /// Panics if the new length of the vector will be greater than the max length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// v.push(1);\n /// v.push(2);\n ///\n /// // Panics with failed assertion \"push out of bounds\"\n /// v.push(3);\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 /// Returns the current length of this vector\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// assert(v.len() == 0);\n ///\n /// v.push(100);\n /// assert(v.len() == 1);\n ///\n /// v.push(200);\n /// v.push(300);\n /// v.push(400);\n /// assert(v.len() == 4);\n ///\n /// let _ = v.pop();\n /// let _ = v.pop();\n /// assert(v.len() == 2);\n /// ```\n pub fn len(self) -> u32 {\n self.len\n }\n\n /// Returns the maximum length of this vector. This is always\n /// equal to the `MaxLen` parameter this vector was initialized with.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// assert(v.max_len() == 5);\n /// v.push(10);\n /// assert(v.max_len() == 5);\n /// ```\n pub fn max_len(_self: BoundedVec) -> u32 {\n MaxLen\n }\n\n /// Returns the internal array within this vector.\n ///\n /// Since arrays in Noir are immutable, mutating the returned storage array will not mutate\n /// the storage held internally by this vector.\n ///\n /// Note that uninitialized elements may be zeroed out!\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n ///\n /// assert(v.storage() == [0, 0, 0, 0, 0]);\n ///\n /// v.push(57);\n /// assert(v.storage() == [57, 0, 0, 0, 0]);\n /// ```\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n /// Pushes each element from the given array to this vector.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_array([2, 4]);\n ///\n /// assert(vec.len == 2);\n /// assert(vec.get(0) == 2);\n /// assert(vec.get(1) == 4);\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 /// Pushes each element from the given slice to this vector.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut vec: BoundedVec = BoundedVec::new();\n /// vec.extend_from_slice(&[2, 4]);\n ///\n /// assert(vec.len == 2);\n /// assert(vec.get(0) == 2);\n /// assert(vec.get(1) == 4);\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 /// Pushes each element from the other vector to this vector. The length of\n /// the other vector is left unchanged.\n ///\n /// Panics if pushing each element would cause the length of this vector\n /// to exceed the maximum length.\n ///\n /// ```noir\n /// let mut v1: BoundedVec = BoundedVec::new();\n /// let mut v2: BoundedVec = BoundedVec::new();\n ///\n /// v2.extend_from_array([1, 2, 3]);\n /// v1.extend_from_bounded_vec(v2);\n ///\n /// assert(v1.storage() == [1, 2, 3, 0, 0]);\n /// assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]);\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 if is_unconstrained() {\n for i in 0..append_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n } else {\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 }\n self.len = new_len;\n }\n\n /// Creates a new vector, populating it with values derived from an array input.\n /// The maximum length of the vector is determined based on the type signature.\n ///\n /// Example:\n ///\n /// ```noir\n /// let bounded_vec: BoundedVec = BoundedVec::from_array([1, 2, 3])\n /// ```\n pub fn from_array(array: [T; Len]) -> Self {\n static_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 /// Pops the element at the end of the vector. This will decrease the length\n /// of the vector by one.\n ///\n /// Panics if the vector is empty.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// v.push(1);\n /// v.push(2);\n ///\n /// let two = v.pop();\n /// let one = v.pop();\n ///\n /// assert(two == 2);\n /// assert(one == 1);\n ///\n /// // error: cannot pop from an empty vector\n /// let _ = v.pop();\n /// ```\n pub fn pop(&mut self) -> T {\n assert(self.len > 0, \"cannot pop from an empty vector\");\n self.len -= 1;\n\n let elem = self.storage[self.len];\n self.storage[self.len] = crate::mem::zeroed();\n elem\n }\n\n /// Returns true if the given predicate returns true for any element\n /// in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let mut v: BoundedVec = BoundedVec::new();\n /// v.extend_from_array([2, 4, 6]);\n ///\n /// let all_even = !v.any(|elem: u32| elem % 2 != 0);\n /// assert(all_even);\n /// ```\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n if is_unconstrained() {\n for i in 0..self.len {\n ret |= predicate(self.storage[i]);\n }\n } else {\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 }\n ret\n }\n\n /// Creates a new vector of equal size by calling a closure on each element in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let result = vec.map(|value| value * 2);\n ///\n /// let expected = BoundedVec::from_array([2, 4, 6, 8]);\n /// assert_eq(result, expected);\n /// ```\n pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec {\n let mut ret = BoundedVec::new();\n ret.len = self.len();\n\n if is_unconstrained() {\n for i in 0..self.len() {\n ret.storage[i] = f(self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n ret.storage[i] = f(self.get_unchecked(i));\n }\n }\n }\n\n ret\n }\n\n /// Creates a new vector of equal size by calling a closure on each element\n /// in this vector, along with its index.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let result = vec.mapi(|i, value| i + value * 2);\n ///\n /// let expected = BoundedVec::from_array([2, 5, 8, 11]);\n /// assert_eq(result, expected);\n /// ```\n pub fn mapi(self, f: fn[Env](u32, T) -> U) -> BoundedVec {\n let mut ret = BoundedVec::new();\n ret.len = self.len();\n\n if is_unconstrained() {\n for i in 0..self.len() {\n ret.storage[i] = f(i, self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n ret.storage[i] = f(i, self.get_unchecked(i));\n }\n }\n }\n\n ret\n }\n\n /// Calls a closure on each element in this vector.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let mut result = BoundedVec::::new();\n /// vec.for_each(|value| result.push(value * 2));\n ///\n /// let expected = BoundedVec::from_array([2, 4, 6, 8]);\n /// assert_eq(result, expected);\n /// ```\n pub fn for_each(self, f: fn[Env](T) -> ()) {\n if is_unconstrained() {\n for i in 0..self.len() {\n f(self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n f(self.get_unchecked(i));\n }\n }\n }\n }\n\n /// Calls a closure on each element in this vector, along with its index.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n /// let mut result = BoundedVec::::new();\n /// vec.for_eachi(|i, value| result.push(i + value * 2));\n ///\n /// let expected = BoundedVec::from_array([2, 5, 8, 11]);\n /// assert_eq(result, expected);\n /// ```\n pub fn for_eachi(self, f: fn[Env](u32, T) -> ()) {\n if is_unconstrained() {\n for i in 0..self.len() {\n f(i, self.get_unchecked(i));\n }\n } else {\n for i in 0..MaxLen {\n if i < self.len() {\n f(i, self.get_unchecked(i));\n }\n }\n }\n }\n\n /// Creates a new BoundedVec from the given array and length.\n /// The given length must be less than or equal to the length of the array.\n ///\n /// This function will zero out any elements at or past index `len` of `array`.\n /// This incurs an extra runtime cost of O(MaxLen). If you are sure your array is\n /// zeroed after that index, you can use `from_parts_unchecked` to remove the extra loop.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_parts([1, 2, 3, 0], 3);\n /// assert_eq(vec.len(), 3);\n /// ```\n pub fn from_parts(mut array: [T; MaxLen], len: u32) -> Self {\n assert(len <= MaxLen);\n let zeroed = crate::mem::zeroed();\n\n if is_unconstrained() {\n for i in len..MaxLen {\n array[i] = zeroed;\n }\n } else {\n for i in 0..MaxLen {\n if i >= len {\n array[i] = zeroed;\n }\n }\n }\n\n BoundedVec { storage: array, len }\n }\n\n /// Creates a new BoundedVec from the given array and length.\n /// The given length must be less than or equal to the length of the array.\n ///\n /// This function is unsafe because it expects all elements past the `len` index\n /// of `array` to be zeroed, but does not check for this internally. Use `from_parts`\n /// for a safe version of this function which does zero out any indices past the\n /// given length. Invalidating this assumption can notably cause `BoundedVec::eq`\n /// to give incorrect results since it will check even elements past `len`.\n ///\n /// Example:\n ///\n /// ```noir\n /// let vec: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 0], 3);\n /// assert_eq(vec.len(), 3);\n ///\n /// // invalid use!\n /// let vec1: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 1], 3);\n /// let vec2: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 2], 3);\n ///\n /// // both vecs have length 3 so we'd expect them to be equal, but this\n /// // fails because elements past the length are still checked in eq\n /// assert_eq(vec1, vec2); // fails\n /// ```\n pub fn from_parts_unchecked(array: [T; MaxLen], len: u32) -> Self {\n assert(len <= MaxLen);\n BoundedVec { storage: array, len }\n }\n}\n\nimpl Eq for BoundedVec\nwhere\n T: Eq,\n{\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 if self.len == other.len {\n self.storage == other.storage\n } else {\n false\n }\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\n mod get {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test(should_fail_with = \"Attempted to read past end of BoundedVec\")]\n fn panics_when_reading_elements_past_end_of_vec() {\n let vec: BoundedVec = BoundedVec::new();\n\n let _ = vec.get(0);\n }\n\n #[test(should_fail_with = \"Attempted to read past end of BoundedVec\")]\n fn panics_when_reading_beyond_length() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n let _ = vec.get(3);\n }\n\n #[test]\n fn get_works_within_bounds() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(2), 3);\n assert_eq(vec.get(4), 5);\n }\n\n #[test]\n fn get_unchecked_works() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n assert_eq(vec.get_unchecked(0), 1);\n assert_eq(vec.get_unchecked(2), 3);\n }\n\n #[test]\n fn get_unchecked_works_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n assert_eq(vec.get_unchecked(4), 0);\n }\n }\n\n mod set {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn set_updates_values_properly() {\n let mut vec = BoundedVec::from_array([0, 0, 0, 0, 0]);\n\n vec.set(0, 42);\n assert_eq(vec.storage, [42, 0, 0, 0, 0]);\n\n vec.set(1, 43);\n assert_eq(vec.storage, [42, 43, 0, 0, 0]);\n\n vec.set(2, 44);\n assert_eq(vec.storage, [42, 43, 44, 0, 0]);\n\n vec.set(1, 10);\n assert_eq(vec.storage, [42, 10, 44, 0, 0]);\n\n vec.set(0, 0);\n assert_eq(vec.storage, [0, 10, 44, 0, 0]);\n }\n\n #[test(should_fail_with = \"Attempted to write past end of BoundedVec\")]\n fn panics_when_writing_elements_past_end_of_vec() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.set(0, 42);\n }\n\n #[test(should_fail_with = \"Attempted to write past end of BoundedVec\")]\n fn panics_when_setting_beyond_length() {\n let mut vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.set(3, 4);\n }\n\n #[test]\n fn set_unchecked_operations() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n\n vec.set_unchecked(0, 10);\n assert_eq(vec.get(0), 10);\n }\n\n #[test(should_fail_with = \"Attempted to read past end of BoundedVec\")]\n fn set_unchecked_operations_past_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n\n vec.set_unchecked(3, 40);\n assert_eq(vec.get(3), 40);\n }\n\n #[test]\n fn set_preserves_other_elements() {\n let mut vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n\n vec.set(2, 30);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 30);\n assert_eq(vec.get(3), 4);\n assert_eq(vec.get(4), 5);\n }\n }\n\n mod any {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn returns_false_if_predicate_not_satisfied() {\n let vec: BoundedVec = BoundedVec::from_array([false, false, false, false]);\n let result = vec.any(|value| value);\n\n assert(!result);\n }\n\n #[test]\n fn returns_true_if_predicate_satisfied() {\n let vec: BoundedVec = BoundedVec::from_array([false, false, true, true]);\n let result = vec.any(|value| value);\n\n assert(result);\n }\n\n #[test]\n fn returns_false_on_empty_boundedvec() {\n let vec: BoundedVec = BoundedVec::new();\n let result = vec.any(|value| value);\n\n assert(!result);\n }\n\n #[test]\n fn any_with_complex_predicates() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n\n assert(vec.any(|x| x > 3));\n assert(!vec.any(|x| x > 10));\n assert(vec.any(|x| x % 2 == 0)); // has a even number\n assert(vec.any(|x| x == 3)); // has a specific value\n }\n\n #[test]\n fn any_with_partial_vector() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n\n assert(vec.any(|x| x == 1));\n assert(vec.any(|x| x == 2));\n assert(!vec.any(|x| x == 3));\n }\n }\n\n mod map {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn applies_function_correctly() {\n // docs:start:bounded-vec-map-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|value| value * 2);\n // docs:end:bounded-vec-map-example\n let expected = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|value| (value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = vec.map(|value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn map_with_conditional_logic() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n\n let result = vec.map(|x| if x % 2 == 0 { x * 2 } else { x });\n let expected = BoundedVec::from_array([1, 4, 3, 8]);\n assert_eq(result, expected);\n }\n\n #[test]\n fn map_preserves_length() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.map(|x| x * 2);\n\n assert_eq(result.len(), vec.len());\n assert_eq(result.max_len(), vec.max_len());\n }\n\n #[test]\n fn map_on_empty_vector() {\n let vec: BoundedVec = BoundedVec::new();\n let result = vec.map(|x| x * 2);\n assert_eq(result, vec);\n assert_eq(result.len(), 0);\n assert_eq(result.max_len(), 5);\n }\n }\n\n mod mapi {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn applies_function_correctly() {\n // docs:start:bounded-vec-mapi-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.mapi(|i, value| i + value * 2);\n // docs:end:bounded-vec-mapi-example\n let expected = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = vec.mapi(|i, value| (i + value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = vec.mapi(|_, value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn mapi_with_index_branching_logic() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n\n let result = vec.mapi(|i, x| if i % 2 == 0 { x * 2 } else { x });\n let expected = BoundedVec::from_array([2, 2, 6, 4]);\n assert_eq(result, expected);\n }\n }\n\n mod for_each {\n use crate::collections::bounded_vec::BoundedVec;\n\n // map in terms of for_each\n fn for_each_map(\n input: BoundedVec,\n f: fn[Env](T) -> U,\n ) -> BoundedVec {\n let mut output = BoundedVec::::new();\n let output_ref = &mut output;\n input.for_each(|x| output_ref.push(f(x)));\n output\n }\n\n #[test]\n fn smoke_test() {\n let mut acc = 0;\n let acc_ref = &mut acc;\n // docs:start:bounded-vec-for-each-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.for_each(|value| { *acc_ref += value; });\n // docs:end:bounded-vec-for-each-example\n assert_eq(acc, 6);\n }\n\n #[test]\n fn applies_function_correctly() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_each_map(vec, |value| value * 2);\n let expected = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_each_map(vec, |value| (value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = for_each_map(vec, |value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn for_each_on_empty_vector() {\n let vec: BoundedVec = BoundedVec::new();\n let mut count = 0;\n let count_ref = &mut count;\n vec.for_each(|_| { *count_ref += 1; });\n assert_eq(count, 0);\n }\n\n #[test]\n fn for_each_with_side_effects() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n let mut seen = BoundedVec::::new();\n let seen_ref = &mut seen;\n vec.for_each(|x| seen_ref.push(x));\n assert_eq(seen, vec);\n }\n }\n\n mod for_eachi {\n use crate::collections::bounded_vec::BoundedVec;\n\n // mapi in terms of for_eachi\n fn for_eachi_mapi(\n input: BoundedVec,\n f: fn[Env](u32, T) -> U,\n ) -> BoundedVec {\n let mut output = BoundedVec::::new();\n let output_ref = &mut output;\n input.for_eachi(|i, x| output_ref.push(f(i, x)));\n output\n }\n\n #[test]\n fn smoke_test() {\n let mut acc = 0;\n let acc_ref = &mut acc;\n // docs:start:bounded-vec-for-eachi-example\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n vec.for_eachi(|i, value| { *acc_ref += i * value; });\n // docs:end:bounded-vec-for-eachi-example\n\n // 0 * 1 + 1 * 2 + 2 * 3\n assert_eq(acc, 8);\n }\n\n #[test]\n fn applies_function_correctly() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_eachi_mapi(vec, |i, value| i + value * 2);\n let expected = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn applies_function_that_changes_return_type() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]);\n let result = for_eachi_mapi(vec, |i, value| (i + value * 2) as Field);\n let expected: BoundedVec = BoundedVec::from_array([2, 5, 8, 11]);\n\n assert_eq(result, expected);\n }\n\n #[test]\n fn does_not_apply_function_past_len() {\n let vec: BoundedVec = BoundedVec::from_array([0, 1]);\n let result = for_eachi_mapi(vec, |_, value| if value == 0 { 5 } else { value });\n let expected = BoundedVec::from_array([5, 1]);\n\n assert_eq(result, expected);\n assert_eq(result.get_unchecked(2), 0);\n }\n\n #[test]\n fn for_eachi_on_empty_vector() {\n let vec: BoundedVec = BoundedVec::new();\n let mut count = 0;\n let count_ref = &mut count;\n vec.for_eachi(|_, _| { *count_ref += 1; });\n assert_eq(count, 0);\n }\n\n #[test]\n fn for_eachi_with_index_tracking() {\n let vec: BoundedVec = BoundedVec::from_array([10, 20, 30]);\n let mut indices = BoundedVec::::new();\n let indices_ref = &mut indices;\n vec.for_eachi(|i, _| indices_ref.push(i));\n\n let expected = BoundedVec::from_array([0, 1, 2]);\n assert_eq(indices, expected);\n }\n\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.get(0), 1);\n assert_eq(bounded_vec.get(1), 2);\n assert_eq(bounded_vec.get(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 #[test]\n fn from_array_preserves_order() {\n let array = [5, 3, 1, 4, 2];\n let vec: BoundedVec = BoundedVec::from_array(array);\n for i in 0..array.len() {\n assert_eq(vec.get(i), array[i]);\n }\n }\n\n #[test]\n fn from_array_with_different_types() {\n let bool_array = [true, false, true];\n let bool_vec: BoundedVec = BoundedVec::from_array(bool_array);\n assert_eq(bool_vec.len(), 3);\n assert_eq(bool_vec.get(0), true);\n assert_eq(bool_vec.get(1), false);\n }\n }\n\n mod trait_from {\n use crate::collections::bounded_vec::BoundedVec;\n use crate::convert::From;\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.get(0), 1);\n assert_eq(bounded_vec.get(1), 2);\n }\n }\n\n mod trait_eq {\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\n mod from_parts {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn from_parts() {\n // docs:start:from-parts\n let vec: BoundedVec = BoundedVec::from_parts([1, 2, 3, 0], 3);\n assert_eq(vec.len(), 3);\n\n // Any elements past the given length are zeroed out, so these\n // two BoundedVecs will be completely equal\n let vec1: BoundedVec = BoundedVec::from_parts([1, 2, 3, 1], 3);\n let vec2: BoundedVec = BoundedVec::from_parts([1, 2, 3, 2], 3);\n assert_eq(vec1, vec2);\n // docs:end:from-parts\n }\n\n #[test]\n fn from_parts_unchecked() {\n // docs:start:from-parts-unchecked\n let vec: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 0], 3);\n assert_eq(vec.len(), 3);\n\n // invalid use!\n let vec1: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 1], 3);\n let vec2: BoundedVec = BoundedVec::from_parts_unchecked([1, 2, 3, 2], 3);\n\n // both vecs have length 3 so we'd expect them to be equal, but this\n // fails because elements past the length are still checked in eq\n assert(vec1 != vec2);\n // docs:end:from-parts-unchecked\n }\n }\n\n mod push_pop {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn push_and_pop_operations() {\n let mut vec: BoundedVec = BoundedVec::new();\n\n assert_eq(vec.len(), 0);\n\n vec.push(1);\n assert_eq(vec.len(), 1);\n assert_eq(vec.get(0), 1);\n\n vec.push(2);\n assert_eq(vec.len(), 2);\n assert_eq(vec.get(1), 2);\n\n let popped = vec.pop();\n assert_eq(popped, 2);\n assert_eq(vec.len(), 1);\n\n let popped2 = vec.pop();\n assert_eq(popped2, 1);\n assert_eq(vec.len(), 0);\n }\n\n #[test(should_fail_with = \"push out of bounds\")]\n fn push_to_full_vector() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.push(2);\n vec.push(3); // should panic\n }\n\n #[test(should_fail_with = \"cannot pop from an empty vector\")]\n fn pop_from_empty_vector() {\n let mut vec: BoundedVec = BoundedVec::new();\n let _ = vec.pop(); // should panic\n }\n\n #[test]\n fn push_pop_cycle() {\n let mut vec: BoundedVec = BoundedVec::new();\n\n // push to full\n vec.push(1);\n vec.push(2);\n vec.push(3);\n assert_eq(vec.len(), 3);\n\n // pop all\n assert_eq(vec.pop(), 3);\n assert_eq(vec.pop(), 2);\n assert_eq(vec.pop(), 1);\n assert_eq(vec.len(), 0);\n\n // push again\n vec.push(4);\n assert_eq(vec.len(), 1);\n assert_eq(vec.get(0), 4);\n }\n }\n\n mod extend {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn extend_from_array() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_array([2, 3]);\n\n assert_eq(vec.len(), 3);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 3);\n }\n\n #[test]\n fn extend_from_slice() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_slice(&[2, 3]);\n\n assert_eq(vec.len(), 3);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 3);\n }\n\n #[test]\n fn extend_from_bounded_vec() {\n let mut vec1: BoundedVec = BoundedVec::new();\n let mut vec2: BoundedVec = BoundedVec::new();\n\n vec1.push(1);\n vec2.push(2);\n vec2.push(3);\n\n vec1.extend_from_bounded_vec(vec2);\n\n assert_eq(vec1.len(), 3);\n assert_eq(vec1.get(0), 1);\n assert_eq(vec1.get(1), 2);\n assert_eq(vec1.get(2), 3);\n }\n\n #[test(should_fail_with = \"extend_from_array out of bounds\")]\n fn extend_array_beyond_max_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_array([2, 3, 4]); // should panic\n }\n\n #[test(should_fail_with = \"extend_from_slice out of bounds\")]\n fn extend_slice_beyond_max_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n vec.push(1);\n vec.extend_from_slice(&[2, 3, 4]); // S]should panic\n }\n\n #[test(should_fail_with = \"extend_from_bounded_vec out of bounds\")]\n fn extend_bounded_vec_beyond_max_len() {\n let mut vec: BoundedVec = BoundedVec::new();\n let other: BoundedVec = BoundedVec::from_array([1, 2, 3, 4, 5]);\n vec.extend_from_bounded_vec(other); // should panic\n }\n\n #[test]\n fn extend_with_empty_collections() {\n let mut vec: BoundedVec = BoundedVec::new();\n let original_len = vec.len();\n\n vec.extend_from_array([]);\n assert_eq(vec.len(), original_len);\n\n vec.extend_from_slice(&[]);\n assert_eq(vec.len(), original_len);\n\n let empty: BoundedVec = BoundedVec::new();\n vec.extend_from_bounded_vec(empty);\n assert_eq(vec.len(), original_len);\n }\n }\n\n mod storage {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn storage_consistency() {\n let mut vec: BoundedVec = BoundedVec::new();\n\n // test initial storage state\n assert_eq(vec.storage(), [0, 0, 0, 0, 0]);\n\n vec.push(1);\n vec.push(2);\n\n // test storage after modifications\n assert_eq(vec.storage(), [1, 2, 0, 0, 0]);\n\n // storage doesn't change length\n assert_eq(vec.len(), 2);\n assert_eq(vec.max_len(), 5);\n }\n\n #[test]\n fn storage_after_pop() {\n let mut vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n\n let _ = vec.pop();\n // after pop, the last element should be zeroed\n assert_eq(vec.storage(), [1, 2, 0]);\n assert_eq(vec.len(), 2);\n }\n\n #[test]\n fn vector_immutable() {\n let vec: BoundedVec = BoundedVec::from_array([1, 2, 3]);\n let storage = vec.storage();\n\n assert_eq(storage, [1, 2, 3]);\n\n // Verify that the original vector is unchanged\n assert_eq(vec.len(), 3);\n assert_eq(vec.get(0), 1);\n assert_eq(vec.get(1), 2);\n assert_eq(vec.get(2), 3);\n }\n }\n}\n" - }, - "60": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/capsules/mod.nr", - "source": "use crate::oracle::capsules;\nuse protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}};\n\n/// A dynamically sized array backed by PXE's non-volatile database (called capsules). Values are persisted until\n/// deleted, so they can be e.g. stored during simulation of a transaction and later retrieved during witness\n/// generation. All values are scoped per contract address, so external contracts cannot access them.\npub struct CapsuleArray {\n contract_address: AztecAddress,\n /// The base slot is where the array length is stored in capsules. Array elements are stored in consecutive slots\n /// after the base slot. For example, with base slot 5: the length is at slot 5, the first element (index 0) is at\n /// slot 6, the second element (index 1) is at slot 7, and so on.\n base_slot: Field,\n}\n\nimpl CapsuleArray {\n /// Returns a CapsuleArray connected to a contract's capsules at a base slot. Array elements are stored in\n /// contiguous slots following the base slot, so there should be sufficient space between array base slots to\n /// accommodate elements. A reasonable strategy is to make the base slot a hash of a unique value.\n pub unconstrained fn at(contract_address: AztecAddress, base_slot: Field) -> Self {\n Self { contract_address, base_slot }\n }\n\n /// Returns the number of elements stored in the array.\n pub unconstrained fn len(self) -> u32 {\n // An uninitialized array defaults to a length of 0.\n capsules::load(self.contract_address, self.base_slot).unwrap_or(0) as u32\n }\n\n /// Stores a value at the end of the array.\n pub unconstrained fn push(self, value: T)\n where\n T: Serialize,\n {\n let current_length = self.len();\n\n // The slot corresponding to the index `current_length` is the first slot immediately after the end of the\n // array, which is where we want to place the new value.\n capsules::store(self.contract_address, self.slot_at(current_length), value);\n\n // Then we simply update the length.\n let new_length = current_length + 1;\n capsules::store(self.contract_address, self.base_slot, new_length);\n }\n\n /// Retrieves the value stored in the array at `index`. Throws if the index is out of bounds.\n pub unconstrained fn get(self, index: u32) -> T\n where\n T: Deserialize,\n {\n assert(index < self.len(), \"Attempted to read past the length of a CapsuleArray\");\n\n capsules::load(self.contract_address, self.slot_at(index)).unwrap()\n }\n\n /// Deletes the value stored in the array at `index`. Throws if the index is out of bounds.\n pub unconstrained fn remove(self, index: u32) {\n let current_length = self.len();\n assert(index < current_length, \"Attempted to delete past the length of a CapsuleArray\");\n\n // In order to be able to remove elements at arbitrary indices, we need to shift the entire contents of the\n // array past the removed element one slot backward so that we don't end up with a gap and preserve the\n // contiguous slots. We can skip this when deleting the last element however.\n if index != current_length - 1 {\n // The source and destination regions overlap, but `copy` supports this.\n capsules::copy(\n self.contract_address,\n self.slot_at(index + 1),\n self.slot_at(index),\n current_length - index - 1,\n );\n }\n\n // We can now delete the last element (which has either been copied to the slot immediately before it, or was\n // the element we meant to delete in the first place) and update the length.\n capsules::delete(self.contract_address, self.slot_at(current_length - 1));\n capsules::store(self.contract_address, self.base_slot, current_length - 1);\n }\n\n /// Iterates over the entire array, calling the callback with all values and their array index. The order in which\n /// values are processed is arbitrary.\n ///\n /// It is safe to delete the current element (and only the current element) from inside the callback via `remove`:\n /// ```noir\n /// array.for_each(|index, value| {\n /// if some_condition(value) {\n /// array.remove(index); // safe only for this index\n /// }\n /// }\n /// ```\n ///\n /// If all elements in the array need to iterated over and then removed, then using `for_each` results in optimal\n /// efficiency.\n ///\n /// It is **not** safe to push new elements into the array from inside the callback.\n pub unconstrained fn for_each(self, f: unconstrained fn[Env](u32, T) -> ())\n where\n T: Deserialize,\n {\n // Iterating over all elements is simple, but we want to do it in such a way that a) deleting the current\n // element is safe to do, and b) deleting *all* elements is optimally efficient. This is because CapsuleArrays\n // are typically used to hold pending tasks, so iterating them while clearing completed tasks (sometimes\n // unconditionally, resulting in a full clear) is a very common access pattern.\n //\n // The way we achieve this is by iterating backwards: each element can always be deleted since it won't change\n // any preceding (lower) indices, and if every element is deleted then every element will (in turn) be the last\n // element. This results in an optimal full clear since `remove` will be able to skip the `capsules::copy` call\n // to shift any elements past the deleted one (because there will be none).\n let mut i = self.len();\n while i > 0 {\n i -= 1;\n f(i, self.get(i));\n }\n }\n\n unconstrained fn slot_at(self, index: u32) -> Field {\n // Elements are stored immediately after the base slot, so we add 1 to it to compute the slot for the first\n // element.\n self.base_slot + 1 + index as Field\n }\n}\n\nmod test {\n use crate::test::helpers::test_environment::TestEnvironment;\n use super::CapsuleArray;\n\n global SLOT: Field = 1230;\n\n #[test]\n unconstrained fn empty_array() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array: CapsuleArray = CapsuleArray::at(contract_address, SLOT);\n assert_eq(array.len(), 0);\n });\n }\n\n #[test(should_fail_with = \"Attempted to read past the length of a CapsuleArray\")]\n unconstrained fn empty_array_read() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n let _: Field = array.get(0);\n });\n }\n\n #[test]\n unconstrained fn array_push() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n array.push(5);\n\n assert_eq(array.len(), 1);\n assert_eq(array.get(0), 5);\n });\n }\n\n #[test(should_fail_with = \"Attempted to read past the length of a CapsuleArray\")]\n unconstrained fn read_past_len() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n array.push(5);\n\n let _ = array.get(1);\n });\n }\n\n #[test]\n unconstrained fn array_remove_last() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(5);\n array.remove(0);\n\n assert_eq(array.len(), 0);\n });\n }\n\n #[test]\n unconstrained fn array_remove_some() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(7);\n array.push(8);\n array.push(9);\n\n assert_eq(array.len(), 3);\n assert_eq(array.get(0), 7);\n assert_eq(array.get(1), 8);\n assert_eq(array.get(2), 9);\n\n array.remove(1);\n\n assert_eq(array.len(), 2);\n assert_eq(array.get(0), 7);\n assert_eq(array.get(1), 9);\n });\n }\n\n #[test]\n unconstrained fn array_remove_all() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(7);\n array.push(8);\n array.push(9);\n\n array.remove(1);\n array.remove(1);\n array.remove(0);\n\n assert_eq(array.len(), 0);\n });\n }\n\n #[test]\n unconstrained fn for_each_called_with_all_elements() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n // We store all values that we were called with and check that all (value, index) tuples are present. Note that\n // we do not care about the order in which each tuple was passed to the closure.\n let called_with = &mut BoundedVec::<(u32, Field), 3>::new();\n array.for_each(|index, value| { called_with.push((index, value)); });\n\n assert_eq(called_with.len(), 3);\n assert(called_with.any(|(index, value)| (index == 0) & (value == 4)));\n assert(called_with.any(|(index, value)| (index == 1) & (value == 5)));\n assert(called_with.any(|(index, value)| (index == 2) & (value == 6)));\n });\n }\n\n #[test]\n unconstrained fn for_each_remove_some() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n array.for_each(|index, _| {\n if index == 1 {\n array.remove(index);\n }\n });\n\n assert_eq(array.len(), 2);\n assert_eq(array.get(0), 4);\n assert_eq(array.get(1), 6);\n });\n }\n\n #[test]\n unconstrained fn for_each_remove_all() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n array.for_each(|index, _| { array.remove(index); });\n\n assert_eq(array.len(), 0);\n });\n }\n\n #[test]\n unconstrained fn for_each_remove_all_no_copy() {\n let env = TestEnvironment::new();\n env.private_context(|context| {\n let contract_address = context.this_address();\n let array = CapsuleArray::at(contract_address, SLOT);\n\n array.push(4);\n array.push(5);\n array.push(6);\n\n // We test that the utilityCopyCapsule was never called, which is the expensive operation we want to avoid.\n let mock = std::test::OracleMock::mock(\"utilityCopyCapsule\");\n\n array.for_each(|index, _| { array.remove(index); });\n\n assert_eq(mock.times_called(), 0);\n });\n }\n}\n" - }, - "61": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr", - "source": "use dep::protocol_types::{\n abis::function_selector::FunctionSelector,\n address::AztecAddress,\n traits::{Deserialize, ToField},\n};\n\nuse crate::context::{gas::GasOpts, private_context::PrivateContext, public_context::PublicContext};\nuse crate::hash::{hash_args, hash_calldata};\nuse crate::oracle::execution_cache;\n\npub trait CallInterface {\n fn get_args(self) -> [Field];\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\n// PrivateCallInterface\n\npub struct PrivateCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n return_type: T,\n is_static: bool,\n}\n\nimpl PrivateCallInterface\nwhere\n T: Deserialize,\n{\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n is_static: bool,\n ) -> Self {\n let args_hash = hash_args(args);\n Self {\n target_contract,\n selector,\n name,\n args_hash,\n args,\n return_type: std::mem::zeroed(),\n is_static,\n }\n }\n\n /// Makes the call to this private function.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n /// This enables contracts to interact with each other while maintaining\n /// privacy. This \"composability\" of private contract functions is a key\n /// feature of the Aztec network.\n ///\n /// If a user's transaction includes multiple private function calls, then\n /// by the design of Aztec, the following information will remain private[1]:\n /// - The function selectors and contract addresses of all private function\n /// calls will remain private, so an observer of the public mempool will\n /// not be able to look at a tx and deduce which private functions have\n /// been executed.\n /// - The arguments and return values of all private function calls will\n /// remain private.\n /// - The person who initiated the tx will remain private.\n /// - The notes and nullifiers and private logs that are emitted by all\n /// private function calls will (if designed well) not leak any user\n /// secrets, nor leak which functions have been executed.\n ///\n /// [1] Caveats: Some of these privacy guarantees depend on how app\n /// developers design their smart contracts. Some actions _can_ leak\n /// information, such as:\n /// - Calling an internal public function.\n /// - Calling a public function and not setting msg_sender to Option::none\n /// (see https://github.com/AztecProtocol/aztec-packages/pull/16433)\n /// - Calling any public function will always leak details about the nature\n /// of the transaction, so devs should be careful in their contract\n /// designs. If it can be done in a private function, then that will give\n /// the best privacy.\n /// - Not padding the side-effects of a tx to some standardised, uniform\n /// size. The kernel circuits can take hints to pad side-effects, so a\n /// wallet should be able to request for a particular amount of padding.\n /// Wallets should ideally agree on some standard.\n /// - Padding should include:\n /// - Padding the lengths of note & nullifier arrays\n /// - Padding private logs with random fields, up to some standardised\n /// size.\n /// See also: https://docs.aztec.network/developers/reference/considerations/privacy_considerations\n ///\n /// # Advanced\n /// * The call is added to the private call stack and executed by kernel\n /// circuits after this function completes\n /// * The called function can modify its own contract's private state\n /// * Side effects from the called function are included in this transaction\n /// * The call inherits the current transaction's context and gas limits\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n pub fn call(self, context: &mut PrivateContext) -> T {\n execution_cache::store(self.args, self.args_hash);\n let returns_hash = context.call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n false,\n );\n\n // If T is () (i.e. if the function does not return anything) then `get_preimage` will constrain that the\n // returns hash is empty as per the protocol rules.\n returns_hash.get_preimage()\n }\n\n /// Makes a _read-only_ call to this private function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state, emit L2->L1 messages, nor emit events. Any nested\n /// calls are constrained to also be staticcalls.\n ///\n /// See `call` for more general info on private function calls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n pub fn view(self, context: &mut PrivateContext) -> T {\n execution_cache::store(self.args, self.args_hash);\n let returns_hash = context.call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n true,\n );\n // If T is () (i.e. if the function does not return anything) then `get_preimage` will constrain that the\n // returns hash is empty as per the protocol rules.\n returns_hash.get_preimage()\n }\n}\n\nimpl CallInterface for PrivateCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// PrivateStaticCallInterface\n\npub struct PrivateStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n return_type: T,\n is_static: bool,\n}\n\nimpl PrivateStaticCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n ) -> Self {\n let args_hash = hash_args(args);\n Self {\n target_contract,\n selector,\n name,\n args_hash,\n args,\n return_type: std::mem::zeroed(),\n is_static: true,\n }\n }\n\n /// Makes a read-only call to this private function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state, emit L2->L1 messages, nor emit events. Any nested\n /// calls are constrained to also be staticcalls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n pub fn view(self, context: &mut PrivateContext) -> T\n where\n T: Deserialize,\n {\n execution_cache::store(self.args, self.args_hash);\n let returns = context.call_private_function_with_args_hash(\n self.target_contract,\n self.selector,\n self.args_hash,\n true,\n );\n returns.get_preimage()\n }\n}\n\nimpl CallInterface for PrivateStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// PublicCallInterface\n\npub struct PublicCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n return_type: T,\n is_static: bool,\n}\n\nimpl PublicCallInterface\nwhere\n T: Deserialize,\n{\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n is_static: bool,\n ) -> Self {\n Self {\n target_contract,\n selector,\n name,\n args,\n gas_opts: GasOpts::default(),\n return_type: std::mem::zeroed(),\n is_static,\n }\n }\n\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n /// Makes the call to this public function.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `context` - The PublicContext -- made magically available to the body\n /// of every #[public] function as `context`, through the\n /// #[public] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n pub unconstrained fn call(self, context: &mut PublicContext) -> T {\n let returns = context.call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n // If T is () (i.e. if the function does not return anything) then `as_array` will constrain that `returns` has\n // a length of 0 (since that is ()'s deserialization length).\n Deserialize::deserialize(returns.as_array())\n }\n\n /// Makes a read-only call to this public function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state or emit events. Any nested calls are constrained to\n /// also be staticcalls.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `context` - The PublicContext -- made magically available to the body\n /// of every #[public] function as `context`, through the\n /// #[public] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n pub unconstrained fn view(self, context: &mut PublicContext) -> T {\n let returns = context.static_call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n // If T is () (i.e. if the function does not return anything) then `as_array` will constrain that `returns` has\n // a length of 0 (since that is ()'s deserialization length).\n Deserialize::deserialize(returns.as_array())\n }\n\n /// Enqueues a call to this public function, to be executed later.\n ///\n /// Unlike private functions which execute immediately on the user's device,\n /// public function calls are \"enqueued\" and executed some time later by a\n /// block proposer.\n ///\n /// This means a public function cannot return any values back to a private\n /// function, because by the time the public function is being executed,\n /// the private function which called it has already completed execution.\n /// (In fact, the private function has been executed and proven, along with\n /// all other private function calls of the user's tx. A single proof of the\n /// tx has been submitted to the Aztec network, and some time later a\n /// proposer has picked the tx up from the mempool and begun executing all\n /// of the enqueued public functions).\n ///\n /// # Privacy warning\n /// Enqueueing a public function call is an inherently leaky action.\n /// Many interesting applications will require some interaction with public\n /// state, but smart contract developers should try to use public function\n /// calls sparingly, and carefully.\n /// _Internal_ public function calls are especially leaky, because they\n /// completely leak which private contract made the call.\n /// See also: https://docs.aztec.network/developers/reference/considerations/privacy_considerations\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n pub fn enqueue(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n false,\n )\n }\n\n /// Enqueues a read-only call to this public function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state, emit L2->L1 messages, nor emit events. Any nested\n /// calls are constrained to also be staticcalls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n true,\n )\n }\n\n /// Enqueues a call to this public function, and designates it to be the\n /// teardown function for this tx. Only one teardown function call can be\n /// made by a tx.\n ///\n /// Niche function: Only wallet developers and paymaster contract developers\n /// (aka Fee-payment contracts) will need to make use of this function.\n ///\n /// Aztec supports a three-phase execution model: setup, app logic, teardown.\n /// The phases exist to enable a fee payer to take on the risk of paying\n /// a transaction fee, safe in the knowledge that their payment (in whatever\n /// token or method the user chooses) will succeed, regardless of whether\n /// the app logic will succeed. The \"setup\" phase ensures the fee payer\n /// has sufficient balance to pay the proposer their fees.\n /// The teardown phase is primarily intended to: calculate exactly\n /// how much the user owes, based on gas consumption, and refund the user\n /// any change.\n ///\n /// Note: in some cases, the cost of refunding the user (i.e. DA costs of\n /// tx side-effects) might exceed the refund amount. For app logic with\n /// fairly stable and predictable gas consumption, a material refund amount\n /// is unlikely. For app logic with unpredictable gas consumption, a\n /// refund might be important to the user (e.g. if a hefty function reverts\n /// very early). Wallet/FPC/Paymaster developers should be mindful of this.\n ///\n /// See `enqueue` for more information about enqueuing public function calls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n pub fn set_as_teardown(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.set_public_teardown_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n false,\n )\n }\n}\n\nimpl CallInterface for PublicCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// PublicStaticCallInterface\n\npub struct PublicStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n return_type: T,\n is_static: bool,\n gas_opts: GasOpts,\n}\n\nimpl PublicStaticCallInterface\nwhere\n T: Deserialize,\n{\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n ) -> Self {\n Self {\n target_contract,\n selector,\n name,\n args,\n return_type: std::mem::zeroed(),\n is_static: true,\n gas_opts: GasOpts::default(),\n }\n }\n\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n /// Makes the read-only call to this public function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state or emit events. Any nested calls are constrained to\n /// also be staticcalls.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `context` - The PublicContext -- made magically available to the body\n /// of every #[public] function as `context`, through the\n /// #[public] annotation's macro.\n ///\n /// # Returns\n /// * `T` - Whatever data the called function has returned.\n ///\n pub unconstrained fn view(self, context: &mut PublicContext) -> T {\n let returns = context.static_call_public_function(\n self.target_contract,\n self.selector,\n self.args,\n self.gas_opts,\n );\n Deserialize::deserialize(returns.as_array())\n }\n\n /// Enqueues a read-only call to this public function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state, emit L2->L1 messages, nor emit events. Any nested\n /// calls are constrained to also be staticcalls.\n ///\n /// # Arguments\n /// * `context` - The PrivateContext -- made magically available to the body\n /// of every #[private] function as `context`, through the\n /// #[private] annotation's macro.\n ///\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n let calldata = self.args.push_front(self.selector.to_field());\n let calldata_hash = hash_calldata(calldata);\n execution_cache::store(calldata, calldata_hash);\n context.call_public_function_with_calldata_hash(\n self.target_contract,\n calldata_hash,\n /*static=*/\n true,\n )\n }\n}\n\nimpl CallInterface for PublicStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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\n// UtilityCallInterface\n\npub struct UtilityCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n return_type: T,\n}\n\nimpl CallInterface for UtilityCallInterface {\n fn get_args(self) -> [Field] {\n self.args\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 false\n }\n}\n\nimpl UtilityCallInterface {\n pub fn new(\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n ) -> Self {\n let args_hash = hash_args(args);\n Self { target_contract, selector, name, args_hash, args, return_type: std::mem::zeroed() }\n }\n\n pub fn get_args(self) -> [Field] {\n self.args\n }\n\n pub fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n pub fn get_name(self) -> str {\n self.name\n }\n\n pub fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n}\n" - }, - "68": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/context/private_context.nr", - "source": "use crate::{\n context::{inputs::PrivateContextInputs, returns_hash::ReturnsHash},\n hash::{ArgsHasher, hash_args_array, hash_calldata_array},\n keys::constants::{NULLIFIER_INDEX, NUM_KEY_TYPES, OUTGOING_INDEX, sk_generators},\n messaging::process_l1_to_l2_message,\n oracle::{\n block_header::get_block_header_at,\n call_private_function::call_private_function_internal,\n enqueue_public_function_call::{\n notify_enqueued_public_function_call, notify_set_min_revertible_side_effect_counter,\n notify_set_public_teardown_function_call,\n },\n execution_cache,\n key_validation_request::get_key_validation_request,\n logs::notify_created_contract_class_log,\n notes::{notify_created_nullifier, notify_nullified_note},\n },\n};\nuse dep::protocol_types::{\n abis::{\n block_header::BlockHeader,\n call_context::CallContext,\n function_selector::FunctionSelector,\n gas_settings::GasSettings,\n log_hash::LogHash,\n note_hash::NoteHash,\n nullifier::Nullifier,\n private_call_request::PrivateCallRequest,\n private_circuit_public_inputs::PrivateCircuitPublicInputs,\n private_log::{PrivateLog, PrivateLogData},\n public_call_request::PublicCallRequest,\n read_request::ReadRequest,\n side_effect::Counted,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n },\n address::{AztecAddress, EthAddress},\n constants::{\n CONTRACT_CLASS_LOG_SIZE_IN_FIELDS, MAX_CONTRACT_CLASS_LOGS_PER_CALL,\n MAX_ENQUEUED_CALLS_PER_CALL, MAX_INCLUDE_BY_TIMESTAMP_DURATION,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASHES_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PRIVATE_LOGS_PER_CALL,\n PRIVATE_LOG_SIZE_IN_FIELDS,\n },\n hash::poseidon2_hash,\n messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Empty, Hash, ToField},\n utils::arrays::{ClaimedLengthArray, trimmed_array_length_hint},\n};\n\n/// # PrivateContext\n///\n/// The **main interface** between a #[private] function and the Aztec blockchain.\n///\n/// An instance of the PrivateContext is initialized automatically at the outset\n/// of every private function, within the #[private] macro, so you'll never\n/// need to consciously instantiate this yourself.\n///\n/// The instance is always named `context`, and it is always be available within\n/// the body of every #[private] function in your smart contract.\n///\n/// > For those used to \"vanilla\" Noir, it might be jarring to have access to\n/// > `context` without seeing a declaration `let context = PrivateContext::new(...)`\n/// > within the body of your function. This is just a consequence of using\n/// > macros to tidy-up verbose boilerplate. You can use `nargo expand` to\n/// > expand all macros, if you dare.\n///\n/// Typical usage for a smart contract developer will be to call getter\n/// methods of the PrivateContext.\n///\n/// _Pushing_ data and requests to the context is mostly handled within\n/// aztec-nr's own functions, so typically a smart contract developer won't\n/// need to call any setter methods directly.\n///\n/// > Advanced users might occasionally wish to push data to the context\n/// > directly for lower-level control. If you find yourself doing this, please\n/// > open an issue on GitHub to describe your use case: it might be that\n/// > new functionality should be added to aztec-nr.\n///\n/// ## Responsibilities\n/// - Exposes contextual data to a private function:\n/// - Data relating to how this private function was called.\n/// - msg_sender\n/// - this_address - (the contract address of the private function being\n/// executed)\n/// - See `CallContext` for more data.\n/// - Data relating to the transaction in which this private function is\n/// being executed.\n/// - chain_id\n/// - version\n/// - gas_settings\n/// - Provides state access:\n/// - Access to the \"Anchor block\" header.\n/// Recall, a private function cannot read from the \"current\" block header,\n/// but must read from some historical block header, because as soon as\n/// private function execution begins (asynchronously, on a user's device),\n/// the public state of the chain (the \"current state\") will have progressed\n/// forward. We call this reference the \"Anchor block\".\n/// See `BlockHeader`.\n/// - Enables consumption of L1->L2 messages.\n/// - Enables calls to functions of other smart contracts:\n/// - Private function calls\n/// - Enqueueing of public function call requests\n/// (Since public functions are executed at a later time, by a block\n/// proposer, we say they are \"enqueued\").\n/// - Writes data to the blockchain:\n/// - New notes\n/// - New nullifiers\n/// - Private logs (for sending encrypted note contents or encrypted events)\n/// - New L2->L1 messages.\n/// - Provides args to the private function (handled by the #[private] macro).\n/// - Returns the return values of this private function (handled by the\n/// #[private] macro).\n/// - Makes Key Validation Requests.\n/// - Private functions are not allowed to see master secret keys, because we\n/// do not trust them. They are instead given \"app-siloed\" secret keys with\n/// a claim that they relate to a master public key. They can then request\n/// validation of this claim, by making a \"key validation request\" to the\n/// protocol's kernel circuits (which _are_ allowed to see certain master\n/// secret keys).\n///\n/// ## Advanced Responsibilities\n///\n/// - Ultimately, the PrivateContext is responsible for constructing the\n/// PrivateCircuitPublicInputs of the private function being executed.\n/// All private functions on Aztec must have public inputs which adhere\n/// to the rigid layout of the PrivateCircuitPublicInputs, in order to be\n/// compatible with the protocol's kernel circuits.\n/// A well-known misnomer:\n/// - \"public inputs\" contain both inputs and outputs of this function.\n/// - By \"outputs\" we mean a lot more side-effects than just the\n/// \"return values\" of the function.\n/// - Most of the so-called \"public inputs\" are kept _private_, and never leak\n/// to the outside world, because they are 'swallowed' by the protocol's\n/// kernel circuits before the tx is sent to the network. Only the\n/// following are exposed to the outside world:\n/// - New note_hashes\n/// - New nullifiers\n/// - New private logs\n/// - New L2->L1 messages\n/// - New enqueued public function call requests\n/// All the above-listed arrays of side-effects can be padded by the\n/// user's wallet (through instructions to the kernel circuits, via the\n/// PXE) to obscure their true lengths.\n///\n/// ## Syntax Justification\n///\n/// Both user-defined functions _and_ most functions in aztec-nr need access to\n/// the PrivateContext instance to read/write data. This is why you'll see the\n/// arguably-ugly pervasiveness of the \"context\" throughout your smart contract\n/// and the aztec-nr library.\n/// For example, `&mut context` is prevalent. In some languages, you can access\n/// and mutate a global variable (such as a PrivateContext instance) from a\n/// function without polluting the function's parameters. With Noir, a function\n/// must explicitly pass control of a mutable variable to another function, by\n/// reference. Since many functions in aztec-nr need to be able to push new data\n/// to the PrivateContext, they need to be handed a mutable reference _to_ the\n/// context as a parameter.\n/// For example, `Context` is prevalent as a generic parameter, to give better\n/// type safety at compile time. Many `aztec-nr` functions don't make sense if\n/// they're called in a particular runtime (private, public or utility), and so\n/// are intentionally only implemented over certain\n/// [Private|Public|Utility]Context structs. This gives smart contract\n/// developers a much faster feedback loop if they're making a mistake, as an\n/// error will be thrown by the LSP or when they compile their contract.\n///\n#[derive(Eq)]\npub struct PrivateContext {\n // docs:start:private-context\n pub inputs: PrivateContextInputs,\n pub side_effect_counter: u32,\n\n pub min_revertible_side_effect_counter: u32,\n pub is_fee_payer: bool,\n\n pub args_hash: Field,\n pub return_hash: Field,\n\n pub include_by_timestamp: u64,\n\n pub note_hash_read_requests: BoundedVec,\n pub nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n pub note_hashes: BoundedVec,\n pub nullifiers: BoundedVec,\n\n pub private_call_requests: BoundedVec,\n pub public_call_requests: BoundedVec, MAX_ENQUEUED_CALLS_PER_CALL>,\n pub public_teardown_call_request: PublicCallRequest,\n pub l2_to_l1_msgs: BoundedVec, MAX_L2_TO_L1_MSGS_PER_CALL>,\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 pub historical_header: BlockHeader,\n\n pub private_logs: BoundedVec,\n pub contract_class_logs_hashes: BoundedVec, MAX_CONTRACT_CLASS_LOGS_PER_CALL>,\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 pub last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n let max_allowed_include_by_timestamp =\n inputs.historical_header.global_variables.timestamp + MAX_INCLUDE_BY_TIMESTAMP_DURATION;\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 include_by_timestamp: max_allowed_include_by_timestamp,\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n note_hashes: BoundedVec::new(),\n nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_requests: BoundedVec::new(),\n public_teardown_call_request: PublicCallRequest::empty(),\n l2_to_l1_msgs: BoundedVec::new(),\n private_logs: BoundedVec::new(),\n contract_class_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES],\n }\n }\n\n /// Returns the contract address that initiated this function call.\n ///\n /// This is similar to `msg.sender` in Solidity (hence the name).\n ///\n /// Important Note: Since Aztec doesn't have a concept of an EoA (\n /// Externally-owned Account), the msg_sender is \"undefined\" for the first\n /// function call of every transaction. A value of `-1` is returned in such\n /// cases.\n /// The first function call of a tx is likely to be a call to the user's\n /// account contract, so this quirk will most often be handled by account\n /// contract developers.\n ///\n /// TODO(https://github.com/AztecProtocol/aztec-packages/issues/14025) - we\n /// are considering making msg_sender: Option, since\n /// a returned value of `Option:none` will be clearer to developers.\n ///\n /// # Returns\n /// * `AztecAddress` - The address of the smart contract that called\n /// this function (be it an app contract or a user's account contract).\n /// Returns `-1` for the first function call of the tx.\n ///\n pub fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n /// Returns the contract address of the current function being executed.\n ///\n /// This is equivalent to `address(this)` in Solidity (hence the name).\n /// Use this to identify the current contract's address, commonly needed for\n /// access control or when interacting with other contracts.\n ///\n /// # Returns\n /// * `AztecAddress` - The contract address of the current function being\n /// executed.\n ///\n pub fn this_address(self) -> AztecAddress {\n self.inputs.call_context.contract_address\n }\n\n /// Returns the chain ID of the current network.\n ///\n /// This is similar to `block.chainid` in Solidity. Returns the unique\n /// identifier for the blockchain network this transaction is executing on.\n ///\n /// Helps prevent cross-chain replay attacks. Useful if implementing\n /// multi-chain contract logic.\n ///\n /// # Returns\n /// * `Field` - The chain ID as a field element\n ///\n pub fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n /// Returns the Aztec protocol version that this transaction is executing\n /// under. Different versions may have different rules, opcodes, or\n /// cryptographic primitives.\n ///\n /// This is similar to how Ethereum has different EVM versions.\n ///\n /// Useful for forward/backward compatibility checks\n ///\n /// Not to be confused with contract versions; this is the protocol version.\n ///\n /// # Returns\n /// * `Field` - The protocol version as a field element\n ///\n pub fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n /// Returns the gas settings for the current transaction.\n ///\n /// This provides information about gas limits and pricing for the\n /// transaction, similar to `tx.gasprice` and gas limits in Ethereum.\n /// However, Aztec has a more sophisticated gas model with separate\n /// accounting for L2 computation and data availability (DA) costs.\n ///\n /// # Returns\n /// * `GasSettings` - Struct containing gas limits and fee information\n ///\n pub fn gas_settings(self) -> GasSettings {\n self.inputs.tx_context.gas_settings\n }\n\n /// Returns the function selector of the currently executing function.\n ///\n /// Low-level function: Ordinarily, smart contract developers will not need\n /// to access this.\n ///\n /// This is similar to `msg.sig` in Solidity, which returns the first 4\n /// bytes of the function signature. In Aztec, the selector uniquely\n /// identifies which function within the contract is being called.\n ///\n /// # Returns\n /// * `FunctionSelector` - The 4-byte function identifier\n ///\n /// # Advanced\n /// Only #[private] functions have a function selector as a protocol-\n /// enshrined concept. The function selectors of private functions are\n /// baked into the preimage of the contract address, and are used by the\n /// protocol's kernel circuits to identify each private function and ensure\n /// the correct one is being executed.\n ///\n /// Used internally for function dispatch and call verification.\n ///\n pub fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n /// Returns the hash of the arguments passed to the current function.\n ///\n /// Very low-level function: You shouldn't need to call this. The #[private]\n /// macro calls this, and it makes the arguments neatly available to the\n /// body of your private function.\n ///\n /// # Returns\n /// * `Field` - Hash of the function arguments\n ///\n /// # Advanced\n /// * Arguments are hashed to reduce proof size and verification time\n /// * Enables efficient argument passing in recursive function calls\n /// * The hash can be used to retrieve the original arguments from the PXE.\n ///\n pub fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n /// Pushes a new note_hash to the Aztec blockchain's global Note Hash Tree\n /// (a state tree).\n ///\n /// A note_hash is a commitment to a piece of private state.\n ///\n /// Low-level function: Ordinarily, smart contract developers will not need\n /// to manually call this. Aztec-nr's state variables (see `../state_vars/`)\n /// are designed to understand when to create and push new note hashes.\n ///\n /// # Arguments\n /// * `note_hash` - The new note_hash.\n ///\n /// # Advanced\n /// From here, the protocol's kernel circuits will take over and insert the\n /// note_hash into the protocol's \"note hash tree\" (in the Base Rollup\n /// circuit).\n /// Before insertion, the protocol will:\n /// - \"Silo\" the `note_hash` with the contract address of this function,\n /// to yield a `siloed_note_hash`. This prevents state collisions\n /// between different smart contracts.\n /// - Ensure uniqueness of the `siloed_note_hash`, to prevent Faerie-Gold\n /// attacks, by hashing the `siloed_note_hash` with a unique value, to\n /// yield a `unique_siloed_note_hash` (see the protocol spec for more).\n ///\n /// In addition to calling this function, aztec-nr provides the contents\n /// of the newly-created note to the PXE, via the `notify_created_note`\n /// oracle.\n ///\n /// > Advanced users might occasionally wish to push data to the context\n /// > directly for lower-level control. If you find yourself doing this,\n /// > please open an issue on GitHub to describe your use case: it might be\n /// > that new functionality should be added to aztec-nr.\n ///\n pub fn push_note_hash(&mut self, note_hash: Field) {\n self.note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n /// Pushes a new nullifier to the Aztec blockchain's global Nullifier Tree\n /// (a state tree).\n ///\n /// See also: `push_nullifier_for_note_hash`.\n ///\n /// Low-level function: Ordinarily, smart contract developers will not need\n /// to manually call this. Aztec-nr's state variables (see `../state_vars/`)\n /// are designed to understand when to create and push new nullifiers.\n ///\n /// A nullifier can only be emitted once. Duplicate nullifier insertions are\n /// rejected by the protocol.\n ///\n /// Generally, a nullifier is emitted to prevent an action from happening\n /// more than once, in such a way that the action cannot be linked (by an\n /// observer of the blockchain) to any earlier transactions.\n ///\n /// I.e. a nullifier is a random-looking, but deterministic record of a\n /// private, one-time action, which does not leak what action has been\n /// taken, and which preserves the property of \"tx unlinkability\".\n ///\n /// Usually, a nullifier will be emitted to \"spend\" a note (a piece of\n /// private state), without revealing which specific note is being spent.\n ///\n /// (Important: in such cases, use the below `push_nullifier_for_note_hash`).\n ///\n /// Sometimes, a nullifier might be emitted completely unrelated to any\n /// notes. Examples include initialization of a new contract; initialization\n /// of a PrivateMutable, or signalling in Semaphore-like applications.\n /// This `push_nullifier` function serves such use cases.\n ///\n /// # Arguments\n /// * `nullifier`\n ///\n /// # Advanced\n /// From here, the protocol's kernel circuits will take over and insert the\n /// nullifier into the protocol's \"nullifier tree\" (in the Base Rollup\n /// circuit).\n /// Before insertion, the protocol will:\n /// - \"Silo\" the `nullifier` with the contract address of this function,\n /// to yield a `siloed_nullifier`. This prevents state collisions\n /// between different smart contracts.\n /// - Ensure the `siloed_nullifier` is unique (the nullifier tree is an\n /// indexed merkle tree which supports efficient non-membership proofs).\n ///\n pub fn push_nullifier(&mut self, nullifier: Field) {\n notify_created_nullifier(nullifier);\n self.nullifiers.push(\n Nullifier { value: nullifier, note_hash: 0, counter: self.next_counter() },\n );\n }\n\n /// Pushes a nullifier that corresponds to a specific note hash.\n ///\n /// Low-level function: Ordinarily, smart contract developers will not need\n /// to manually call this. Aztec-nr's state variables (see `../state_vars/`)\n /// are designed to understand when to create and push new nullifiers.\n ///\n /// This is a specialized version of `push_nullifier` that links a nullifier\n /// to the specific note hash it's nullifying. This is the most common\n /// usage pattern for nullifiers.\n /// See `push_nullifier` for more explanation on nullifiers.\n ///\n /// # Arguments\n /// * `nullifier`\n /// * `nullified_note_hash` - The note hash of the note being nullified\n ///\n /// # Advanced\n /// Important: usage of this function doesn't mean that the world will _see_\n /// that this nullifier relates to the given nullified_note_hash (as that\n /// would violate \"tx unlinkability\"); it simply informs the user's PXE\n /// about the relationship (via `notify_nullified_note`). The PXE can then\n /// use this information to feed hints to the kernel circuits for\n /// \"squashing\" purposes: If a note is nullified during the same tx which\n /// created it, we can \"squash\" (delete) the note and nullifier (and any\n /// private logs associated with the note), to save on data emission costs.\n ///\n pub fn push_nullifier_for_note_hash(&mut self, nullifier: Field, nullified_note_hash: Field) {\n let nullifier_counter = self.next_counter();\n notify_nullified_note(nullifier, nullified_note_hash, nullifier_counter);\n self.nullifiers.push(\n Nullifier {\n value: nullifier,\n note_hash: nullified_note_hash,\n counter: nullifier_counter,\n },\n );\n }\n\n /// Returns the anchor block header - the historical block header that this\n /// private function is reading from.\n ///\n /// A private function CANNOT read from the \"current\" block header,\n /// but must read from some historical block header, because as soon as\n /// private function execution begins (asynchronously, on a user's device),\n /// the public state of the chain (the \"current state\") will have progressed\n /// forward.\n ///\n /// # Returns\n /// * `BlockHeader` - The anchor block header.\n ///\n /// # Advanced\n /// * All private functions of a tx read from the same anchor block header.\n /// * The protocol asserts that the `include_by_timestamp` of every tx\n /// is at most 24 hours beyond the timestamp of the tx's chosen anchor\n /// block header. This enables the network's nodes to safely prune old txs\n /// from the mempool. Therefore, the chosen block header _must_ be one\n /// from within the last 24 hours.\n ///\n pub fn get_block_header(self) -> BlockHeader {\n self.historical_header\n }\n\n /// Returns the header of any historical block at or before the anchor\n /// block.\n ///\n /// This enables private contracts to access information from even older\n /// blocks than the anchor block header.\n ///\n /// Useful for time-based contract logic that needs to compare against\n /// multiple historical points.\n ///\n /// # Arguments\n /// * `block_number` - The block number to retrieve (must be <= anchor\n /// block number)\n ///\n /// # Returns\n /// * `BlockHeader` - The header of the requested historical block\n ///\n /// # Advanced\n /// This function uses an oracle to fetch block header data from the user's\n /// PXE. Depending on how much blockchain data the user's PXE has been set\n /// up to store, this might require a query from the PXE to another Aztec\n /// node to get the data.\n /// > This is generally true of all oracle getters (see `../oracle`).\n ///\n /// Each block header gets hashed and stored as a leaf in the protocol's\n /// Archive Tree. In fact, the i-th block header gets stored at the i-th\n /// leaf index of the Archive Tree. Behind the scenes, this\n /// `get_block_header_at` function will add Archive Tree merkle-membership\n /// constraints (~3k) to your smart contract function's circuit, to prove\n /// existence of the block header in the Archive Tree.\n ///\n /// Note: we don't do any caching, so avoid making duplicate calls for the\n /// same block header, because each call will add duplicate constraints.\n ///\n /// Calling this function is more expensive (constraint-wise) than getting\n /// the anchor block header (via `get_block_header`). This is because the\n /// anchor block's merkle membership proof is handled by Aztec's protocol\n /// circuits, and is only performed once for the entire tx because all\n /// private functions of a tx share a common anchor block header. Therefore,\n /// the cost (constraint-wise) of calling `get_block_header` is effectively\n /// free.\n ///\n pub fn get_block_header_at(self, block_number: u32) -> BlockHeader {\n get_block_header_at(block_number, self)\n }\n\n /// Sets the hash of the return values for this private function.\n ///\n /// Very low-level function: this is called by the #[private] macro.\n ///\n /// # Arguments\n /// * `returns_hasher` - A hasher containing the return values to hash\n ///\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n self.return_hash = returns_hasher.hash();\n execution_cache::store(returns_hasher.fields, self.return_hash);\n }\n\n /// Builds the PrivateCircuitPublicInputs for this private function, to\n /// ensure compatibility with the protocol's kernel circuits.\n ///\n /// Very low-level function: This function is automatically called by the\n /// #[private] macro.\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 include_by_timestamp: self.include_by_timestamp,\n note_hash_read_requests: ClaimedLengthArray::from_bounded_vec(\n self.note_hash_read_requests,\n ),\n nullifier_read_requests: ClaimedLengthArray::from_bounded_vec(\n self.nullifier_read_requests,\n ),\n key_validation_requests_and_generators: ClaimedLengthArray::from_bounded_vec(\n self.key_validation_requests_and_generators,\n ),\n note_hashes: ClaimedLengthArray::from_bounded_vec(self.note_hashes),\n nullifiers: ClaimedLengthArray::from_bounded_vec(self.nullifiers),\n private_call_requests: ClaimedLengthArray::from_bounded_vec(self.private_call_requests),\n public_call_requests: ClaimedLengthArray::from_bounded_vec(self.public_call_requests),\n public_teardown_call_request: self.public_teardown_call_request,\n l2_to_l1_msgs: ClaimedLengthArray::from_bounded_vec(self.l2_to_l1_msgs),\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n private_logs: ClaimedLengthArray::from_bounded_vec(self.private_logs),\n contract_class_logs_hashes: ClaimedLengthArray::from_bounded_vec(\n self.contract_class_logs_hashes,\n ),\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context,\n }\n }\n\n /// Designates this contract as the fee payer for the transaction.\n ///\n /// Unlike Ethereum, where the transaction sender always pays fees, Aztec\n /// allows any contract to voluntarily pay transaction fees. This enables\n /// patterns like sponsored transactions or fee abstraction where users\n /// don't need to hold fee-juice themselves. (Fee juice is a fee-paying\n /// asset for Aztec).\n ///\n /// Only one contract per transaction can declare itself as the fee payer,\n /// and it must have sufficient fee-juice balance (>= the gas limits\n /// specified in the TxContext) by the time we reach the public setup phase\n /// of the tx.\n ///\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\n \"Setting {0} as fee payer\",\n [self.this_address().to_field()],\n );\n self.is_fee_payer = true;\n }\n\n /// Declares the end of the \"setup phase\" of this tx.\n ///\n /// Only one function per tx can declare the end of the setup phase.\n ///\n /// Niche function: Only wallet developers and paymaster contract developers\n /// (aka Fee-payment contracts) will need to make use of this function.\n ///\n /// Aztec supports a three-phase execution model: setup, app logic, teardown.\n /// The phases exist to enable a fee payer to take on the risk of paying\n /// a transaction fee, safe in the knowledge that their payment (in whatever\n /// token or method the user chooses) will succeed, regardless of whether\n /// the app logic will succeed. The \"setup\" phase enables such a payment to\n /// be made, because the setup phase _cannot revert_: a reverting function\n /// within the setup phase would result in an invalid block which cannot\n /// be proven. Any side-effects generated during that phase are guaranteed\n /// to be inserted into Aztec's state trees (except for squashed notes &\n /// nullifiers, of course).\n ///\n /// Even though the end of the setup phase is declared within a private\n /// function, you might have noticed that _public_ functions can also\n /// execute within the setup phase. This is because any public function\n /// calls which were enqueued _within the setup phase_ by a private\n /// function are considered part of the setup phase.\n ///\n /// # Advanced\n /// * Sets the minimum revertible side effect counter of this tx to be the\n /// PrivateContext's _current_ side effect counter.\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 notify_set_min_revertible_side_effect_counter(self.min_revertible_side_effect_counter);\n }\n\n /// Sets a deadline (an \"include-by timestamp\") for when this transaction\n /// must be included in a block.\n ///\n /// Other functions in this tx might call this setter with differing\n /// values for the include-by timestamp. To ensure that all functions'\n /// deadlines are met, the _minimum_ of all these include-by timestamps will\n /// be exposed when this tx is submitted to the network.\n ///\n /// If the transaction is not included in a block by its include-by\n /// timestamp, it becomes invalid and it will never be included.\n ///\n /// This expiry timestamp is publicly visible. See the \"Advanced\" section\n /// for privacy concerns.\n ///\n /// # Arguments\n /// * `include_by_timestamp` - Unix timestamp (seconds) deadline for inclusion.\n /// The include-by timestamp of this tx will be\n /// _at most_ the timestamp specified.\n ///\n /// # Advanced\n /// * If multiple functions set differing `include_by_timestamp`s, the\n /// kernel circuits will set it to be the _minimum_ of the two. This\n /// ensures the tx expiry requirements of all functions in the tx are met.\n /// * Rollup circuits will reject expired txs.\n /// * The protocol enforces that all transactions must be included within\n /// 24 hours of their chosen anchor block's timestamp, to enable safe\n /// mempool pruning.\n /// * The DelayedPublicMutable design makes heavy use of this functionality,\n /// to enable private functions to read public state.\n /// * A sophisticated Wallet should cleverly set an include-by timestamp\n /// to improve the privacy of the user and the network as a whole.\n /// For example, if a contract interaction sets include-by to some\n /// publicly-known value (e.g. the time when a contract upgrades), then\n /// the wallet might wish to set an even lower one to avoid revealing that\n /// this tx is interacting with said contract.\n /// Ideally, all wallets should standardise on an approach in order to\n /// provide users with a large anonymity set -- although the exact apprach\n /// will need to be discussed. Wallets that deviate from a standard might\n /// accidentally reveal which wallet each transaction originates from.\n ///\n // docs:start:include-by-timestamp\n pub fn set_include_by_timestamp(&mut self, include_by_timestamp: u64) {\n // docs:end:include-by-timestamp\n self.include_by_timestamp = std::cmp::min(self.include_by_timestamp, include_by_timestamp);\n }\n\n /// Makes a request to the protocol's kernel circuit to ensure a note_hash\n /// actually exists.\n ///\n /// \"Read requests\" are used to prove that a note hash exists without\n /// revealing which specific note was read.\n ///\n /// This can be used to prove existence of both settled notes (created in\n /// prior transactions) and transient notes (created in the current\n /// transaction).\n /// If you need to prove existence of a settled note _at a specific block\n /// number_, use `note_inclusion::prove_note_inclusion`.\n ///\n /// Low-level function. Ordinarily, smart contract developers will not need\n /// to call this directly. Aztec-nr's state variables (see `../state_vars/`)\n /// are designed to understand when to create and push new note_hash read\n /// requests.\n ///\n /// # Arguments\n /// * `note_hash` - The note hash to read and verify\n ///\n /// # Advanced\n /// In \"traditional\" circuits for non-Aztec privacy applications, the merkle\n /// membership proofs to check existence of a note are performed _within_\n /// the application circuit.\n ///\n /// All Aztec private functions have access to the following constraint\n /// optimisation:\n /// In cases where the note being read was created earlier in the same tx,\n /// the note wouldn't yet exist in the Note Hash Tree, so a hard-coded\n /// merkle membership check which then gets ignored would be a waste of\n /// constraints.\n /// Instead, we can send read requests for all notes to the protocol's\n /// kernel circuits, where we can conditionally assess which notes actually\n /// need merkle membership proofs, and select an appropriately-sized\n /// kernel circuit.\n ///\n /// For \"settled notes\" (which already existed in the Note Hash Tree of the\n /// anchor block (i.e. before the tx began)), the kernel does a merkle\n /// membership check.\n ///\n /// For \"pending notes\" (which were created earlier in _this_ tx), the\n /// kernel will check that the note existed _before_ this read request was\n /// made, by checking the side-effect counters of the note_hash and this\n /// read request.\n ///\n /// This approach improves latency between writes and reads:\n /// a function can read a note which was created earlier in the tx (rather\n /// than performing the read in a later tx, after waiting for the earlier tx\n /// to be included, to ensure the note is included in the tree).\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 /// Requests to read a specific nullifier from the nullifier tree.\n ///\n /// Nullifier read requests are used to prove that a nullifier exists without\n /// revealing which specific nullifier preimage was read.\n ///\n /// This can be used to prove existence of both settled nullifiers (created in\n /// prior transactions) and transient nullifiers (created in the current\n /// transaction).\n /// If you need to prove existence of a settled nullifier _at a specific block\n /// number_, use `nullifier_inclusion::prove_nullifier_inclusion`.\n ///\n /// Low-level function. Ordinarily, smart contract developers will not need\n /// to call this directly. Aztec-nr's state variables (see `../state_vars/`)\n /// are designed to understand when to create and push new nullifier read\n /// requests.\n ///\n /// # Arguments\n /// * `nullifier` - The nullifier to read and verify\n ///\n /// # Advanced\n /// This approach improves latency between writes and reads:\n /// a function can read a nullifier which was created earlier in the tx\n /// (rather than performing the read in a later tx, after waiting for the\n /// earlier tx to be included, to ensure the note is included in the tree).\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 /// Requests the app-siloed nullifier secret key (nsk_app) for the given\n /// (hashed) master nullifier public key (npk_m), from the user's PXE.\n ///\n /// Advanced function: Only needed if you're designing your own notes and/or\n /// nullifiers.\n ///\n /// Contracts are not allowed to compute nullifiers for other contracts, as\n /// that would let them read parts of their private state. Because of this,\n /// a contract is only given an \"app-siloed secret key\", which is\n /// constructed by hashing the user's master nullifier secret key with the\n /// contract's address.\n /// However, because contracts cannot be trusted with a user's master\n /// nullifier secret key (because we don't know which contracts are honest\n /// or malicious), the PXE refuses to provide any master secret keys to\n /// any app smart contract function. This means app functions are unable to\n /// prove that the derivation of an app-siloed nullifier secret key has been\n /// computed correctly. Instead, an app function can request to the kernel\n /// (via `request_nsk_app`) that it validates the siloed derivation, since\n /// the kernel has been vetted to not leak any master secret keys.\n ///\n /// A common nullification scheme is to inject a nullifier secret key into\n /// the preimage of a nullifier, to make the nullifier deterministic but\n /// random-looking. This function enables that flow.\n ///\n /// # Arguments\n /// * `npk_m_hash` - A hash of the master nullifier public key of the user\n /// whose PXE is executing this function.\n ///\n /// # Returns\n /// * The app-siloed nullifier secret key that corresponds to the given\n /// `npk_m_hash`.\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 /// Requests the app-siloed nullifier secret key (nsk_app) for the given\n /// (hashed) master nullifier public key (npk_m), from the user's PXE.\n ///\n /// See `request_nsk_app` and `request_sk_app` for more info.\n ///\n /// The intention of the \"outgoing\" keypair is to provide a second secret\n /// key for all of a user's outgoing activity (i.e. for notes that a user\n /// creates, as opposed to notes that a user receives from others). The\n /// separation of incoming and outgoing data was a distinction made by\n /// zcash, with the intention of enabling a user to optionally share with a\n /// 3rd party a controlled view of only incoming or outgoing notes.\n /// Similar functionality of sharing select data can be achieved with\n /// offchain zero-knowledge proofs. It is up to an app developer whether\n /// they choose to make use of a user's outgoing keypair within their\n /// application logic, or instead simply use the same keypair (the address\n /// keypair (which is effectively the same as the \"incooming\" keypair)) for\n /// all incoming & outgoing messages to a user.\n ///\n /// Currently, all of the exposed encryption functions in aztec-nr ignore\n /// the outgoing viewing keys, and instead encrypt all note logs and event\n /// logs to a user's address public key.\n ///\n /// # Arguments\n /// * `ovpk_m_hash` - Hash of the outgoing viewing public key master\n ///\n /// # Returns\n /// * The application-specific outgoing viewing secret key\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 /// Pushes a Key Validation Request to the kernel.\n ///\n /// Private functions are not allowed to see a user's master secret keys,\n /// because we do not trust them. They are instead given \"app-siloed\" secret\n /// keys with a claim that they relate to a master public key.\n /// They can then request validation of this claim, by making a \"key\n /// validation request\" to the protocol's kernel circuits (which _are_\n /// allowed to see certain master secret keys).\n ///\n /// When a Key Validation Request tuple of (sk_app, Pk_m, app_address) is\n /// submitted to the kernel, it will perform the following derivations\n /// to validate the relationship between the claimed sk_app and the user's\n /// Pk_m:\n ///\n /// (sk_m) ----> * G ----> Pk_m\n /// | |\n /// v We use the kernel to prove this\n /// h(sk_m, app_address) | sk_app-Pk_m relationship, because app\n /// | circuits must not be trusted to see sk_m.\n /// v |\n /// sk_app - - - - - - - - -\n ///\n /// The function is named \"request_\" instead of \"get_\" to remind the user\n /// that a Key Validation Request will be emitted to the kernel.\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 as u32].unwrap_or(\n KeyValidationRequest::empty(),\n );\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\n // Typically we'd validate keys by showing that they are the preimage of `pk_m_hash`, but that'd require\n // the oracle returning the master secret keys, which could cause malicious contracts to leak it or learn\n // about secrets from other contracts. We therefore silo secret keys, and rely on the private kernel to\n // validate that we siloed secret key corresponds to correct siloing of the master secret key that hashes\n // to `pk_m_hash`.\n\n // Safety: Kernels verify that the key validation request is valid and below we verify that a request\n // for the correct public key has been received.\n let request = unsafe { get_key_validation_request(pk_m_hash, key_index) };\n assert_eq(request.pk_m.hash(), pk_m_hash, \"Obtained invalid key validation request\");\n\n self.key_validation_requests_and_generators.push(\n KeyValidationRequestAndGenerator {\n request,\n sk_app_generator: sk_generators[key_index as u32],\n },\n );\n self.last_key_validation_requests[key_index as u32] = Option::some(request);\n request.sk_app\n }\n }\n\n /// Sends an \"L2 -> L1 message\" from this function (Aztec, L2) to a smart\n /// contract on Ethereum (L1). L1 contracts which are designed to\n /// send/receive messages to/from Aztec are called \"Portal Contracts\".\n ///\n /// Common use cases include withdrawals, cross-chain asset transfers, and\n /// triggering L1 actions based on L2 state changes.\n ///\n /// The message will be inserted into an Aztec \"Outbox\" contract on L1,\n /// when this transaction's block is proposed to L1.\n /// Sending the message will not result in any immediate state changes in\n /// the target portal contract. The message will need to be manually\n /// consumed from the Outbox through a separate Ethereum transaction: a user\n /// will need to call a function of the portal contract -- a function\n /// specifically designed to make a call to the Outbox to consume the\n /// message.\n /// The message will only be available for consumption once the _epoch_\n /// proof has been submitted. Given that there are multiple Aztec blocks\n /// within an epoch, it might take some time for this epoch proof to be\n /// submitted -- especially if the block was near the start of an epoch.\n ///\n /// # Arguments\n /// * `recipient` - Ethereum address that will receive the message\n /// * `content` - Message content (32 bytes as a Field element).\n /// This content has a very specific layout.\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 };\n self.l2_to_l1_msgs.push(message.count(self.next_counter()));\n }\n\n /// Consumes a message sent from Ethereum (L1) to Aztec (L2).\n ///\n /// Common use cases include token bridging, cross-chain governance, and\n /// triggering L2 actions based on L1 events.\n ///\n /// Use this function if you only want the message to ever be \"referred to\"\n /// once. Once consumed using this method, the message cannot be consumed\n /// again, because a nullifier is emitted.\n /// If your use case wants for the message to be read unlimited times, then\n /// you can always read any historic message from the L1-to-L2 messages tree;\n /// messages never technically get deleted from that tree.\n ///\n /// The message will first be inserted into an Aztec \"Inbox\" smart contract\n /// on L1.\n /// Sending the message will not result in any immediate state changes in\n /// the target L2 contract. The message will need to be manually\n /// consumed by the target contract through a separate Aztec transaction.\n /// The message will not be available for consumption immediately. Messages\n /// get copied over from the L1 Inbox to L2 by the next Proposer in batches.\n /// So you will need to wait until the messages are copied before you can\n /// consume them.\n ///\n /// # Arguments\n /// * `content` - The message content that was sent from L1\n /// * `secret` - Secret value used for message privacy (if needed)\n /// * `sender` - Ethereum address that sent the message\n /// * `leaf_index` - Index of the message in the L1-to-L2 message tree\n ///\n /// # Advanced\n /// Validates message existence in the L1-to-L2 message tree and nullifies\n /// the message to prevent double-consumption.\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(\n &mut self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field,\n ) {\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 leaf_index,\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_nullifier(nullifier)\n }\n // docs:end:consume_l1_to_l2_message\n\n /// Emits a private log (an array of Fields) that will be published to an\n /// Ethereum blob.\n ///\n /// Private logs are intended for the broadcasting of ciphertexts: that is,\n /// encrypted events or encrypted note contents.\n /// Since the data in the logs is meant to be _encrypted_, private_logs are\n /// broadcast to publicly-visible Ethereum blobs.\n /// The intended recipients of such encrypted messages can then discover and\n /// decrypt these encrypted logs using their viewing secret key.\n /// (See `../messages/discovery` for more details).\n ///\n /// Important note: This function DOES NOT _do_ any encryption of the input\n /// `log` fields. This function blindly publishes whatever input `log` data\n /// is fed into it, so the caller of this function should have already\n /// performed the encryption, and the `log` should be the result of that\n /// encryption.\n ///\n /// The protocol does not dictate what encryption scheme should be used:\n /// a smart contract developer can choose whatever encryption scheme they\n /// like.\n /// Aztec-nr includes some off-the-shelf encryption libraries that\n /// developers might wish to use, for convenience. These libraries not only\n /// encrypt a plaintext (to produce a ciphertext); they also prepend the\n /// ciphertext with a `tag` and `ephemeral public key` for easier message\n /// discovery. This is a very dense topic, and we will be writing more\n /// libraries and docs soon.\n ///\n /// > Currently, AES128 CBC encryption is the main scheme included in\n /// > aztec.nr.\n /// > We are currently making significant changes to the interfaces of the\n /// > encryption library.\n ///\n /// In some niche use cases, an app might be tempted to publish\n /// _un-encrypted_ data via a private log, because _public logs_ are not\n /// available to private functions. Be warned that emitting public data via\n /// private logs is strongly discouraged, and is considered a \"privacy\n /// anti-pattern\", because it reveals identifiable information about _which_\n /// function has been executed. A tx which leaks such information does not\n /// contribute to the privacy set of the network.\n ///\n /// * Unlike `emit_raw_note_log`, this log is not tied to any specific note\n ///\n /// # Arguments\n /// * `log` - The log data that will be publicly broadcast (so make sure\n /// it's already been encrypted before you call this function).\n /// Private logs are bounded in size (PRIVATE_LOG_SIZE_IN_FIELDS), to\n /// encourage all logs from all smart contracts look identical.\n /// * `length` - The actual length of the `log` (measured in number of\n /// Fields). Although the input log has a max size of\n /// PRIVATE_LOG_SIZE_IN_FIELDS, the latter values of the array might all\n /// be 0's for small logs. This `length` should reflect the trimmed length\n /// of the array. The protocol's kernel circuits can then append random\n /// fields as \"padding\" after the `length`, so that the logs of this\n /// smart contract look indistinguishable from (the same length as) the\n /// logs of all other applications. It's up to wallets how much padding\n /// to apply, so ideally all wallets should agree on standards for this.\n ///\n /// # Advanced\n ///\n pub fn emit_private_log(&mut self, log: [Field; PRIVATE_LOG_SIZE_IN_FIELDS], length: u32) {\n let counter = self.next_counter();\n let private_log =\n PrivateLogData { log: PrivateLog::new(log, length), note_hash_counter: 0, counter };\n self.private_logs.push(private_log);\n }\n\n // TODO: rename.\n /// Emits a private log that is explicitly tied to a newly-emitted note_hash,\n /// to convey to the kernel: \"this log relates to this note\".\n ///\n /// This linkage is important in case the note gets squashed (due to being\n /// read later in this same tx), since we can then squash the log as well.\n ///\n /// See `emit_private_log` for more info about private log emission.\n ///\n /// # Arguments\n /// * `log` - The log data as an array of Field elements\n /// * `length` - The actual length of the `log` (measured in number of\n /// Fields).\n /// * `note_hash_counter` - The side-effect counter that was assigned to the\n /// new note_hash when it was pushed to this\n // `PrivateContext`.\n ///\n /// Important: If your application logic requires the log to always be\n /// emitted regardless of note squashing, consider using `emit_private_log`\n /// instead, or emitting additional events.\n ///\n pub fn emit_raw_note_log(\n &mut self,\n log: [Field; PRIVATE_LOG_SIZE_IN_FIELDS],\n length: u32,\n note_hash_counter: u32,\n ) {\n let counter = self.next_counter();\n let private_log =\n PrivateLogData { log: PrivateLog::new(log, length), note_hash_counter, counter };\n self.private_logs.push(private_log);\n }\n\n pub fn emit_contract_class_log(&mut self, log: [Field; N]) {\n let contract_address = self.this_address();\n let counter = self.next_counter();\n\n let log_to_emit: [Field; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS] =\n log.concat([0; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS - N]);\n // Note: the length is not always N, it is the number of fields we want to broadcast, omitting trailing zeros to save blob space.\n // Safety: The below length is constrained in the base rollup, which will make sure that all the fields beyond length are zero.\n let length = unsafe { trimmed_array_length_hint(log_to_emit) };\n // We hash the entire padded log to ensure a user cannot pass a shorter length and so emit incorrect shorter bytecode.\n let log_hash = poseidon2_hash(log_to_emit);\n // Safety: the below only exists to broadcast the raw log, so we can provide it to the base rollup later to be constrained.\n unsafe {\n notify_created_contract_class_log(contract_address, log_to_emit, length, counter);\n }\n\n self.contract_class_logs_hashes.push(LogHash { value: log_hash, length: length }.count(\n counter,\n ));\n }\n\n /// Calls a private function on another contract (or the same contract).\n ///\n /// Very low-level function.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n /// * `args` - Array of arguments to pass to the called function\n ///\n /// # Returns\n /// * `ReturnsHash` - Hash of the called function's return values. Use\n /// `.get_preimage()` to extract the actual return values.\n ///\n /// This enables contracts to interact with each other while maintaining\n /// privacy. This \"composability\" of private contract functions is a key\n /// feature of the Aztec network.\n ///\n /// If a user's transaction includes multiple private function calls, then\n /// by the design of Aztec, the following information will remain private[1]:\n /// - The function selectors and contract addresses of all private function\n /// calls will remain private, so an observer of the public mempool will\n /// not be able to look at a tx and deduce which private functions have\n /// been executed.\n /// - The arguments and return values of all private function calls will\n /// remain private.\n /// - The person who initiated the tx will remain private.\n /// - The notes and nullifiers and private logs that are emitted by all\n /// private function calls will (if designed well) not leak any user\n /// secrets, nor leak which functions have been executed.\n ///\n /// [1] Caveats: Some of these privacy guarantees depend on how app\n /// developers design their smart contracts. Some actions _can_ leak\n /// information, such as:\n /// - Calling an internal public function.\n /// - Calling a public function and not setting msg_sender to Option::none\n /// (feature not built yet - see github).\n /// - Calling any public function will always leak details about the nature\n /// of the transaction, so devs should be careful in their contract\n /// designs. If it can be done in a private function, then that will give\n /// the best privacy.\n /// - Not padding the side-effects of a tx to some standardised, uniform\n /// size. The kernel circuits can take hints to pad side-effects, so a\n /// wallet should be able to request for a particular amount of padding.\n /// Wallets should ideally agree on some standard.\n /// - Padding should include:\n /// - Padding the lengths of note & nullifier arrays\n /// - Padding private logs with random fields, up to some standardised\n /// size.\n /// See also: https://docs.aztec.network/developers/reference/considerations/privacy_considerations\n ///\n /// # Advanced\n /// * The call is added to the private call stack and executed by kernel\n /// circuits after this function completes\n /// * The called function can modify its own contract's private state\n /// * Side effects from the called function are included in this transaction\n /// * The call inherits the current transaction's context and gas limits\n ///\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ArgsCount],\n ) -> ReturnsHash {\n let args_hash = hash_args_array(args);\n execution_cache::store(args, args_hash);\n self.call_private_function_with_args_hash(\n contract_address,\n function_selector,\n args_hash,\n false,\n )\n }\n\n /// Makes a read-only call to a private function on another contract.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state or emit events. Any nested calls are constrained to\n /// also be staticcalls.\n ///\n /// See `call_private_function` for more general info on private function\n /// calls.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract to call\n /// * `function_selector` - 4-byte identifier of the function to call\n /// * `args` - Array of arguments to pass to the called function\n ///\n /// # Returns\n /// * `ReturnsHash` - Hash of the called function's return values. Use\n /// `.get_preimage()` to extract the actual return values.\n ///\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ArgsCount],\n ) -> ReturnsHash {\n let args_hash = hash_args_array(args);\n execution_cache::store(args, args_hash);\n self.call_private_function_with_args_hash(\n contract_address,\n function_selector,\n args_hash,\n true,\n )\n }\n\n /// Calls a private function that takes no arguments.\n ///\n /// This is a convenience function for calling private functions that don't\n /// require any input parameters. It's equivalent to `call_private_function`\n /// but slightly more efficient to use when no arguments are needed.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n ///\n /// # Returns\n /// * `ReturnsHash` - Hash of the called function's return values. Use\n /// `.get_preimage()` to extract the actual return values.\n ///\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n ) -> ReturnsHash {\n self.call_private_function_with_args_hash(contract_address, function_selector, 0, false)\n }\n\n /// Makes a read-only call to a private function which takes no arguments.\n ///\n /// This combines the optimisation of `call_private_function_no_args` with\n /// the safety of `static_call_private_function`.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n ///\n /// # Returns\n /// * `ReturnsHash` - Hash of the called function's return values. Use\n /// `.get_preimage()` to extract the actual return values.\n ///\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n ) -> ReturnsHash {\n self.call_private_function_with_args_hash(contract_address, function_selector, 0, true)\n }\n\n /// Low-level private function call.\n ///\n /// This is the underlying implementation used by all other private function\n /// call methods. Instead of taking raw arguments, it accepts a\n /// hash of the arguments.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n /// * `args_hash` - Pre-computed hash of the function arguments\n /// * `is_static_call` - Whether this should be a read-only call\n ///\n /// # Returns\n /// * `ReturnsHash` - Hash of the called function's return values\n ///\n pub fn call_private_function_with_args_hash(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n ) -> ReturnsHash {\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\n // Safety: The oracle simulates the private call and returns the value of the side effects counter after\n // execution of the call (which means that end_side_effect_counter - start_side_effect_counter is\n // the number of side effects that took place), along with the hash of the return values. We validate these\n // by requesting a private kernel iteration in which the return values are constrained to hash\n // to `returns_hash` and the side effects counter to increment from start to end.\n let (end_side_effect_counter, returns_hash) = unsafe {\n call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n )\n };\n\n self.private_call_requests.push(\n PrivateCallRequest {\n call_context: CallContext {\n msg_sender: self.this_address(),\n contract_address,\n function_selector,\n is_static_call,\n },\n args_hash,\n returns_hash,\n start_side_effect_counter,\n end_side_effect_counter,\n },\n );\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 // 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 self.side_effect_counter = end_side_effect_counter + 1; // TODO: call `next_counter` instead, for consistency\n ReturnsHash::new(returns_hash)\n }\n\n /// Enqueues a call to a public function to be executed later.\n ///\n /// Unlike private functions which execute immediately on the user's device,\n /// public function calls are \"enqueued\" and executed some time later by a\n /// block proposer.\n ///\n /// This means a public function cannot return any values back to a private\n /// function, because by the time the public function is being executed,\n /// the private function which called it has already completed execution.\n /// (In fact, the private function has been executed and proven, along with\n /// all other private function calls of the user's tx. A single proof of the\n /// tx has been submitted to the Aztec network, and some time later a\n /// proposer has picked the tx up from the mempool and begun executing all\n /// of the enqueued public functions).\n ///\n /// # Privacy warning\n /// Enqueueing a public function call is an inherently leaky action.\n /// Many interesting applications will require some interaction with public\n /// state, but smart contract developers should try to use public function\n /// calls sparingly, and carefully.\n /// _Internal_ public function calls are especially leaky, because they\n /// completely leak which private contract made the call.\n /// See also: https://docs.aztec.network/developers/reference/considerations/privacy_considerations\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n /// * `args` - Array of arguments to pass to the public function\n ///\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ArgsCount],\n ) {\n let calldata = [function_selector.to_field()].concat(args);\n let calldata_hash = hash_calldata_array(calldata);\n execution_cache::store(calldata, calldata_hash);\n self.call_public_function_with_calldata_hash(contract_address, calldata_hash, false)\n }\n\n /// Enqueues a read-only call to a public function.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state or emit events. Any nested calls are constrained to\n /// also be staticcalls.\n ///\n /// See also `call_public_function` for more important information about\n /// making private -> public function calls.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n /// * `args` - Array of arguments to pass to the public function\n ///\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ArgsCount],\n ) {\n let calldata = [function_selector.to_field()].concat(args);\n let calldata_hash = hash_calldata_array(calldata);\n execution_cache::store(calldata, calldata_hash);\n self.call_public_function_with_calldata_hash(contract_address, calldata_hash, true)\n }\n\n /// Enqueues a call to a public function that takes no arguments.\n ///\n /// This is an optimisation for calling public functions that don't\n /// take any input parameters. It's otherwise equivalent to\n /// `call_public_function`.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n ///\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n ) {\n let calldata_hash = hash_calldata_array([function_selector.to_field()]);\n self.call_public_function_with_calldata_hash(contract_address, calldata_hash, false)\n }\n\n /// Enqueues a read-only call to a public function with no arguments.\n ///\n /// This combines the optimisation of `call_public_function_no_args` with\n /// the safety of `static_call_public_function`.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `function_selector` - 4-byte identifier of the function to call\n ///\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n ) {\n let calldata_hash = hash_calldata_array([function_selector.to_field()]);\n self.call_public_function_with_calldata_hash(contract_address, calldata_hash, true)\n }\n\n /// Low-level public function call.\n ///\n /// This is the underlying implementation used by all other public function\n /// call methods. Instead of taking raw arguments, it accepts a\n /// hash of the arguments.\n ///\n /// Advanced function: Most developers should use `call_public_function`\n /// or `static_call_public_function` instead. This function is exposed for\n /// performance optimization and advanced use cases.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the function\n /// * `calldata_hash` - Hash of the function calldata\n /// * `is_static_call` - Whether this should be a read-only call\n ///\n pub fn call_public_function_with_calldata_hash(\n &mut self,\n contract_address: AztecAddress,\n calldata_hash: Field,\n is_static_call: bool,\n ) {\n let counter = self.next_counter();\n\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n\n notify_enqueued_public_function_call(\n contract_address,\n calldata_hash,\n counter,\n is_static_call,\n );\n\n let call_request = PublicCallRequest {\n msg_sender: self.this_address(),\n contract_address,\n is_static_call,\n calldata_hash,\n };\n\n self.public_call_requests.push(Counted::new(call_request, counter));\n }\n\n /// Enqueues a public function call, and designates it to be the teardown\n /// function for this tx. Only one teardown function call can be made by a\n /// tx.\n ///\n /// Niche function: Only wallet developers and paymaster contract developers\n /// (aka Fee-payment contracts) will need to make use of this function.\n ///\n /// Aztec supports a three-phase execution model: setup, app logic, teardown.\n /// The phases exist to enable a fee payer to take on the risk of paying\n /// a transaction fee, safe in the knowledge that their payment (in whatever\n /// token or method the user chooses) will succeed, regardless of whether\n /// the app logic will succeed. The \"setup\" phase ensures the fee payer\n /// has sufficient balance to pay the proposer their fees.\n /// The teardown phase is primarily intended to: calculate exactly\n /// how much the user owes, based on gas consumption, and refund the user\n /// any change.\n ///\n /// Note: in some cases, the cost of refunding the user (i.e. DA costs of\n /// tx side-effects) might exceed the refund amount. For app logic with\n /// fairly stable and predictable gas consumption, a material refund amount\n /// is unlikely. For app logic with unpredictable gas consumption, a\n /// refund might be important to the user (e.g. if a heft function reverts\n /// very early). Wallet/FPC/Paymaster developers should be mindful of this.\n ///\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ArgsCount],\n ) {\n let calldata = [function_selector.to_field()].concat(args);\n let calldata_hash = hash_calldata_array(calldata);\n execution_cache::store(calldata, calldata_hash);\n self.set_public_teardown_function_with_calldata_hash(contract_address, calldata_hash, false)\n }\n\n /// Low-level function to set the public teardown function.\n ///\n /// This is the underlying implementation for setting the teardown function\n /// call that will execute at the end of the transaction. Instead of taking\n /// raw arguments, it accepts a hash of the arguments.\n ///\n /// Advanced function: Most developers should use\n /// `set_public_teardown_function` instead.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract containing the teardown\n /// function\n /// * `calldata_hash` - Hash of the function calldata\n /// * `is_static_call` - Whether this should be a read-only call\n ///\n pub fn set_public_teardown_function_with_calldata_hash(\n &mut self,\n contract_address: AztecAddress,\n calldata_hash: Field,\n is_static_call: bool,\n ) {\n let counter = self.next_counter();\n\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n\n notify_set_public_teardown_function_call(\n contract_address,\n calldata_hash,\n counter,\n is_static_call,\n );\n\n self.public_teardown_call_request = PublicCallRequest {\n msg_sender: self.this_address(),\n contract_address,\n is_static_call,\n calldata_hash,\n };\n }\n\n /// Increments the side-effect counter.\n ///\n /// Very low-level function.\n ///\n /// # Advanced\n ///\n /// Every side-effect of a private function is given a \"side-effect counter\",\n /// based on when it is created. This PrivateContext is in charge of\n /// assigning the counters.\n ///\n /// The reason we have side-effect counters is complicated. Consider this\n /// illustrative pseudocode of inter-contract function calls:\n /// ```\n /// contract A {\n /// let x = 5; // pseudocode for storage var x.\n /// fn a1 {\n /// read x; // value: 5, counter: 1.\n /// x = x + 1;\n /// write x; // value: 6, counter: 2.\n ///\n /// B.b(); // start_counter: 2, end_counter: 4\n ///\n /// read x; // value: 36, counter: 5.\n /// x = x + 1;\n /// write x; // value: 37, counter: 6.\n /// }\n ///\n /// fn a2 {\n /// read x; // value: 6, counter: 3.\n /// x = x * x;\n /// write x; // value: 36, counter: 4.\n /// }\n /// }\n ///\n /// contract B {\n /// fn b() {\n /// A.a2();\n /// }\n /// }\n /// ```\n ///\n /// Suppose a1 is the first function called. The comments show the execution\n /// counter of each side-effect, and what the new value of `x` is.\n ///\n /// These (private) functions are processed by Aztec's kernel circuits in an\n /// order that is different from execution order:\n /// All of A.a1 is proven before B.b is proven, before A.a2 is proven.\n /// So when we're in the 2nd execution frame of A.a1 (after the call to\n /// B.b), the circuit needs to justify why x went from being `6` to `36`.\n /// But the circuit doesn't know why, and given the order of proving, the\n /// kernel hasn't _seen_ a value of 36 get written yet.\n /// The kernel needs to track big arrays of all side-effects of all\n /// private functions in a tx. Then, as it recurses and processes B.b(), it\n /// will eventually see a value of 36 get written.\n ///\n /// Suppose side-effect counters weren't exposed:\n /// The kernel would only see this ordering (in order of proof verification):\n /// [ A.a1.read, A.a1.write, A.a1.read, A.a1.write, A.a2.read, A.a2.write ]\n /// [ 5, 6, 36, 37, 6, 36 ]\n /// The kernel wouldn't know _when_ B.b() was called within A.a1(), because\n /// it can't see what's going on within an app circuit. So the kernel\n /// wouldn't know that the ordering of reads and writes should actually be:\n /// [ A.a1.read, A.a1.write, A.a2.read, A.a2.write, A.a1.read, A.a1.write ]\n /// [ 5, 6, 6, 36, 36, 37 ]\n ///\n /// And so, we introduced side-effect counters: every private function must\n /// assign side-effect counters alongside every side-effect that it emits,\n /// and also expose to the kernel the counters that it started and ended\n /// with.\n /// This gives the kernel enough information to arrange all side-effects in\n /// the correct order.\n /// It can then catch (for example) if a function tries to read state\n /// before it has been written (e.g. if A.a2() maliciously tried to read\n /// a value of x=37) (e.g. if A.a1() maliciously tried to read x=6).\n ///\n /// If a malicious app contract _lies_ and does not count correctly:\n /// - It cannot lie about its start and end counters because the kernel\n /// will catch this.\n /// - It _could_ lie about its intermediate counters:\n /// - 1. It could not increment its side-effects correctly\n /// - 2. It could label its side-effects with counters outside of its\n /// start and end counters' range.\n /// The kernel will catch 2.\n /// The kernel will not catch 1., but this would only cause corruption\n /// to the private state of the malicious contract, and not any other\n /// contracts (because a contract can only modify its own state). If\n /// a \"good\" contract is given _read access_ to a maliciously-counting\n /// contract (via an external getter function, or by reading historic\n /// state from the archive tree directly), and they then make state\n /// changes to their _own_ state accordingly, that could be dangerous.\n /// Developers should be mindful not to trust the claimed innards of\n /// external contracts unless they have audited/vetted the contracts\n /// including vetting the side-effect counter incrementation.\n /// This is a similar paradigm to Ethereum smart contract development:\n /// you must vet external contracts that your contract relies upon, and\n /// you must not make any presumptions about their claimed behaviour.\n /// (Hopefully if a contract imports a version of aztec-nr, we will get\n /// contract verification tooling that can validate the authenticity\n /// of the imported aztec-nr package, and hence infer that the side-\n /// effect counting will be correct, without having to re-audit such logic\n /// for every contract).\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 include_by_timestamp: 0,\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n note_hashes: BoundedVec::new(),\n nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_requests: BoundedVec::new(),\n public_teardown_call_request: PublicCallRequest::empty(),\n l2_to_l1_msgs: BoundedVec::new(),\n historical_header: BlockHeader::empty(),\n private_logs: BoundedVec::new(),\n contract_class_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES],\n }\n }\n}\n" - }, - "69": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/context/public_context.nr", - "source": "use crate::context::gas::GasOpts;\nuse crate::hash::{\n compute_l1_to_l2_message_hash, compute_l1_to_l2_message_nullifier, compute_secret_hash,\n};\nuse dep::protocol_types::abis::function_selector::FunctionSelector;\nuse dep::protocol_types::address::{AztecAddress, EthAddress};\nuse dep::protocol_types::constants::MAX_U32_VALUE;\nuse dep::protocol_types::traits::{Empty, FromField, Packable, Serialize, ToField};\n\n/// # PublicContext\n///\n/// The **main interface** between a #[public] function and the Aztec blockchain.\n///\n/// An instance of the PublicContext is initialized automatically at the outset\n/// of every public function, within the #[public] macro, so you'll never\n/// need to consciously instantiate this yourself.\n///\n/// The instance is always named `context`, and it will always be available\n/// within the body of every #[public] function in your smart contract.\n///\n/// Typical usage for a smart contract developer will be to call getter\n/// methods of the PublicContext.\n///\n/// _Pushing_ data and requests to the context is mostly handled within\n/// aztec-nr's own functions, so typically a smart contract developer won't\n/// need to call any setter methods directly.\n///\n/// ## Responsibilities\n/// - Exposes contextual data to a public function:\n/// - Data relating to how this public function was called:\n/// - msg_sender, this_address\n/// - Data relating to the current blockchain state:\n/// - timestamp, block_number, chain_id, version\n/// - Gas and fee information\n/// - Provides state access:\n/// - Read/write public storage (key-value mapping)\n/// - Check existence of notes and nullifiers\n/// (Some patterns use notes & nullifiers to store public (not private)\n/// information)\n/// - Enables consumption of L1->L2 messages.\n/// - Enables calls to other public smart contract functions:\n/// - Writes data to the blockchain:\n/// - Updates to public state variables\n/// - New public logs (for events)\n/// - New L2->L1 messages\n/// - New notes & nullifiers\n/// (E.g. pushing public info to notes/nullifiers, or for completing\n/// \"partial notes\")\n///\n/// ## Key Differences from Private Execution\n///\n/// Unlike private functions -- which are executed on the user's device and which\n/// can only reference historic state -- public functions are executed by a block\n/// proposer and are executed \"live\" on the _current_ tip of the chain.\n/// This means public functions can:\n/// - Read and write _current_ public state\n/// - Immediately see the effects of earlier transactions in the same block\n///\n/// Also, public functions are executed within a zkVM (the \"AVM\"), so that they\n/// can _revert_ whilst still ensuring payment to the proposer and prover.\n/// (Private functions cannot revert: they either succeed, or they cannot be\n/// included).\n///\n/// ## Optimising Public Functions\n///\n/// Using the AVM to execute public functions means they compile down to \"AVM\n/// bytecode\" instead of the ACIR that private functions (standalone circuits)\n/// compile to. Therefore the approach to optimising a public function is\n/// fundamentally different from optimising a public function.\n///\npub struct PublicContext {\n pub args_hash: Option,\n pub compute_args_hash: fn() -> Field,\n}\n\nimpl Eq for PublicContext {\n fn eq(self, other: Self) -> bool {\n (self.args_hash == other.args_hash)\n // Can't compare the function compute_args_hash\n }\n}\n\nimpl PublicContext {\n /// Creates a new PublicContext instance.\n ///\n /// Low-level function: This is called automatically by the #[public]\n /// macro, so you shouldn't need to be called directly by smart contract\n /// developers.\n ///\n /// # Arguments\n /// * `compute_args_hash` - Function to compute the args_hash\n ///\n /// # Returns\n /// * A new PublicContext instance\n ///\n pub fn new(compute_args_hash: fn() -> Field) -> Self {\n PublicContext { args_hash: Option::none(), compute_args_hash }\n }\n\n /// Emits a _public_ log that will be visible onchain to everyone.\n ///\n /// # Arguments\n /// * `log` - The data to log, must implement Serialize trait\n ///\n pub fn emit_public_log(_self: &mut Self, log: T)\n where\n T: Serialize,\n {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { emit_public_log(Serialize::serialize(log).as_slice()) };\n }\n\n /// Checks if a given note hash exists in the note hash tree at a particular\n /// leaf_index.\n ///\n /// # Arguments\n /// * `note_hash` - The note hash to check for existence\n /// * `leaf_index` - The index where the note hash should be located\n ///\n /// # Returns\n /// * `bool` - True if the note hash exists at the specified index\n ///\n pub fn note_hash_exists(_self: Self, note_hash: Field, leaf_index: u64) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { note_hash_exists(note_hash, leaf_index) } == 1\n }\n\n /// Checks if a specific L1-to-L2 message exists in the L1-to-L2 message\n /// tree at a particular leaf index.\n ///\n /// Common use cases include token bridging, cross-chain governance, and\n /// triggering L2 actions based on L1 events.\n ///\n /// This function should be called before attempting to consume an L1-to-L2\n /// message.\n ///\n /// # Arguments\n /// * `msg_hash` - Hash of the L1-to-L2 message to check\n /// * `msg_leaf_index` - The index where the message should be located\n ///\n /// # Returns\n /// * `bool` - True if the message exists at the specified index\n ///\n /// # Advanced\n /// * Uses the AVM l1_to_l2_msg_exists opcode for tree lookup\n /// * Messages are copied from L1 Inbox to L2 by block proposers\n ///\n pub fn l1_to_l2_msg_exists(_self: Self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n // TODO(alvaro): Make l1l2msg leaf index a u64 upstream\n unsafe { l1_to_l2_msg_exists(msg_hash, msg_leaf_index as u64) } == 1\n }\n\n /// Checks if a specific nullifier has been emitted by a given contract.\n ///\n /// Whilst nullifiers are primarily intended as a _privacy-preserving_\n /// record of a one-time action, they can also be used to efficiently\n /// record _public_ one-time actions too. An example is to check\n /// whether a contract has been published: we emit a nullifier that is\n /// deterministic, but whose preimage is _not_ private. This is more\n /// efficient than using mutable storage, and can be done directly\n /// from a private function.\n ///\n /// Nullifiers can be tested for non-existence in public, which is not the\n /// case in private. Because private functions do not have access to\n /// the tip of the blockchain (but only the anchor block they are built\n /// at) they can only prove nullifier non-existence in the past. But between\n /// an anchor block and the block in which a tx is included, the nullifier\n /// might have been inserted into the nullifier tree by some other\n /// transaction.\n /// Public functions _do_ have access to the tip of the state, and so\n /// this pattern is safe.\n ///\n /// # Arguments\n /// * `unsiloed_nullifier` - The raw nullifier value (before siloing with\n /// the contract address that emitted it).\n /// * `address` - The claimed contract address that emitted the nullifier\n ///\n /// # Returns\n /// * `bool` - True if the nullifier has been emitted by the specified contract\n ///\n pub fn nullifier_exists(_self: Self, unsiloed_nullifier: Field, address: AztecAddress) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { nullifier_exists(unsiloed_nullifier, address.to_field()) } == 1\n }\n\n /// Consumes a message sent from Ethereum (L1) to Aztec (L2) -- effectively\n /// marking it as \"read\".\n ///\n /// Use this function if you only want the message to ever be \"referred to\"\n /// once. Once consumed using this method, the message cannot be consumed\n /// again, because a nullifier is emitted.\n /// If your use case wants for the message to be read unlimited times, then\n /// you can always read any historic message from the L1-to-L2 messages tree,\n /// using the `l1_to_l2_msg_exists` method. Messages never technically get\n /// deleted from that tree.\n ///\n /// The message will first be inserted into an Aztec \"Inbox\" smart contract\n /// on L1. It will not be available for consumption immediately. Messages\n /// get copied-over from the L1 Inbox to L2 by the next Proposer in batches.\n /// So you will need to wait until the messages are copied before you can\n /// consume them.\n ///\n /// # Arguments\n /// * `content` - The message content that was sent from L1\n /// * `secret` - Secret value used for message privacy (if needed)\n /// * `sender` - Ethereum address that sent the message\n /// * `leaf_index` - Index of the message in the L1-to-L2 message tree\n ///\n /// # Advanced\n /// * Validates message existence in the L1-to-L2 message tree\n /// * Prevents double-consumption by emitting a nullifier\n /// * Message hash is computed from all parameters + chain context\n /// * Will revert if message doesn't exist or was already consumed\n ///\n pub 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_l1_to_l2_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/\n self.this_address(),\n self.version(),\n content,\n secret_hash,\n leaf_index,\n );\n let nullifier = compute_l1_to_l2_message_nullifier(message_hash, secret);\n\n assert(\n !self.nullifier_exists(nullifier, self.this_address()),\n \"L1-to-L2 message is already nullified\",\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index),\n \"Tried to consume nonexistent L1-to-L2 message\",\n );\n\n self.push_nullifier(nullifier);\n }\n\n /// Sends an \"L2 -> L1 message\" from this function (Aztec, L2) to a smart\n /// contract on Ethereum (L1). L1 contracts which are designed to\n /// send/receive messages to/from Aztec are called \"Portal Contracts\".\n ///\n /// Common use cases include withdrawals, cross-chain asset transfers, and\n /// triggering L1 actions based on L2 state changes.\n ///\n /// The message will be inserted into an Aztec \"Outbox\" contract on L1,\n /// when this transaction's block is proposed to L1.\n /// Sending the message will not result in any immediate state changes in\n /// the target portal contract. The message will need to be manually\n /// consumed from the Outbox through a separate Ethereum transaction: a user\n /// will need to call a function of the portal contract -- a function\n /// specifically designed to make a call to the Outbox to consume the\n /// message.\n /// The message will only be available for consumption once the _epoch_\n /// proof has been submitted. Given that there are multiple Aztec blocks\n /// within an epoch, it might take some time for this epoch proof to be\n /// submitted -- especially if the block was near the start of an epoch.\n ///\n /// # Arguments\n /// * `recipient` - Ethereum address that will receive the message\n /// * `content` - Message content (32 bytes as a Field element)\n ///\n pub fn message_portal(_self: &mut Self, recipient: EthAddress, content: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { send_l2_to_l1_msg(recipient, content) };\n }\n\n /// Calls a public function on another contract.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract to call\n /// * `function_selector` - Function to call on the target contract\n /// * `args` - Arguments to pass to the function\n /// * `gas_opts` - An optional allocation of gas to the called function.\n ///\n /// # Returns\n /// * `[Field]` - Return data from the called function\n ///\n pub unconstrained fn call_public_function(\n _self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = args.push_front(function_selector.to_field());\n\n call(\n gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_U32_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = success_copy();\n\n let result_data = returndata_copy(0, returndata_size());\n if !success {\n // Rethrow the revert data.\n avm_revert(result_data);\n }\n result_data\n }\n\n /// Makes a read-only call to a public function on another contract.\n ///\n /// This is similar to Solidity's `staticcall`. The called function\n /// cannot modify state or emit events. Any nested calls are constrained to\n /// also be staticcalls.\n ///\n /// Useful for querying data from other contracts safely.\n ///\n /// Will revert if the called function reverts or runs out of gas.\n ///\n /// # Arguments\n /// * `contract_address` - Address of the contract to call\n /// * `function_selector` - Function to call on the target contract\n /// * `args` - Array of arguments to pass to the called function\n /// * `gas_opts` - An optional allocation of gas to the called function.\n ///\n /// # Returns\n /// * `[Field]` - Return data from the called function\n ///\n pub unconstrained fn static_call_public_function(\n _self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts,\n ) -> [Field] {\n let calldata = args.push_front(function_selector.to_field());\n\n call_static(\n gas_opts.l2_gas.unwrap_or(MAX_U32_VALUE),\n gas_opts.da_gas.unwrap_or(MAX_U32_VALUE),\n contract_address,\n calldata,\n );\n // Use success_copy to determine whether the call succeeded\n let success = success_copy();\n\n let result_data = returndata_copy(0, returndata_size());\n if !success {\n // Rethrow the revert data.\n avm_revert(result_data);\n }\n result_data\n }\n\n /// Adds a new note hash to the Aztec blockchain's global Note Hash Tree.\n ///\n /// Notes are ordinarily constructed and emitted by _private_ functions, to\n /// ensure that both the content of the note, and the contract that emitted\n /// the note, stay private.\n ///\n /// There are however some useful patterns whereby a note needs to contain\n /// _public_ data. The ability to push a new note_hash from a _public_\n /// function means that notes can be injected with public data immediately\n /// -- as soon as the public value is known. The slower alternative would\n /// be to submit a follow-up transaction so that a private function can\n /// inject the data. Both are possible on Aztec.\n ///\n /// Search \"Partial Note\" for a very common pattern which enables a note\n /// to be \"partially\" populated with some data in a _private_ function, and\n /// then later \"completed\" with some data in a public function.\n ///\n /// # Arguments\n /// * `note_hash` - The hash of the note to add to the tree\n ///\n /// # Advanced\n /// * The note hash will be siloed with the contract address by the protocol\n ///\n pub fn push_note_hash(_self: &mut Self, note_hash: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { emit_note_hash(note_hash) };\n }\n\n /// Adds a new nullifier to the Aztec blockchain's global Nullifier Tree.\n ///\n /// Whilst nullifiers are primarily intended as a _privacy-preserving_\n /// record of a one-time action, they can also be used to efficiently\n /// record _public_ one-time actions too. Hence why you're seeing this\n /// function within the PublicContext.\n /// An example is to check whether a contract has been published: we emit\n /// a nullifier that is deterministic, but whose preimage is _not_ private.\n ///\n /// # Arguments\n /// * `nullifier` - A unique field element that represents the consumed\n /// state\n ///\n /// # Advanced\n /// * Nullifier is immediately added to the global nullifier tree\n /// * Emitted nullifiers are immediately visible to all\n /// subsequent transactions in the same block\n /// * Automatically siloed with the contract address by the protocol\n /// * Used for preventing double-spending and ensuring one-time actions\n ///\n pub fn push_nullifier(_self: &mut Self, nullifier: Field) {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { emit_nullifier(nullifier) };\n }\n\n /// Returns the address of the current contract being executed.\n ///\n /// This is equivalent to `address(this)` in Solidity (hence the name).\n /// Use this to identify the current contract's address, commonly needed for\n /// access control or when interacting with other contracts.\n ///\n /// # Returns\n /// * `AztecAddress` - The contract address of the current function being\n /// executed.\n ///\n pub fn this_address(_self: Self) -> AztecAddress {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n address()\n }\n }\n\n /// Returns the contract address that initiated this function call.\n ///\n /// This is similar to `msg.sender` in Solidity (hence the name).\n ///\n /// Important Note: Since Aztec doesn't have a concept of an EoA (\n /// Externally-owned Account), the msg_sender is \"undefined\" for the first\n /// function call of every transaction. A value of `-1` is returned in such\n /// cases, and is enforced by the protocol's kernel circuits.\n /// The first function call of a tx is likely to be a call to the user's\n /// account contract, so this quirk will most often be handled by account\n /// contract developers.\n ///\n /// # Returns\n /// * `AztecAddress` - The address of the account or contract that called\n /// this function\n ///\n /// # Examples\n /// ```rust\n /// #[aztec(public)]\n /// fn transfer(context: &mut PublicContext, to: AztecAddress, amount: u64) {\n /// let sender = context.msg_sender();\n /// // Only the sender can transfer their own tokens\n /// assert(sender == get_token_owner(), \"Unauthorized\");\n /// }\n /// ```\n ///\n /// # Advanced\n /// * Value is provided by the AVM sender opcode\n /// * In nested calls, this is the immediate caller, not the original\n /// transaction sender\n /// * Globally visible unlike private execution where it's contract-local\n pub fn msg_sender(_self: Self) -> AztecAddress {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n sender()\n }\n }\n\n /// Returns the function selector of the currently-executing function.\n ///\n /// This is similar to `msg.sig` in Solidity, returning the first 4\n /// bytes of the function signature.\n ///\n /// # Returns\n /// * `FunctionSelector` - The 4-byte function identifier\n ///\n /// # Advanced\n /// * Extracted from the first element of calldata\n /// * Used internally for function dispatch in the AVM\n ///\n pub fn selector(_self: Self) -> FunctionSelector {\n // The selector is the first element of the calldata when calling a public function through dispatch.\n // Safety: AVM opcodes are constrained by the AVM itself\n let raw_selector: [Field; 1] = unsafe { calldata_copy(0, 1) };\n FunctionSelector::from_field(raw_selector[0])\n }\n\n /// Returns the hash of the arguments passed to the current function.\n ///\n /// Very low-level function: The #[public] macro uses this internally.\n /// Smart contract developers typically won't need to access this\n /// directly as arguments are automatically made available.\n ///\n /// # Returns\n /// * `Field` - Hash of the function arguments\n ///\n pub fn get_args_hash(mut self) -> Field {\n if !self.args_hash.is_some() {\n self.args_hash = Option::some((self.compute_args_hash)());\n }\n\n self.args_hash.unwrap_unchecked()\n }\n\n /// Returns the \"transaction fee\" for the current transaction.\n /// This is the final tx fee that will be deducted from the fee_payer's\n /// \"fee-juice\" balance (in the protocol's Base Rollup circuit).\n ///\n /// # Returns\n /// * `Field` - The actual, final cost of the transaction, taking into account:\n /// the actual gas used during the setup and app-logic phases,\n /// and the fixed amount of gas that's been allocated by the user\n /// for the teardown phase.\n /// I.e. effectiveL2FeePerGas * l2GasUsed + effectiveDAFeePerGas * daGasUsed\n ///\n /// This will return `0` during the \"setup\" and \"app-logic\" phases of\n /// tx execution (because the final tx fee is not known at that time).\n /// This will only return a nonzero value during the \"teardown\" phase of\n /// execution, where the final tx fee can actually be computed.\n ///\n /// Regardless of _when_ this function is called during the teardown phase,\n /// it will always return the same final tx fee value. The teardown phase\n /// does not consume a variable amount of gas: it always consumes a\n /// pre-allocated amount of gas, as specified by the user when they generate\n /// their tx.\n ///\n pub fn transaction_fee(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n transaction_fee()\n }\n }\n\n /// Returns the chain ID of the current network.\n ///\n /// This is similar to `block.chainid` in Solidity. Returns the unique\n /// identifier for the blockchain network this transaction is executing on.\n ///\n /// Helps prevent cross-chain replay attacks. Useful if implementing\n /// multi-chain contract logic.\n ///\n /// # Returns\n /// * `Field` - The chain ID as a field element\n ///\n pub fn chain_id(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n chain_id()\n }\n }\n\n /// Returns the Aztec protocol version that this transaction is executing\n /// under. Different versions may have different rules, opcodes, or\n /// cryptographic primitives.\n ///\n /// This is similar to how Ethereum has different EVM versions.\n ///\n /// Useful for forward/backward compatibility checks\n ///\n /// Not to be confused with contract versions; this is the protocol version.\n ///\n /// # Returns\n /// * `Field` - The protocol version as a field element\n ///\n pub fn version(_self: Self) -> Field {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n version()\n }\n }\n /// Returns the current block number.\n ///\n /// This is similar to `block.number` in Solidity.\n ///\n /// Note: the current block number is only available within a public function\n /// (as opposed to a private function).\n ///\n /// Note: the time intervals between blocks should not be relied upon as\n /// being consistent:\n /// - Timestamps of blocks fall within a range, rather than at exact regular\n /// intervals.\n /// - Slots can be missed.\n /// - Protocol upgrades can completely change the intervals between blocks\n /// (and indeed the current roadmap plans to reduce the time between\n /// blocks, eventually).\n /// Use `context.timestamp()` for more-reliable time-based logic.\n ///\n /// # Returns\n /// * `u32` - The current block number\n ///\n pub fn block_number(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n block_number()\n }\n }\n\n /// Returns the timestamp of the current block.\n ///\n /// This is similar to `block.timestamp` in Solidity.\n ///\n /// All functions of all transactions in a block share the exact same\n /// timestamp (even though technically each transaction is executed\n /// one-after-the-other).\n ///\n /// Important note: Timestamps of Aztec blocks are not at reliably-fixed\n /// intervals. The proposer of the block has some flexibility to choose a\n /// timestamp which is in a valid _range_: Obviously the timestamp of this\n /// block must be strictly greater than that of the previous block, and must\n /// must be less than the timestamp of whichever ethereum block the aztec\n /// block is proposed to. Furthermore, if the timestamp is not deemed close\n /// enough to the actual current time, the committee of validators will not\n /// attest to the block.\n ///\n /// # Returns\n /// * `u64` - Unix timestamp in seconds\n ///\n pub fn timestamp(_self: Self) -> u64 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n timestamp()\n }\n }\n\n /// Returns the fee per unit of L2 gas for this transaction (aka the \"L2 gas\n /// price\"), as chosen by the user.\n ///\n /// L2 gas covers the cost of executing public functions and handling\n /// side-effects within the AVM.\n ///\n /// # Returns\n /// * `u128` - Fee per unit of L2 gas\n ///\n /// Wallet developers should be mindful that the choice of gas price (which\n /// is publicly visible) can leak information about the user, e.g.:\n /// - which wallet software the user is using;\n /// - the amount of time which has elapsed from the time the user's wallet\n /// chose a gas price (at the going rate), to the time of tx submission.\n /// This can give clues about the proving time, and hence the nature of\n /// the tx.\n /// - the urgency of the transaction (which is kind of unavoidable, if the\n /// tx is indeed urgent).\n /// - the wealth of the user.\n /// - the exact user (if the gas price is explicitly chosen by the user to\n /// be some unique number like 0.123456789, or their favourite number).\n /// Wallet devs might wish to consider fuzzing the choice of gas price.\n ///\n pub fn base_fee_per_l2_gas(_self: Self) -> u128 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n base_fee_per_l2_gas()\n }\n }\n\n /// Returns the fee per unit of DA (Data Availability) gas (aka the \"DA gas\n /// price\").\n ///\n /// DA gas covers the cost of making transaction data available on L1.\n ///\n /// See the warning in `fee_pre_l2_gas` for how gas prices can be leaky.\n ///\n /// # Returns\n /// * `u128` - Fee per unit of DA gas\n ///\n pub fn base_fee_per_da_gas(_self: Self) -> u128 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n base_fee_per_da_gas()\n }\n }\n\n /// Returns the remaining L2 gas available for this transaction.\n ///\n /// Different AVM opcodes consume different amounts of gas.\n ///\n /// # Returns\n /// * `u32` - Remaining L2 gas units\n ///\n pub fn l2_gas_left(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n l2_gas_left()\n }\n }\n\n /// Returns the remaining DA (Data Availability) gas available for this\n /// transaction.\n ///\n /// DA gas is consumed when emitting data that needs to be made available\n /// on L1, such as public logs or state updates.\n /// All of the side-effects from the private part of the tx also consume\n /// DA gas before execution of any public functions even begins.\n ///\n /// # Returns\n /// * `u32` - Remaining DA gas units\n ///\n pub fn da_gas_left(_self: Self) -> u32 {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe {\n da_gas_left()\n }\n }\n\n /// Checks if the current execution is within a staticcall context, where\n /// no state changes or logs are allowed to be emitted (by this function\n /// or any nested function calls).\n ///\n /// # Returns\n /// * `bool` - True if in staticcall context, false otherwise\n ///\n pub fn is_static_call(_self: Self) -> bool {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { is_static_call() } == 1\n }\n\n /// Reads raw field values from public storage.\n /// Reads N consecutive storage slots starting from the given slot.\n ///\n /// Very low-level function. Users should typically use the public state\n /// variable abstractions to perform reads: PublicMutable & PublicImmutable.\n ///\n /// # Arguments\n /// * `storage_slot` - The starting storage slot to read from\n ///\n /// # Returns\n /// * `[Field; N]` - Array of N field values from consecutive storage slots\n ///\n /// # Generic Parameters\n /// * `N` - the number of consecutive slots to return, starting from the\n /// `storage_slot`.\n ///\n pub fn raw_storage_read(_self: Self, storage_slot: Field) -> [Field; N] {\n let mut out = [0; N];\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n out[i] = unsafe { storage_read(storage_slot + i as Field) };\n }\n out\n }\n\n /// Reads a typed value from public storage.\n ///\n /// Low-level function. Users should typically use the public state\n /// variable abstractions to perform reads: PublicMutable & PublicImmutable.\n ///\n /// # Arguments\n /// * `storage_slot` - The storage slot to read from\n ///\n /// # Returns\n /// * `T` - The deserialized value from storage\n ///\n /// # Generic Parameters\n /// * `T` - The type that the caller expects to read from the `storage_slot`.\n ///\n pub fn storage_read(self, storage_slot: Field) -> T\n where\n T: Packable,\n {\n T::unpack(self.raw_storage_read(storage_slot))\n }\n\n /// Writes raw field values to public storage.\n /// Writes to N consecutive storage slots starting from the given slot.\n ///\n /// Very low-level function. Users should typically use the public state\n /// variable abstractions to perform writes: PublicMutable & PublicImmutable.\n ///\n /// Public storage writes take effect immediately.\n ///\n /// # Arguments\n /// * `storage_slot` - The starting storage slot to write to\n /// * `values` - Array of N Fields to write to storage\n ///\n pub fn raw_storage_write(_self: Self, storage_slot: Field, values: [Field; N]) {\n for i in 0..N {\n // Safety: AVM opcodes are constrained by the AVM itself\n unsafe { storage_write(storage_slot + i as Field, values[i]) };\n }\n }\n\n /// Writes a typed value to public storage.\n ///\n /// Low-level function. Users should typically use the public state\n /// variable abstractions to perform writes: PublicMutable & PublicImmutable.\n ///\n /// # Arguments\n /// * `storage_slot` - The storage slot to write to\n /// * `value` - The typed value to write to storage\n ///\n /// # Generic Parameters\n /// * `T` - The type to write to storage.\n ///\n pub fn storage_write(self, storage_slot: Field, value: T)\n where\n T: Packable,\n {\n self.raw_storage_write(storage_slot, value.pack());\n }\n}\n\n// TODO: consider putting this oracle code in its own file.\n// Unconstrained opcode wrappers (do not use directly).\nunconstrained fn address() -> AztecAddress {\n address_opcode()\n}\nunconstrained fn sender() -> AztecAddress {\n sender_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() -> u32 {\n block_number_opcode()\n}\nunconstrained fn timestamp() -> u64 {\n timestamp_opcode()\n}\nunconstrained fn base_fee_per_l2_gas() -> u128 {\n base_fee_per_l2_gas_opcode()\n}\nunconstrained fn base_fee_per_da_gas() -> u128 {\n base_fee_per_da_gas_opcode()\n}\nunconstrained fn l2_gas_left() -> u32 {\n l2_gas_left_opcode()\n}\nunconstrained fn da_gas_left() -> u32 {\n da_gas_left_opcode()\n}\nunconstrained fn is_static_call() -> u1 {\n is_static_call_opcode()\n}\nunconstrained fn note_hash_exists(note_hash: Field, leaf_index: u64) -> u1 {\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) -> u1 {\n nullifier_exists_opcode(nullifier, address)\n}\nunconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\nunconstrained fn emit_public_log(message: [Field]) {\n emit_public_log_opcode(message)\n}\nunconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: u64) -> u1 {\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}\n\nunconstrained fn call(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field],\n) {\n call_opcode(l2_gas_allocation, da_gas_allocation, address, args)\n}\n\nunconstrained fn call_static(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field],\n) {\n call_static_opcode(l2_gas_allocation, da_gas_allocation, address, args)\n}\n\npub unconstrained fn calldata_copy(cdoffset: u32, copy_size: u32) -> [Field; N] {\n calldata_copy_opcode(cdoffset, copy_size)\n}\n\n// `success_copy` is placed immediately after the CALL opcode to get the success value\nunconstrained fn success_copy() -> bool {\n success_copy_opcode()\n}\n\nunconstrained fn returndata_size() -> u32 {\n returndata_size_opcode()\n}\n\nunconstrained fn returndata_copy(rdoffset: u32, copy_size: u32) -> [Field] {\n returndata_copy_opcode(rdoffset, copy_size)\n}\n\npub unconstrained fn avm_return(returndata: [Field]) {\n return_opcode(returndata)\n}\n\n// This opcode reverts using the exact data given. In general it should only be used\n// to do rethrows, where the revert data is the same as the original revert data.\n// For normal reverts, use Noir's `assert` which, on top of reverting, will also add\n// an error selector to the revert data.\nunconstrained fn avm_revert(revertdata: [Field]) {\n revert_opcode(revertdata)\n}\n\nunconstrained fn storage_read(storage_slot: Field) -> Field {\n storage_read_opcode(storage_slot)\n}\n\nunconstrained fn storage_write(storage_slot: Field, value: Field) {\n storage_write_opcode(storage_slot, value);\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(|| 0)\n }\n}\n\n// TODO: consider putting this oracle code in its own file.\n// AVM oracles (opcodes) follow, do not use directly.\n#[oracle(avmOpcodeAddress)]\nunconstrained fn address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeSender)]\nunconstrained fn sender_opcode() -> AztecAddress {}\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() -> u32 {}\n\n#[oracle(avmOpcodeTimestamp)]\nunconstrained fn timestamp_opcode() -> u64 {}\n\n#[oracle(avmOpcodeBaseFeePerL2Gas)]\nunconstrained fn base_fee_per_l2_gas_opcode() -> u128 {}\n\n#[oracle(avmOpcodeBaseFeePerDaGas)]\nunconstrained fn base_fee_per_da_gas_opcode() -> u128 {}\n\n#[oracle(avmOpcodeL2GasLeft)]\nunconstrained fn l2_gas_left_opcode() -> u32 {}\n\n#[oracle(avmOpcodeDaGasLeft)]\nunconstrained fn da_gas_left_opcode() -> u32 {}\n\n#[oracle(avmOpcodeIsStaticCall)]\nunconstrained fn is_static_call_opcode() -> u1 {}\n\n#[oracle(avmOpcodeNoteHashExists)]\nunconstrained fn note_hash_exists_opcode(note_hash: Field, leaf_index: u64) -> u1 {}\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) -> u1 {}\n\n#[oracle(avmOpcodeEmitNullifier)]\nunconstrained fn emit_nullifier_opcode(nullifier: Field) {}\n\n// TODO(#11124): rename unencrypted to public in avm\n#[oracle(avmOpcodeEmitUnencryptedLog)]\nunconstrained fn emit_public_log_opcode(message: [Field]) {}\n\n#[oracle(avmOpcodeL1ToL2MsgExists)]\nunconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: u64) -> u1 {}\n\n#[oracle(avmOpcodeSendL2ToL1Msg)]\nunconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(avmOpcodeCalldataCopy)]\nunconstrained fn calldata_copy_opcode(cdoffset: u32, copy_size: u32) -> [Field; N] {}\n\n#[oracle(avmOpcodeReturndataSize)]\nunconstrained fn returndata_size_opcode() -> u32 {}\n\n#[oracle(avmOpcodeReturndataCopy)]\nunconstrained fn returndata_copy_opcode(rdoffset: u32, copy_size: u32) -> [Field] {}\n\n#[oracle(avmOpcodeReturn)]\nunconstrained fn return_opcode(returndata: [Field]) {}\n\n// This opcode reverts using the exact data given. In general it should only be used\n// to do rethrows, where the revert data is the same as the original revert data.\n// For normal reverts, use Noir's `assert` which, on top of reverting, will also add\n// an error selector to the revert data.\n#[oracle(avmOpcodeRevert)]\nunconstrained fn revert_opcode(revertdata: [Field]) {}\n\n#[oracle(avmOpcodeCall)]\nunconstrained fn call_opcode(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field],\n) {}\n\n#[oracle(avmOpcodeStaticCall)]\nunconstrained fn call_static_opcode(\n l2_gas_allocation: u32,\n da_gas_allocation: u32,\n address: AztecAddress,\n args: [Field],\n) {}\n\n#[oracle(avmOpcodeSuccessCopy)]\nunconstrained fn success_copy_opcode() -> bool {}\n\n#[oracle(avmOpcodeStorageRead)]\nunconstrained fn storage_read_opcode(storage_slot: Field) -> Field {}\n\n#[oracle(avmOpcodeStorageWrite)]\nunconstrained fn storage_write_opcode(storage_slot: Field, value: Field) {}\n" - }, - "71": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/context/utility_context.nr", - "source": "use crate::oracle::{\n execution::{get_block_number, get_chain_id, get_contract_address, get_timestamp, get_version},\n storage::storage_read,\n};\nuse dep::protocol_types::{address::AztecAddress, traits::Packable};\n\npub struct UtilityContext {\n block_number: u32,\n timestamp: u64,\n contract_address: AztecAddress,\n version: Field,\n chain_id: Field,\n}\n\nimpl UtilityContext {\n pub unconstrained 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 a UtilityContext in an environment in which these oracles are not\n // available.\n let block_number = get_block_number();\n let timestamp = get_timestamp();\n let contract_address = get_contract_address();\n let version = get_version();\n let chain_id = get_chain_id();\n Self { block_number, timestamp, contract_address, version, chain_id }\n }\n\n pub unconstrained fn at(contract_address: AztecAddress) -> Self {\n let block_number = get_block_number();\n let timestamp = get_timestamp();\n let chain_id = get_chain_id();\n let version = get_version();\n Self { block_number, timestamp, contract_address, version, chain_id }\n }\n\n pub unconstrained fn at_historical(contract_address: AztecAddress, block_number: u32) -> Self {\n let timestamp = get_timestamp();\n let chain_id = get_chain_id();\n let version = get_version();\n Self { block_number, timestamp, contract_address, version, chain_id }\n }\n\n pub fn block_number(self) -> u32 {\n self.block_number\n }\n\n pub fn timestamp(self) -> u64 {\n self.timestamp\n }\n\n pub fn this_address(self) -> AztecAddress {\n self.contract_address\n }\n\n pub fn version(self) -> Field {\n self.version\n }\n\n pub fn chain_id(self) -> Field {\n self.chain_id\n }\n\n pub unconstrained fn raw_storage_read(\n self: Self,\n storage_slot: Field,\n ) -> [Field; N] {\n storage_read(self.this_address(), storage_slot, self.block_number())\n }\n\n pub unconstrained fn storage_read(self, storage_slot: Field) -> T\n where\n T: Packable,\n {\n T::unpack(self.raw_storage_read(storage_slot))\n }\n}\n" - }, - "73": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/event/event_selector.nr", - "source": "use dep::protocol_types::{\n hash::poseidon2_hash_bytes,\n traits::{Deserialize, Empty, FromField, Serialize, ToField},\n};\n\n#[derive(Deserialize, Eq, Serialize)]\npub struct EventSelector {\n // 1st 4-bytes (big-endian leftmost) of abi-encoding of an event.\n inner: u32,\n}\n\nimpl FromField for EventSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for EventSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for EventSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl EventSelector {\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 = poseidon2_hash_bytes(bytes);\n\n // `hash` is automatically truncated to fit within 32 bits.\n EventSelector::from_field(hash)\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n" - }, - "75": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/hash.nr", - "source": "use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__FUNCTION_ARGS, GENERATOR_INDEX__MESSAGE_NULLIFIER,\n GENERATOR_INDEX__PUBLIC_BYTECODE, GENERATOR_INDEX__PUBLIC_CALLDATA,\n GENERATOR_INDEX__SECRET_HASH, MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS,\n },\n hash::{\n poseidon2_hash_subarray, poseidon2_hash_with_separator, poseidon2_hash_with_separator_slice,\n sha256_to_field,\n },\n point::Point,\n traits::{Hash, ToField},\n};\n\npub use dep::protocol_types::hash::{compute_siloed_nullifier, pedersen_hash};\n\npub fn pedersen_commitment(inputs: [Field; N], hash_index: u32) -> Point {\n std::hash::pedersen_commitment_with_separator(inputs, hash_index)\n}\n\npub fn compute_secret_hash(secret: Field) -> Field {\n poseidon2_hash_with_separator([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_l1_to_l2_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field,\n leaf_index: Field,\n) -> Field {\n let mut hash_bytes = [0 as u8; 224];\n let sender_bytes: [u8; 32] = sender.to_field().to_be_bytes();\n let chain_id_bytes: [u8; 32] = chain_id.to_be_bytes();\n let recipient_bytes: [u8; 32] = recipient.to_field().to_be_bytes();\n let version_bytes: [u8; 32] = version.to_be_bytes();\n let content_bytes: [u8; 32] = content.to_be_bytes();\n let secret_hash_bytes: [u8; 32] = secret_hash.to_be_bytes();\n let leaf_index_bytes: [u8; 32] = leaf_index.to_be_bytes();\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 hash_bytes[i + 192] = leaf_index_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\npub fn compute_l1_to_l2_message_nullifier(message_hash: Field, secret: Field) -> Field {\n poseidon2_hash_with_separator([message_hash, secret], GENERATOR_INDEX__MESSAGE_NULLIFIER)\n}\n\npub struct ArgsHasher {\n pub 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\n// Computes the hash of input arguments or return values for private functions, or for authwit creation.\npub fn hash_args_array(args: [Field; N]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n poseidon2_hash_with_separator(args, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n// Same as `hash_args_array`, but takes a slice instead of an array.\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n poseidon2_hash_with_separator_slice(args, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n// Computes the hash of calldata for public functions.\npub fn hash_calldata_array(calldata: [Field; N]) -> Field {\n if calldata.len() == 0 {\n 0\n } else {\n poseidon2_hash_with_separator(calldata, GENERATOR_INDEX__PUBLIC_CALLDATA)\n }\n}\n\n// Same as `hash_calldata_array`, but takes a slice instead of an array.\npub fn hash_calldata(calldata: [Field]) -> Field {\n if calldata.len() == 0 {\n 0\n } else {\n poseidon2_hash_with_separator_slice(calldata, GENERATOR_INDEX__PUBLIC_CALLDATA)\n }\n}\n\n/**\n * Computes the public bytecode commitment for a contract class.\n * The commitment is `hash([separator, ...bytecode])` where bytecode omits the length prefix present\n * in `packed_bytecode`.\n *\n * @param packed_bytecode - The packed bytecode of the contract class. 0th word is the length in bytes.\n * packed_bytecode is mutable so that we can avoid copying the array to construct one starting with\n * separator instead of length.\n * @returns The public bytecode commitment.\n */\npub fn compute_public_bytecode_commitment(\n mut packed_public_bytecode: [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS],\n) -> Field {\n // First field element contains the length of the bytecode\n let bytecode_length_in_bytes: u32 = packed_public_bytecode[0] as u32;\n let bytecode_length_in_fields: u32 =\n (bytecode_length_in_bytes / 31) + (bytecode_length_in_bytes % 31 != 0) as u32;\n // Don't allow empty public bytecode.\n // AVM doesn't handle execution of contracts that exist with empty bytecode.\n assert(bytecode_length_in_fields != 0);\n assert(bytecode_length_in_fields < MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS);\n\n // Packed_bytecode's 0th entry is the length. Replace it with separator before hashing.\n let separator = GENERATOR_INDEX__PUBLIC_BYTECODE.to_field();\n packed_public_bytecode[0] = separator;\n // +1 to length to account for the separator\n let nonzero_length = bytecode_length_in_fields + 1;\n\n poseidon2_hash_subarray(packed_public_bytecode, nonzero_length)\n // NOTE: we use poseidon2_hash_subarray here because we want to hash the bytecode only up to\n // its nonzero length. We do NOT want to include a `1` at the end to indicate \"variable length\",\n // and we want to enforce that all trailing elements are zero.\n}\n\n#[test]\nunconstrained fn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..100 {\n input.add(i as Field);\n }\n let hash = input.hash();\n dep::std::println(hash);\n assert(hash == 0x19b0d74feb06ebde19edd85a28986c97063e84b3b351a8b666c7cac963ce655f);\n}\n" - }, - "92": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/keys/getters/mod.nr", - "source": "use crate::{\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX},\n oracle::{\n key_validation_request::get_key_validation_request,\n keys::get_public_keys_and_partial_address,\n },\n};\nuse dep::protocol_types::{address::AztecAddress, public_keys::PublicKeys};\n\npub unconstrained fn get_nsk_app(npk_m_hash: Field) -> Field {\n get_key_validation_request(npk_m_hash, NULLIFIER_INDEX).sk_app\n}\n\n// A helper function that gets app-siloed outgoing viewing key for a given `ovpk_m_hash`. This function is used\n// in unconstrained contexts only - when computing unconstrained note logs. The safe alternative is `request_ovsk_app`\n// function defined on `PrivateContext`.\npub unconstrained fn get_ovsk_app(ovpk_m_hash: Field) -> Field {\n get_key_validation_request(ovpk_m_hash, OUTGOING_INDEX).sk_app\n}\n\n// Returns all public keys for a given account, applying proper constraints to the context. We read all\n// keys at once since the constraints for reading them all are actually fewer than if we read them one at a time - any\n// read keys that are not required by the caller can simply be discarded.\npub fn get_public_keys(account: AztecAddress) -> PublicKeys {\n // Safety: Public keys are constrained by showing their inclusion in the address's preimage.\n let (public_keys, partial_address) = unsafe { get_public_keys_and_partial_address(account) };\n assert_eq(\n account,\n AztecAddress::compute(public_keys, partial_address),\n \"Invalid public keys hint for address\",\n );\n\n public_keys\n}\n\nmod test {\n use super::get_public_keys;\n\n use crate::test::helpers::test_environment::TestEnvironment;\n use protocol_types::traits::Serialize;\n use std::test::OracleMock;\n\n global KEY_ORACLE_RESPONSE_LENGTH: u32 = 13; // 12 fields for the keys, one field for the partial address\n\n #[test(should_fail_with = \"Invalid public keys hint for address\")]\n unconstrained fn get_public_keys_fails_with_bad_hint() {\n let mut env = TestEnvironment::new();\n let account = env.create_light_account();\n\n // Instead of querying for some unknown account, which would result in the oracle erroring out, we mock a bad oracle\n // response to check that the circuit properly checks the address derivation.\n let mut random_keys_and_partial_address = [0; KEY_ORACLE_RESPONSE_LENGTH];\n // We use randomly generated points on the curve, and a random partial address to ensure that\n // this combination does not derive the address and we should see the assertion fail.\n // npk_m\n random_keys_and_partial_address[0] =\n 0x292364b852c6c6f01472951e76a39cbcf074591fd0e063a81965e7b51ad868a5;\n random_keys_and_partial_address[1] =\n 0x0a687b46cdc9238f1c311f126aaaa4acbd7a737bff2efd7aeabdb8d805843a27;\n random_keys_and_partial_address[2] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // ivpk_m\n random_keys_and_partial_address[3] =\n 0x173c5229a00c5425255680dd6edc27e278c48883991f348fe6985de43b4ec25f;\n random_keys_and_partial_address[4] =\n 0x1698608e23b5f6c2f43c49a559108bb64e2247b8fc2da842296a416817f40b7f;\n random_keys_and_partial_address[5] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // ovpk_m\n random_keys_and_partial_address[6] =\n 0x1bad2f7d1ad960a1bd0fe4d2c8d17f5ab4a86ef8b103e0a9e7f67ec0d3b4795e;\n random_keys_and_partial_address[7] =\n 0x206db87110abbecc9fbaef2c865189d94ef2c106202f734ee4eba9257fd28bf1;\n random_keys_and_partial_address[8] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // tpk_m\n random_keys_and_partial_address[9] =\n 0x05e3bd9cfe6b47daa139613619cf7d7fd8bb0112b6f2908caa6d9b536ed948ed;\n random_keys_and_partial_address[10] =\n 0x051066f877c9df47552d02e7dc32127ff4edefc8498e813bca1cbd3f5d1be429;\n random_keys_and_partial_address[11] =\n 0x0000000000000000000000000000000000000000000000000000000000000000;\n // partial address\n random_keys_and_partial_address[12] =\n 0x236703e2cb00a182e024e98e9f759231b556d25ff19f98896cebb69e9e678cc9;\n\n let _ = OracleMock::mock(\"utilityGetPublicKeysAndPartialAddress\").returns(\n random_keys_and_partial_address.serialize(),\n );\n let _ = get_public_keys(account);\n }\n}\n" - }, - "96": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/macros/aztec.nr", - "source": "use crate::macros::{\n dispatch::generate_public_dispatch,\n functions::{stub_registry, utils::check_each_fn_macroified},\n notes::NOTES,\n storage::STORAGE_LAYOUT_NAME,\n utils::{get_trait_impl_method, module_has_storage},\n};\n\n/// Marks a contract as an Aztec contract, generating the interfaces for its functions and notes, as well as injecting\n/// the `sync_private_state` utility function.\n/// Note: This is a module annotation, so the returned quote gets injected inside the module (contract) itself.\npub comptime fn aztec(m: Module) -> Quoted {\n let interface = generate_contract_interface(m);\n\n // Functions that don't have #[private], #[public], #[utility], #[contract_library_method], or #[test] are not\n // allowed in contracts.\n check_each_fn_macroified(m);\n\n // We generate `_compute_note_hash_and_nullifier`, `sync_private_state` and `process_message`\n // functions only if they are not already implemented. If they are implemented we just insert empty\n // quotes.\n let contract_library_method_compute_note_hash_and_nullifier = if !m.functions().any(|f| {\n f.name() == quote { _compute_note_hash_and_nullifier }\n }) {\n generate_contract_library_method_compute_note_hash_and_nullifier()\n } else {\n quote {}\n };\n let sync_private_state = if !m.functions().any(|f| f.name() == quote { sync_private_state }) {\n generate_sync_private_state()\n } else {\n quote {}\n };\n let process_message = if !m.functions().any(|f| f.name() == quote { process_message }) {\n generate_process_message()\n } else {\n quote {}\n };\n let public_dispatch = generate_public_dispatch(m);\n\n quote {\n $interface\n $contract_library_method_compute_note_hash_and_nullifier\n $public_dispatch\n $sync_private_state\n $process_message\n }\n}\n\ncomptime fn generate_contract_interface(m: Module) -> Quoted {\n let module_name = m.name();\n let contract_stubs = stub_registry::get(m);\n let fn_stubs_quote = if contract_stubs.is_some() {\n contract_stubs.unwrap().join(quote {})\n } else {\n quote {}\n };\n\n let has_storage_layout = module_has_storage(m) & STORAGE_LAYOUT_NAME.get(m).is_some();\n let storage_layout_getter = if has_storage_layout {\n let storage_layout_name = STORAGE_LAYOUT_NAME.get(m).unwrap();\n quote {\n pub fn storage_layout() -> StorageLayoutFields {\n $storage_layout_name.fields\n }\n }\n } else {\n quote {}\n };\n\n let library_storage_layout_getter = if has_storage_layout {\n quote {\n #[contract_library_method]\n $storage_layout_getter\n }\n } else {\n quote {}\n };\n\n quote {\n pub struct $module_name {\n pub target_contract: dep::aztec::protocol_types::address::AztecAddress\n }\n\n impl $module_name {\n $fn_stubs_quote\n\n pub fn at(\n addr: aztec::protocol_types::address::AztecAddress\n ) -> Self {\n Self { target_contract: addr }\n }\n\n pub fn interface() -> Self {\n Self { target_contract: aztec::protocol_types::address::AztecAddress::zero() }\n }\n\n $storage_layout_getter\n }\n\n #[contract_library_method]\n pub fn at(\n addr: aztec::protocol_types::address::AztecAddress\n ) -> $module_name {\n $module_name { target_contract: addr }\n }\n\n #[contract_library_method]\n pub fn interface() -> $module_name {\n $module_name { target_contract: aztec::protocol_types::address::AztecAddress::zero() }\n }\n\n $library_storage_layout_getter\n\n }\n}\n\n/// Generates a contract library method called `_compute_note_hash_and_nullifier` which is used for note\n/// discovery (to create the `aztec::messages::discovery::ComputeNoteHashAndNullifier` function) and to implement the\n/// `compute_note_hash_and_nullifier` unconstrained contract function.\ncomptime fn generate_contract_library_method_compute_note_hash_and_nullifier() -> Quoted {\n if NOTES.len() > 0 {\n // Contracts that do define notes produce an if-else chain where `note_type_id` is matched against the\n // `get_note_type_id()` function of each note type that we know of, in order to identify the note type. Once we\n // know it we call we correct `unpack` method from the `Packable` trait to obtain the underlying note type, and\n // compute the note hash (non-siloed) and inner nullifier (also non-siloed).\n\n let mut if_note_type_id_match_statements_list = &[];\n for i in 0..NOTES.len() {\n let typ = NOTES.get(i);\n\n let get_note_type_id = get_trait_impl_method(\n typ,\n quote { crate::note::note_interface::NoteType },\n quote { get_id },\n );\n let unpack = get_trait_impl_method(\n typ,\n quote { crate::protocol_types::traits::Packable },\n quote { unpack },\n );\n\n let compute_note_hash = get_trait_impl_method(\n typ,\n quote { crate::note::note_interface::NoteHash },\n quote { compute_note_hash },\n );\n\n let compute_nullifier_unconstrained = get_trait_impl_method(\n typ,\n quote { crate::note::note_interface::NoteHash },\n quote { compute_nullifier_unconstrained },\n );\n\n let if_or_else_if = if i == 0 {\n quote { if }\n } else {\n quote { else if }\n };\n\n if_note_type_id_match_statements_list = if_note_type_id_match_statements_list.push_back(\n quote {\n $if_or_else_if note_type_id == $get_note_type_id() {\n // As an extra safety check we make sure that the packed_note BoundedVec has the expected\n // length, since we're about to interpret its raw storage as a fixed-size array by calling the\n // unpack function on it.\n let expected_len = <$typ as $crate::protocol_types::traits::Packable>::N;\n let actual_len = packed_note.len();\n assert(\n actual_len == expected_len,\n f\"Expected packed note of length {expected_len} but got {actual_len} for note type id {note_type_id}\"\n );\n\n let note = $unpack(aztec::utils::array::subarray(packed_note.storage(), 0));\n\n let note_hash = $compute_note_hash(note, storage_slot);\n \n // The message discovery process finds settled notes, that is, notes that were created in prior\n // transactions and are therefore already part of the note hash tree. We therefore compute the\n // nullification note hash by treating the note as a settled note with the provided note nonce.\n let note_hash_for_nullify = aztec::note::utils::compute_note_hash_for_nullify(\n aztec::note::retrieved_note::RetrievedNote{ \n note, \n contract_address, \n metadata: aztec::note::note_metadata::SettledNoteMetadata::new(note_nonce).into()\n }, \n storage_slot,\n );\n\n let inner_nullifier = $compute_nullifier_unconstrained(note, note_hash_for_nullify);\n\n Option::some(\n aztec::messages::discovery::NoteHashAndNullifier {\n note_hash, inner_nullifier\n }\n )\n }\n },\n );\n }\n\n let if_note_type_id_match_statements = if_note_type_id_match_statements_list.join(quote {});\n\n quote {\n /// Unpacks an array into a note corresponding to `note_type_id` and then computes its note hash\n /// (non-siloed) and inner nullifier (non-siloed) assuming the note has been inserted into the note hash\n /// tree with `note_nonce`.\n ///\n /// The signature of this function notably matches the `aztec::messages::discovery::ComputeNoteHashAndNullifier` type,\n /// and so it can be used to call functions from that module such as `discover_new_messages`, \n /// `do_process_log` and `attempt_note_discovery`.\n ///\n /// This function is automatically injected by the `#[aztec]` macro.\n #[contract_library_method]\n unconstrained fn _compute_note_hash_and_nullifier(\n packed_note: BoundedVec,\n storage_slot: Field,\n note_type_id: Field,\n contract_address: aztec::protocol_types::address::AztecAddress,\n note_nonce: Field,\n ) -> Option {\n $if_note_type_id_match_statements\n else {\n Option::none()\n }\n }\n }\n } else {\n // Contracts with no notes still implement this function to avoid having special-casing, the implementation\n // simply throws immediately.\n quote {\n /// This contract does not use private notes, so this function should never be called as it will\n /// unconditionally fail.\n ///\n /// This function is automatically injected by the `#[aztec]` macro.\n #[contract_library_method]\n unconstrained fn _compute_note_hash_and_nullifier(\n _packed_note: BoundedVec,\n _storage_slot: Field,\n _note_type_id: Field,\n _contract_address: aztec::protocol_types::address::AztecAddress,\n _nonce: Field,\n ) -> Option {\n panic(f\"This contract does not use private notes\")\n }\n }\n }\n}\n\ncomptime fn generate_sync_private_state() -> Quoted {\n // We obtain the `utility` function on the next line instead of directly doing\n // `#[aztec::macros::functions::utility]` in the returned quote because the latter would result in the function\n // attribute having the full path in the ABI. This is undesirable because we use the information in the ABI only\n // to determine whether a function is `private`, `public`, or `utility`.\n let utility = crate::macros::functions::utility;\n\n // All we need to do here is trigger message discovery, but this is already done by the #[utility] macro - we don't\n // need to do anything extra.\n quote {\n #[$utility]\n unconstrained fn sync_private_state() {\n }\n }\n}\n\ncomptime fn generate_process_message() -> Quoted {\n // We obtain the `utility` function on the next line instead of directly doing\n // `#[aztec::macros::functions::utility]` in the returned quote because the latter would result in the function\n // attribute having the full path in the ABI. This is undesirable because we use the information in the ABI only\n // to determine whether a function is `private`, `public`, or `utility`.\n let utility = crate::macros::functions::utility;\n\n // TODO(#15012): Here we use PRIVATE_LOG_CIPHERTEXT_LEN for message ciphertext length. Fix message vs log naming.\n quote {\n #[$utility]\n unconstrained fn process_message(\n message_ciphertext: BoundedVec,\n message_context: aztec::messages::processing::message_context::MessageContext,\n ) {\n aztec::messages::discovery::process_message::do_process_message(\n context.this_address(),\n _compute_note_hash_and_nullifier,\n message_ciphertext,\n message_context,\n );\n }\n }\n}\n" - }, - "97": { - "path": "/home/josh/nargo/github.com/AztecProtocol/aztec-packages/v2.0.2/noir-projects/aztec-nr/aztec/src/macros/dispatch.nr", - "source": "use super::utils::{compute_fn_selector, size_in_fields};\nuse poseidon::poseidon2::Poseidon2Hasher;\nuse std::{collections::umap::UHashMap, hash::BuildHasherDefault, panic};\n\n/// Returns an `fn public_dispatch(...)` function for the given module that's assumed to be an Aztec contract.\npub comptime fn generate_public_dispatch(m: Module) -> Quoted {\n let functions = m.functions();\n let functions =\n functions.filter(|function: FunctionDefinition| function.has_named_attribute(\"public\"));\n\n let unit = get_type::<()>();\n\n let seen_selectors =\n &mut UHashMap::>::default();\n\n let ifs = functions.map(|function: FunctionDefinition| {\n let parameters = function.parameters();\n let return_type = function.return_type();\n\n let selector: Field = compute_fn_selector(function);\n let fn_name = function.name();\n\n // Since function selectors are computed as the first 4 bytes of the hash of the function signature,\n // it's possible to have collisions. With the following check, we ensure it doesn't happen within\n // the same contract.\n if seen_selectors.contains_key(selector) {\n let existing_fn = seen_selectors.get(selector).unwrap();\n panic(\n f\"Public function selector collision detected between functions '{fn_name}' and '{existing_fn}'\",\n );\n }\n seen_selectors.insert(selector, fn_name);\n\n let mut parameters_size = 0;\n for param in parameters {\n parameters_size += size_in_fields(param.1);\n }\n\n let initial_read = if parameters.len() == 0 {\n quote {}\n } else {\n // The initial calldata_copy offset is 1 to skip the Field selector\n // The expected calldata is the serialization of\n // - FunctionSelector: the selector of the function intended to dispatch\n // - Parameters: the parameters of the function intended to dispatch\n // That is, exactly what is expected for a call to the target function,\n // but with a selector added at the beginning.\n quote {\n let input_calldata: [Field; $parameters_size] = dep::aztec::context::public_context::calldata_copy(1, $parameters_size);\n let mut reader = dep::aztec::protocol_types::utils::reader::Reader::new(input_calldata);\n }\n };\n\n let parameter_index: &mut u32 = &mut 0;\n let reads = parameters.map(|param: (Quoted, Type)| {\n let parameter_index_value = *parameter_index;\n let param_name = f\"arg{parameter_index_value}\".quoted_contents();\n let param_type = param.1;\n let read = quote {\n let $param_name: $param_type = reader.read_struct(dep::aztec::protocol_types::traits::Deserialize::deserialize);\n };\n *parameter_index += 1;\n quote { $read }\n });\n let read = reads.join(quote { });\n\n let mut args = &[];\n for parameter_index in 0..parameters.len() {\n let param_name = f\"arg{parameter_index}\".quoted_contents();\n args = args.push_back(quote { $param_name });\n }\n\n let args = args.join(quote { , });\n // name of the function is assigned just before the call so debug metadata doesn't span most of this macro when figuring out where the call comes from.\n let name = function.name();\n let call = quote { $name($args) };\n\n let return_code = if return_type == unit {\n quote {\n $call;\n // Force early return.\n dep::aztec::context::public_context::avm_return([]);\n }\n } else {\n quote {\n let return_value = dep::aztec::protocol_types::traits::Serialize::serialize($call);\n dep::aztec::context::public_context::avm_return(return_value.as_slice());\n }\n };\n\n let if_ = quote {\n if selector == $selector {\n $initial_read\n $read\n $return_code\n }\n };\n if_\n });\n\n if ifs.len() == 0 {\n // No dispatch function if there are no public functions\n quote {}\n } else {\n let ifs = ifs.push_back(quote { panic(f\"Unknown selector {selector}\") });\n let dispatch = ifs.join(quote { });\n\n let body = quote {\n // We mark this as public because our whole system depends on public\n // functions having this attribute. However, the public MACRO will\n // handle the public_dispatch function specially and do nothing.\n #[public]\n pub unconstrained fn public_dispatch(selector: Field) {\n $dispatch\n }\n };\n\n body\n }\n}\n\ncomptime fn get_type() -> Type {\n let t: T = std::mem::zeroed();\n std::meta::type_of(t)\n}\n" - } - } -} From 5f2a85b9d5aa947f4b609dcc9a76df5d7dbfa436 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Fri, 19 Sep 2025 11:10:32 -0400 Subject: [PATCH 7/8] add artifacts --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 234f4f6..334d583 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,4 @@ blob-report/ playwright/.cache/ .env +app/artifacts/ \ No newline at end of file From 2bf24ab05483f0df06ea4201e46a9a317a4204a8 Mon Sep 17 00:00:00 2001 From: Josh Crites Date: Fri, 19 Sep 2025 11:12:37 -0400 Subject: [PATCH 8/8] update artifact script --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bc41c96..fd80a33 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "clean": "rm -rf app/dist contracts/target contracts/codegenCache.json", "compile-contracts": "cd contracts && ${AZTEC_NARGO:-aztec-nargo} compile && ${AZTEC_POSTPROCESS:-aztec-postprocess-contract}", "codegen-contracts": "cd contracts && ${AZTEC_BUILDER:-aztec} codegen ./target -o ./target", - "copy-artifacts": "cp contracts/target/*.json contracts/target/*.ts app/artifacts", + "copy-artifacts": "mkdir -p app/artifacts && cp contracts/target/*.json contracts/target/*.ts app/artifacts", "build-contracts": "yarn clean && yarn compile-contracts && yarn codegen-contracts && yarn copy-artifacts", "deploy-contracts": "node --experimental-transform-types scripts/deploy.ts", "dev": "webpack serve --mode development",