diff --git a/.github/workflows/mirror_noir_subrepo.yml b/.github/workflows/mirror_noir_subrepo.yml index 651f2e23134..54b45855e72 100644 --- a/.github/workflows/mirror_noir_subrepo.yml +++ b/.github/workflows/mirror_noir_subrepo.yml @@ -86,7 +86,7 @@ jobs: # clone noir repo for manipulations, we use aztec bot token for writeability git clone https://x-access-token:${{ secrets.AZTEC_BOT_GITHUB_TOKEN }}@github.com/noir-lang/noir.git noir-repo - # reset_pr: Reset aztec-packages staging. If no PR, this is the PR branch. + # reset_noir_staging_branch: Reset aztec-packages staging. If no PR, this is the PR branch. function reset_noir_staging_branch() { cd noir-repo git checkout $STAGING_BRANCH || git checkout -b $STAGING_BRANCH @@ -117,7 +117,7 @@ jobs: cd noir-repo git fetch # see recent change git checkout $BRANCH || git checkout -b $BRANCH - git merge -Xtheirs origin/$STAGING_BRANCH -m "$COMMIT_MESSAGE" + git merge -Xours origin/$STAGING_BRANCH -m "$COMMIT_MESSAGE" git push origin $BRANCH cd .. } @@ -131,7 +131,9 @@ jobs: run: | set -xue # print commands # Formatted for updating the PR, overrides for release-please commit message parsing - PR_BODY="""BEGIN_COMMIT_OVERRIDE + PR_BODY=""" + Automated pull of Noir development from [aztec-packages](https://github.com/AztecProtocol/aztec-packages). + BEGIN_COMMIT_OVERRIDE $(cat .PR_BODY_MESSAGE) END_COMMIT_OVERRIDE""" # for cross-opening PR in noir repo, we use aztecbot's token @@ -139,5 +141,6 @@ jobs: if [[ "$PR_URL" == "" ]]; then gh pr create --repo noir-lang/noir --title "feat: Sync from aztec-packages" --body "$PR_BODY" --base master --head aztec-packages else + echo "Updating existing PR." gh pr edit "$PR_URL" --body "$PR_BODY" fi diff --git a/.github/workflows/pull_noir.yml b/.github/workflows/pull_noir.yml new file mode 100644 index 00000000000..8ee023b5cb7 --- /dev/null +++ b/.github/workflows/pull_noir.yml @@ -0,0 +1,130 @@ +# Create a pull request from current Noir master. +name: Pull from noir repo + +# Don't allow multiple of these running at once: +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: false +on: + # o + workflow_dispatch: {} + +jobs: + mirror_repo: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + token: ${{ secrets.AZTEC_BOT_GITHUB_TOKEN }} + + - name: Check for existing PR + run: | + set -xue # print commands + # Enable gh executable. We spread out the API requests between the github actions bot token, and aztecbot + export GH_TOKEN="${{ secrets.GITHUB_TOKEN }}" + # Do we have a PR active? + PR_URL=$(gh pr list --repo AztecProtocol/aztec-packages --head sync-noir --json url --jq ".[0].url") + echo "PR_URL=$PR_URL" >> $GITHUB_ENV + # What was our last merge on noir side? + BASE_NOIR_COMMIT=`gh pr list --repo=noir-lang/noir --state merged --head aztec-packages --json mergeCommit --jq=.[0].mergeCommit.oid` + echo "BASE_NOIR_COMMIT=$BASE_NOIR_COMMIT" >> $GITHUB_ENV + # What was our last sync on aztec side? + BASE_AZTEC_COMMIT=`curl https://raw.githubusercontent.com/noir-lang/noir/master/.aztec-sync-commit` + echo "BASE_AZTEC_COMMIT=$BASE_AZTEC_COMMIT" >> $GITHUB_ENV + + - name: Generate PR body + run: | + # clone noir repo for manipulations, we use aztec bot token for writeability + git clone https://x-access-token:${{ secrets.AZTEC_BOT_GITHUB_TOKEN }}@github.com/noir-lang/noir.git noir-repo + + set -xue # print commands + # compute_commit_message: Create a filtered git log for release-please changelog / metadata + function compute_commit_message() { + cd noir-repo + # Create a filtered git log for release-please changelog / metadata + RAW_MESSAGE=$(git log --pretty=format:"%s" $BASE_NOIR_COMMIT..HEAD || true) + # Fix Noir PR links and output message + echo "$RAW_MESSAGE" | sed -E 's/\(#([0-9]+)\)/(https:\/\/github.com\/noir-lang\/noir\/pull\/\1)/g' + cd .. + } + echo "$(compute_commit_message)" >> .PR_BODY_MESSAGE + + - name: Set git configure for commits + run: | + # identify ourselves, needed to commit + git config --global user.name AztecBot + git config --global user.email tech@aztecprotocol.com + + # We push using git subrepo (https://github.com/ingydotnet/git-subrepo) + # and push all Aztec commits as a single commit with metadata. + - name: Push to branch + run: | + set -xue # print commands + SUBREPO_PATH=noir/noir-repo + BRANCH=sync-noir + if [[ "$PR_URL" == "" ]]; then + # if no staging branch, we can overwrite + STAGING_BRANCH=$BRANCH + else + # otherwise we first reset our staging branch + STAGING_BRANCH=$BRANCH-staging + fi + + # Get the last sync PR's last commit state + COMMIT_MESSAGE=$(cat .PR_BODY_MESSAGE) + LINES=$(echo $COMMIT_MESSAGE | wc -l) + + function force_sync_staging() { + # reset to last noir merge + git checkout $STAGING_BRANCH || git checkout -b $STAGING_BRANCH + git reset --hard "$BASE_AZTEC_COMMIT" + # Reset our branch to our expected target + git push origin $STAGING_BRANCH --force + # force gitrepo to point to the right HEAD (we ignore .gitrepo contents otherwise) + git config --file="$SUBREPO_PATH/.gitrepo" subrepo.commit "$BASE_NOIR_COMMIT" + # we need to commit for git-subrepo + git commit -am "[$LINES changes] $COMMIT_MESSAGE" + if ./scripts/git-subrepo/lib/git-subrepo pull --force $SUBREPO_PATH --branch=master; then + git reset --soft "$BASE_AZTEC_COMMIT" + # We don't really need the sync commit on our side, and don't need .gitrepo at all except just in time for the command. + git checkout origin/master -- noir/noir-repo/.aztec-sync-commit noir/noir-repo/.gitrepo + git commit -am "[$LINES changes] $COMMIT_MESSAGE" + git push origin $STAGING_BRANCH --force + else + echo "Problems syncing noir. Needs manual attention, might be a merge conflict." + exit 1 + fi + } + # merge_staging_branch: Merge our staging branch into aztec-packages. + function merge_staging_branch() { + # Fix PR branch + git fetch # see recent change + git checkout $BRANCH || git checkout -b $BRANCH + git merge -Xours origin/$STAGING_BRANCH -m "$COMMIT_MESSAGE" + git push origin $BRANCH + } + force_sync_staging + if [[ "$PR_URL" != "" ]]; then + merge_staging_branch + fi + + - name: Update PR + run: | + set -xue # print commands + # Formatted for updating the PR, overrides for release-please commit message parsing + PR_BODY=""" + Automated pull of development from the [noir](https://github.com/noir-lang/noir) programming language, a dependency of Aztec. + BEGIN_COMMIT_OVERRIDE + $(cat .PR_BODY_MESSAGE) + END_COMMIT_OVERRIDE""" + # for cross-opening PR in noir repo, we use aztecbot's token + export GH_TOKEN=${{ secrets.AZTEC_BOT_GITHUB_TOKEN }} + if [[ "$PR_URL" == "" ]]; then + gh pr create --repo AztecProtocol/aztec-packages --title "feat: Sync from noir" --body "$PR_BODY" --base master --head sync-noir + else + echo "Updating existing PR." + gh pr edit "$PR_URL" --body "$PR_BODY" + fi diff --git a/.release-please-manifest.json b/.release-please-manifest.json index be5c3462ef5..6d2f484e77a 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,7 +1,7 @@ { - ".": "0.26.6", - "yarn-project/cli": "0.26.6", - "yarn-project/aztec": "0.26.6", - "barretenberg": "0.26.6", - "barretenberg/ts": "0.26.6" + ".": "0.27.1", + "yarn-project/cli": "0.27.1", + "yarn-project/aztec": "0.27.1", + "barretenberg": "0.27.1", + "barretenberg/ts": "0.27.1" } diff --git a/CHANGELOG.md b/CHANGELOG.md index e8f45aaea9e..57c7e0b6e12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,71 @@ # Changelog +## [0.27.1](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.27.0...aztec-packages-v0.27.1) (2024-03-12) + + +### Features + +* Further ClientIVC breakdown ([#5146](https://github.com/AztecProtocol/aztec-packages/issues/5146)) ([c8e1cb8](https://github.com/AztecProtocol/aztec-packages/commit/c8e1cb8c6bc07bda2cf4aec3b5d2b2120bfafd01)) +* Nullifier non membership ([#5152](https://github.com/AztecProtocol/aztec-packages/issues/5152)) ([426bd6d](https://github.com/AztecProtocol/aztec-packages/commit/426bd6d2490d59126a31de91cd783a76b0dfdc84)) + + +### Bug Fixes + +* Increase the json limit for RPC requests ([#5161](https://github.com/AztecProtocol/aztec-packages/issues/5161)) ([419958c](https://github.com/AztecProtocol/aztec-packages/commit/419958c7c9abc40a5d83739a74e1ea0797b4f474)) +* Move timers for ClientIVC breakdown ([#5145](https://github.com/AztecProtocol/aztec-packages/issues/5145)) ([5457edb](https://github.com/AztecProtocol/aztec-packages/commit/5457edb3ddd29df96906f98fb05469a26a644654)) + + +### Miscellaneous + +* **boxes:** Adding clone contract option ([#4980](https://github.com/AztecProtocol/aztec-packages/issues/4980)) ([a427aa5](https://github.com/AztecProtocol/aztec-packages/commit/a427aa533216187a23b0697a2d91a9d89fb1e0eb)) +* Share code between provers ([#4655](https://github.com/AztecProtocol/aztec-packages/issues/4655)) ([ef10d65](https://github.com/AztecProtocol/aztec-packages/commit/ef10d6576aa9e89eece5a40669c425ae7987ee8a)) + +## [0.27.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.26.6...aztec-packages-v0.27.0) (2024-03-12) + + +### ⚠ BREAKING CHANGES + +* Remove open keyword from Noir ([#4967](https://github.com/AztecProtocol/aztec-packages/issues/4967)) + +### Features + +* Add api for inclusion proof of outgoing message in block [#4562](https://github.com/AztecProtocol/aztec-packages/issues/4562) ([#4899](https://github.com/AztecProtocol/aztec-packages/issues/4899)) ([26d2643](https://github.com/AztecProtocol/aztec-packages/commit/26d26437022567e2d54052f21b1c937259f26c94)) +* **avm-simulator:** External calls + integration ([#5051](https://github.com/AztecProtocol/aztec-packages/issues/5051)) ([dde33f4](https://github.com/AztecProtocol/aztec-packages/commit/dde33f498b0432e5c4adce84191d3517176077dd)) +* **avm-simulator:** External static calls + integration ([#5089](https://github.com/AztecProtocol/aztec-packages/issues/5089)) ([428d950](https://github.com/AztecProtocol/aztec-packages/commit/428d950ec1f2dc7b129b61380d7d1426a7b7441d)) +* **avm:** Equivalence check between Main trace and Mem trace ([#5032](https://github.com/AztecProtocol/aztec-packages/issues/5032)) ([7f216eb](https://github.com/AztecProtocol/aztec-packages/commit/7f216eb064fc95791de1286c7695e89575e02b40)), closes [#4955](https://github.com/AztecProtocol/aztec-packages/issues/4955) +* **avm:** Fix some Brillig problems ([#5091](https://github.com/AztecProtocol/aztec-packages/issues/5091)) ([07dd821](https://github.com/AztecProtocol/aztec-packages/commit/07dd8215dffd2c3c6d22e0f430f5072b4ff7c763)) +* Initial integration avm prover ([#4878](https://github.com/AztecProtocol/aztec-packages/issues/4878)) ([2e2554e](https://github.com/AztecProtocol/aztec-packages/commit/2e2554e6a055ff7124e18d1566371d5d108c5d5d)) +* Noir pull action ([#5062](https://github.com/AztecProtocol/aztec-packages/issues/5062)) ([b2d7d14](https://github.com/AztecProtocol/aztec-packages/commit/b2d7d14996722c50c769dfcd9f7b0c324b2e3a7e)) +* Restore contract inclusion proofs ([#5141](https://github.com/AztecProtocol/aztec-packages/issues/5141)) ([a39cd61](https://github.com/AztecProtocol/aztec-packages/commit/a39cd6192022cd14b824d159b4262c10669b7de3)) +* Update the core of SMT Circuit class ([#5096](https://github.com/AztecProtocol/aztec-packages/issues/5096)) ([1519d3b](https://github.com/AztecProtocol/aztec-packages/commit/1519d3b07664f471a43d3f6bbb3dbe2d387289fc)) +* Updating archiver with new inbox ([#5025](https://github.com/AztecProtocol/aztec-packages/issues/5025)) ([f6d17c9](https://github.com/AztecProtocol/aztec-packages/commit/f6d17c972d2cf9c5aa468c8cf954431b42240f87)), closes [#4828](https://github.com/AztecProtocol/aztec-packages/issues/4828) + + +### Bug Fixes + +* Duplicate factory code temporarily to unblock ([#5099](https://github.com/AztecProtocol/aztec-packages/issues/5099)) ([8b10600](https://github.com/AztecProtocol/aztec-packages/commit/8b1060013e35a3b4e73d75b18bb2a8c16985e662)) +* Remove hard coded canonical gas address ([#5106](https://github.com/AztecProtocol/aztec-packages/issues/5106)) ([dc2fd9e](https://github.com/AztecProtocol/aztec-packages/commit/dc2fd9e584d987bdc5d2d7a117b76cb50a20b969)) + + +### Miscellaneous + +* **avm-simulator:** Enable compressed strings unencrypted log test ([#5083](https://github.com/AztecProtocol/aztec-packages/issues/5083)) ([8f7519b](https://github.com/AztecProtocol/aztec-packages/commit/8f7519bdacd3c8b3a91d4361e4648688ec5d47bc)) +* **avm-simulator:** Formatting and fixes ([#5092](https://github.com/AztecProtocol/aztec-packages/issues/5092)) ([b3fa084](https://github.com/AztecProtocol/aztec-packages/commit/b3fa08469658bd7220863e514d8e4b069d40a00f)) +* **AVM:** Negative unit tests for inter table relations ([#5143](https://github.com/AztecProtocol/aztec-packages/issues/5143)) ([a74dccb](https://github.com/AztecProtocol/aztec-packages/commit/a74dccbdef0939b77978ddec3875b1afc2d0b530)), closes [#5033](https://github.com/AztecProtocol/aztec-packages/issues/5033) +* Aztec-macros refactor ([#5127](https://github.com/AztecProtocol/aztec-packages/issues/5127)) ([2195441](https://github.com/AztecProtocol/aztec-packages/commit/2195441afde4d6e78ad0c6027d0a7dbc8671817d)) +* **ci:** Fail on clippy warnings in noir ([#5101](https://github.com/AztecProtocol/aztec-packages/issues/5101)) ([54af648](https://github.com/AztecProtocol/aztec-packages/commit/54af648b5928b200cd40c8d90a21c155bc2e43bd)) +* Extract bb binary in bs fast ([#5128](https://github.com/AztecProtocol/aztec-packages/issues/5128)) ([9ca41ef](https://github.com/AztecProtocol/aztec-packages/commit/9ca41ef6951566622ab9e68924958dbb66b160df)) +* Increase bytecode size limit ([#5098](https://github.com/AztecProtocol/aztec-packages/issues/5098)) ([53b2381](https://github.com/AztecProtocol/aztec-packages/commit/53b238190a9d123c292c3079bb23ed2ecff824c8)) +* Increase permitted bytecode size ([#5136](https://github.com/AztecProtocol/aztec-packages/issues/5136)) ([6865c34](https://github.com/AztecProtocol/aztec-packages/commit/6865c34fccfd74f83525c8d47b5c516d1696c432)) +* Join-split example Part 2 ([#5016](https://github.com/AztecProtocol/aztec-packages/issues/5016)) ([0718320](https://github.com/AztecProtocol/aztec-packages/commit/07183200b136ec39087c2b35e5799686319d561b)) +* Move alpine containers to ubuntu ([#5026](https://github.com/AztecProtocol/aztec-packages/issues/5026)) ([d483e67](https://github.com/AztecProtocol/aztec-packages/commit/d483e678e4b2558f74c3b79083cf2257d6eafe0c)), closes [#4708](https://github.com/AztecProtocol/aztec-packages/issues/4708) +* Nicer snapshots ([#5133](https://github.com/AztecProtocol/aztec-packages/issues/5133)) ([9a737eb](https://github.com/AztecProtocol/aztec-packages/commit/9a737eb9674a757ca3ac9c7a6607ed0f39304d52)) +* Pin foundry ([#5151](https://github.com/AztecProtocol/aztec-packages/issues/5151)) ([69bd7dd](https://github.com/AztecProtocol/aztec-packages/commit/69bd7dd45af6b197b23c25dc883a1a5485955203)) +* Remove old contract deployment flow ([#4970](https://github.com/AztecProtocol/aztec-packages/issues/4970)) ([6d15947](https://github.com/AztecProtocol/aztec-packages/commit/6d1594736e96cd744ea691a239fcd3a46bdade60)) +* Remove open keyword from Noir ([#4967](https://github.com/AztecProtocol/aztec-packages/issues/4967)) ([401557e](https://github.com/AztecProtocol/aztec-packages/commit/401557e1119c1dc4968c16f51381f3306ed8e876)) +* Run nargo fmt on each nargo project ([#5102](https://github.com/AztecProtocol/aztec-packages/issues/5102)) ([b327254](https://github.com/AztecProtocol/aztec-packages/commit/b32725421171f39d510619c8f78a39c182738725)) +* Use context interface in mark-as-initialized ([#5142](https://github.com/AztecProtocol/aztec-packages/issues/5142)) ([932c1d5](https://github.com/AztecProtocol/aztec-packages/commit/932c1d5006ad793ee05ed7cdbae05d59c04334d8)) + ## [0.26.6](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.26.5...aztec-packages-v0.26.6) (2024-03-08) diff --git a/avm-transpiler/Cargo.lock b/avm-transpiler/Cargo.lock index 43287fcb588..8cc69462e76 100644 --- a/avm-transpiler/Cargo.lock +++ b/avm-transpiler/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "acir" -version = "0.40.0" +version = "0.41.0" dependencies = [ "acir_field", "base64 0.21.7", @@ -17,7 +17,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "0.40.0" +version = "0.41.0" dependencies = [ "ark-bn254", "ark-ff", @@ -30,7 +30,7 @@ dependencies = [ [[package]] name = "acvm" -version = "0.40.0" +version = "0.41.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -43,7 +43,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "0.40.0" +version = "0.41.0" dependencies = [ "acir", "blake2", @@ -159,7 +159,7 @@ dependencies = [ [[package]] name = "arena" -version = "0.24.0" +version = "0.25.0" [[package]] name = "ark-bn254" @@ -312,7 +312,7 @@ dependencies = [ [[package]] name = "aztec_macros" -version = "0.24.0" +version = "0.25.0" dependencies = [ "convert_case", "iter-extended", @@ -395,7 +395,7 @@ dependencies = [ [[package]] name = "brillig" -version = "0.40.0" +version = "0.41.0" dependencies = [ "acir_field", "serde", @@ -403,7 +403,7 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "0.40.0" +version = "0.41.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -776,7 +776,7 @@ dependencies = [ [[package]] name = "fm" -version = "0.24.0" +version = "0.25.0" dependencies = [ "codespan-reporting", "serde", @@ -954,7 +954,7 @@ dependencies = [ [[package]] name = "iter-extended" -version = "0.24.0" +version = "0.25.0" [[package]] name = "itertools" @@ -1053,7 +1053,7 @@ dependencies = [ [[package]] name = "noirc_abi" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "iter-extended", @@ -1068,7 +1068,7 @@ dependencies = [ [[package]] name = "noirc_driver" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "aztec_macros", @@ -1081,7 +1081,6 @@ dependencies = [ "noirc_errors", "noirc_evaluator", "noirc_frontend", - "noirc_macros", "rust-embed", "serde", "thiserror", @@ -1090,7 +1089,7 @@ dependencies = [ [[package]] name = "noirc_errors" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "base64 0.21.7", @@ -1108,7 +1107,7 @@ dependencies = [ [[package]] name = "noirc_evaluator" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "fxhash", @@ -1124,7 +1123,7 @@ dependencies = [ [[package]] name = "noirc_frontend" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "arena", @@ -1144,17 +1143,9 @@ dependencies = [ "tracing", ] -[[package]] -name = "noirc_macros" -version = "0.24.0" -dependencies = [ - "iter-extended", - "noirc_frontend", -] - [[package]] name = "noirc_printable_type" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "iter-extended", diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs index 093d90a8711..c1123799dba 100644 --- a/avm-transpiler/src/transpile.rs +++ b/avm-transpiler/src/transpile.rs @@ -239,7 +239,10 @@ fn handle_foreign_call( inputs: &Vec, ) { match function { - "avmOpcodeCall" => handle_external_call(avm_instrs, destinations, inputs), + "avmOpcodeCall" => handle_external_call(avm_instrs, destinations, inputs, AvmOpcode::CALL), + "avmOpcodeStaticCall" => { + handle_external_call(avm_instrs, destinations, inputs, AvmOpcode::STATICCALL) + } "amvOpcodeEmitUnencryptedLog" => { handle_emit_unencrypted_log(avm_instrs, destinations, inputs) } @@ -280,10 +283,11 @@ fn handle_external_call( avm_instrs: &mut Vec, destinations: &Vec, inputs: &Vec, + opcode: AvmOpcode, ) { if destinations.len() != 2 || inputs.len() != 4 { panic!( - "Transpiler expects ForeignCall::CALL to have 2 destinations and 4 inputs, got {} and {}. + "Transpiler expects ForeignCall (Static)Call to have 2 destinations and 4 inputs, got {} and {}. Make sure your call instructions's input/return arrays have static length (`[Field; ]`)!", destinations.len(), inputs.len() @@ -326,7 +330,7 @@ fn handle_external_call( _ => panic!("Call instruction's success destination should be a basic MemoryAddress",), }; avm_instrs.push(AvmInstruction { - opcode: AvmOpcode::CALL, + opcode: opcode, indirect: Some(0b01101), // (left to right) selector direct, ret offset INDIRECT, args offset INDIRECT, address offset direct, gas offset INDIRECT operands: vec![ AvmOperand::U32 { value: gas_offset }, diff --git a/avm-transpiler/src/transpile_contract.rs b/avm-transpiler/src/transpile_contract.rs index bcf848ab88e..77528a46057 100644 --- a/avm-transpiler/src/transpile_contract.rs +++ b/avm-transpiler/src/transpile_contract.rs @@ -4,7 +4,6 @@ use regex::Regex; use serde::{Deserialize, Serialize}; use acvm::acir::circuit::Circuit; -use noirc_driver::ContractFunctionType; use crate::transpile::brillig_to_avm; use crate::utils::extract_brillig_from_acir; @@ -40,8 +39,8 @@ pub struct CompiledAcirContract { #[derive(Debug, Serialize, Deserialize)] pub struct AvmContractFunction { pub name: String, - pub function_type: ContractFunctionType, - pub is_internal: bool, + pub is_unconstrained: bool, + pub custom_attributes: Vec, pub abi: serde_json::Value, pub bytecode: String, // base64 pub debug_symbols: serde_json::Value, @@ -52,8 +51,8 @@ pub struct AvmContractFunction { #[derive(Debug, Serialize, Deserialize)] pub struct AcirContractFunction { pub name: String, - pub function_type: ContractFunctionType, - pub is_internal: bool, + pub is_unconstrained: bool, + pub custom_attributes: Vec, pub abi: serde_json::Value, #[serde( serialize_with = "Circuit::serialize_circuit_base64", @@ -82,7 +81,9 @@ impl From for TranspiledContract { let re = Regex::new(r"avm_.*$").unwrap(); for function in contract.functions { // TODO(4269): once functions are tagged for transpilation to AVM, check tag - if function.function_type == ContractFunctionType::Open + if function + .custom_attributes + .contains(&"aztec(public-vm)".to_string()) && re.is_match(function.name.as_str()) { info!( @@ -99,8 +100,8 @@ impl From for TranspiledContract { // Push modified function entry to ABI functions.push(AvmOrAcirContractFunction::Avm(AvmContractFunction { name: function.name, - function_type: function.function_type, - is_internal: function.is_internal, + is_unconstrained: function.is_unconstrained, + custom_attributes: function.custom_attributes, abi: function.abi, bytecode: base64::prelude::BASE64_STANDARD.encode(avm_bytecode), debug_symbols: function.debug_symbols, diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index d06c3b8bfa1..e81d3d0d0d4 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = 7ceeec61b9abb42f6785b8da5b822046c3967308 - parent = d483e678e4b2558f74c3b79083cf2257d6eafe0c + commit = 890e262b4bc4d19d2e3e00971d89fb22d447e302 + parent = 401557e1119c1dc4968c16f51381f3306ed8e876 method = merge cmdver = 0.4.6 diff --git a/barretenberg/CHANGELOG.md b/barretenberg/CHANGELOG.md index d6f4bfe1fe5..007fb71e3a0 100644 --- a/barretenberg/CHANGELOG.md +++ b/barretenberg/CHANGELOG.md @@ -1,5 +1,40 @@ # Changelog +## [0.27.1](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.27.0...barretenberg-v0.27.1) (2024-03-12) + + +### Features + +* Further ClientIVC breakdown ([#5146](https://github.com/AztecProtocol/aztec-packages/issues/5146)) ([c8e1cb8](https://github.com/AztecProtocol/aztec-packages/commit/c8e1cb8c6bc07bda2cf4aec3b5d2b2120bfafd01)) + + +### Bug Fixes + +* Move timers for ClientIVC breakdown ([#5145](https://github.com/AztecProtocol/aztec-packages/issues/5145)) ([5457edb](https://github.com/AztecProtocol/aztec-packages/commit/5457edb3ddd29df96906f98fb05469a26a644654)) + + +### Miscellaneous + +* Share code between provers ([#4655](https://github.com/AztecProtocol/aztec-packages/issues/4655)) ([ef10d65](https://github.com/AztecProtocol/aztec-packages/commit/ef10d6576aa9e89eece5a40669c425ae7987ee8a)) + +## [0.27.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.26.6...barretenberg-v0.27.0) (2024-03-12) + + +### Features + +* **avm:** Equivalence check between Main trace and Mem trace ([#5032](https://github.com/AztecProtocol/aztec-packages/issues/5032)) ([7f216eb](https://github.com/AztecProtocol/aztec-packages/commit/7f216eb064fc95791de1286c7695e89575e02b40)), closes [#4955](https://github.com/AztecProtocol/aztec-packages/issues/4955) +* Initial integration avm prover ([#4878](https://github.com/AztecProtocol/aztec-packages/issues/4878)) ([2e2554e](https://github.com/AztecProtocol/aztec-packages/commit/2e2554e6a055ff7124e18d1566371d5d108c5d5d)) +* Update the core of SMT Circuit class ([#5096](https://github.com/AztecProtocol/aztec-packages/issues/5096)) ([1519d3b](https://github.com/AztecProtocol/aztec-packages/commit/1519d3b07664f471a43d3f6bbb3dbe2d387289fc)) + + +### Miscellaneous + +* **AVM:** Negative unit tests for inter table relations ([#5143](https://github.com/AztecProtocol/aztec-packages/issues/5143)) ([a74dccb](https://github.com/AztecProtocol/aztec-packages/commit/a74dccbdef0939b77978ddec3875b1afc2d0b530)), closes [#5033](https://github.com/AztecProtocol/aztec-packages/issues/5033) +* Extract bb binary in bs fast ([#5128](https://github.com/AztecProtocol/aztec-packages/issues/5128)) ([9ca41ef](https://github.com/AztecProtocol/aztec-packages/commit/9ca41ef6951566622ab9e68924958dbb66b160df)) +* Join-split example Part 2 ([#5016](https://github.com/AztecProtocol/aztec-packages/issues/5016)) ([0718320](https://github.com/AztecProtocol/aztec-packages/commit/07183200b136ec39087c2b35e5799686319d561b)) +* Move alpine containers to ubuntu ([#5026](https://github.com/AztecProtocol/aztec-packages/issues/5026)) ([d483e67](https://github.com/AztecProtocol/aztec-packages/commit/d483e678e4b2558f74c3b79083cf2257d6eafe0c)), closes [#4708](https://github.com/AztecProtocol/aztec-packages/issues/4708) +* Pin foundry ([#5151](https://github.com/AztecProtocol/aztec-packages/issues/5151)) ([69bd7dd](https://github.com/AztecProtocol/aztec-packages/commit/69bd7dd45af6b197b23c25dc883a1a5485955203)) + ## [0.26.6](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.26.5...barretenberg-v0.26.6) (2024-03-08) diff --git a/barretenberg/cpp/CMakeLists.txt b/barretenberg/cpp/CMakeLists.txt index 8a7cd0012d8..dd4aa5cda50 100644 --- a/barretenberg/cpp/CMakeLists.txt +++ b/barretenberg/cpp/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.24 FATAL_ERROR) project( Barretenberg DESCRIPTION "BN254 elliptic curve library, and PLONK SNARK prover" - VERSION 0.26.6 # x-release-please-version + VERSION 0.27.1 # x-release-please-version LANGUAGES CXX C ) # Insert version into `bb` config file diff --git a/barretenberg/cpp/bootstrap_cache.sh b/barretenberg/cpp/bootstrap_cache.sh index a739a6cab66..7b0a56ec716 100755 --- a/barretenberg/cpp/bootstrap_cache.sh +++ b/barretenberg/cpp/bootstrap_cache.sh @@ -4,9 +4,13 @@ set -eu cd "$(dirname "$0")" source ../../build-system/scripts/setup_env '' '' mainframe_$USER > /dev/null +echo -e "\033[1mRetrieving bb binary from remote cache...\033[0m" +extract_repo barretenberg-x86_64-linux-clang \ + /usr/src/barretenberg/cpp/build/bin ./build + echo -e "\033[1mRetrieving bb.wasm from remote cache...\033[0m" extract_repo barretenberg-wasm-linux-clang \ - /usr/src/barretenberg/cpp/build-wasm/bin ./cpp/build-wasm \ - /usr/src/barretenberg/cpp/build-wasm-threads/bin ./cpp/build-wasm-threads + /usr/src/barretenberg/cpp/build-wasm/bin ./build-wasm \ + /usr/src/barretenberg/cpp/build-wasm-threads/bin ./build-wasm-threads remove_old_images barretenberg-wasm-linux-clang diff --git a/barretenberg/cpp/pil/avm/avm_main.pil b/barretenberg/cpp/pil/avm/avm_main.pil index 81f51fe7e82..37a32778bdb 100644 --- a/barretenberg/cpp/pil/avm/avm_main.pil +++ b/barretenberg/cpp/pil/avm/avm_main.pil @@ -62,7 +62,7 @@ namespace avm_main(256); pol commit mem_op_a; pol commit mem_op_b; pol commit mem_op_c; - + // Read-write flag per intermediate register: Read = 0, Write = 1 pol commit rwa; pol commit rwb; @@ -104,7 +104,7 @@ namespace avm_main(256); rwa * (1 - rwa) = 0; rwb * (1 - rwb) = 0; rwc * (1 - rwc) = 0; - + // TODO: Constrain rwa, rwb, rwc to u32 type and 0 <= in_tag <= 6 // Relation for division over the finite field @@ -189,8 +189,8 @@ namespace avm_main(256); // TODO: we want to set an initial number for the reserved memory of the jump pointer // Inter-table Constraints - - #[equiv_tag_err] + + #[INCL_MAIN_TAG_ERR] avm_mem.m_tag_err {avm_mem.m_clk} in tag_err {clk}; // Predicate to activate the copy of intermediate registers to ALU table. If tag_err == 1, @@ -198,7 +198,7 @@ namespace avm_main(256); // TODO: when division is moved to the alu, we will need to add the selector in the list below: alu_sel = (sel_op_add + sel_op_sub + sel_op_mul + sel_op_not + sel_op_eq) * (1 - tag_err); - #[equiv_inter_reg_alu] + #[PERM_MAIN_ALU] alu_sel {clk, ia, ib, ic, sel_op_add, sel_op_sub, sel_op_mul, sel_op_eq, sel_op_not, in_tag} @@ -207,5 +207,17 @@ namespace avm_main(256); avm_alu.alu_op_add, avm_alu.alu_op_sub, avm_alu.alu_op_mul, avm_alu.alu_op_eq, avm_alu.alu_op_not, avm_alu.alu_in_tag}; - // TODO: Map memory trace with intermediate register values whenever there is no tag error, sthg like: - // mem_op_a * (1 - tag_err) {mem_idx_a, clk, ia, rwa} IS m_sub_clk == 0 && 1 - m_tag_err {m_addr, m_clk, m_val, m_rw} + #[PERM_MAIN_MEM_A] + mem_op_a {clk, mem_idx_a, ia, rwa, in_tag} + is + avm_mem.m_op_a {avm_mem.m_clk, avm_mem.m_addr, avm_mem.m_val, avm_mem.m_rw, avm_mem.m_in_tag}; + + #[PERM_MAIN_MEM_B] + mem_op_b {clk, mem_idx_b, ib, rwb, in_tag} + is + avm_mem.m_op_b {avm_mem.m_clk, avm_mem.m_addr, avm_mem.m_val, avm_mem.m_rw, avm_mem.m_in_tag}; + + #[PERM_MAIN_MEM_C] + mem_op_c {clk, mem_idx_c, ic, rwc, in_tag} + is + avm_mem.m_op_c {avm_mem.m_clk, avm_mem.m_addr, avm_mem.m_val, avm_mem.m_rw, avm_mem.m_in_tag}; \ No newline at end of file diff --git a/barretenberg/cpp/pil/avm/avm_mem.pil b/barretenberg/cpp/pil/avm/avm_mem.pil index a974351dcf5..356b05ee0ce 100644 --- a/barretenberg/cpp/pil/avm/avm_mem.pil +++ b/barretenberg/cpp/pil/avm/avm_mem.pil @@ -15,6 +15,11 @@ namespace avm_mem(256); pol commit m_in_tag; // Instruction memory tag ("foreign key" pointing to avm_main.in_tag) + // Indicator of the intermediate register pertaining to the memory operation (foreign key to avm_main.mem_op_XXX) + pol commit m_op_a; + pol commit m_op_b; + pol commit m_op_c; + // Error columns pol commit m_tag_err; // Boolean (1 if m_in_tag != m_tag is detected) @@ -26,10 +31,20 @@ namespace avm_mem(256); m_last * (1 - m_last) = 0; m_rw * (1 - m_rw) = 0; m_tag_err * (1 - m_tag_err) = 0; + m_op_a * (1 - m_op_a) = 0; + m_op_b * (1 - m_op_b) = 0; + m_op_c * (1 - m_op_c) = 0; // TODO: m_addr is u32 and 0 <= m_tag <= 6 // (m_in_tag will be constrained through inclusion check to main trace) + // sub_clk derivation + m_sub_clk = 3 * m_rw + m_op_b + 2 * m_op_c; + + // Maximum one memory operation enabled per row + pol M_OP_SUM = m_op_a + m_op_b + m_op_c; + M_OP_SUM * (M_OP_SUM - 1) = 0; + // Remark: m_lastAccess == 1 on first row and therefore any relation with the // multiplicative term (1 - m_lastAccess) implicitly includes (1 - avm_main.first) // Similarly, this includes (1 - m_last) as well. @@ -96,11 +111,4 @@ namespace avm_mem(256); // Correctness of two above checks MEM_IN_TAG_CONSISTENCY_1/2: // m_in_tag == m_tag ==> m_tag_err == 0 (first relation) - // m_tag_err == 0 ==> m_one_min_inv == 0 by second relation. First relation ==> m_in_tag - m_tag == 0 - - // TODO: when introducing load/store as sub-operations, we will have to add consistency of intermediate - // register values ia, ib, ic - - // Inter-table Constraints - - // TODO: {m_clk, m_in_tag} IN {avm_main.clk, avm_main.in_tag} \ No newline at end of file + // m_tag_err == 0 ==> m_one_min_inv == 0 by second relation. First relation ==> m_in_tag - m_tag == 0 \ No newline at end of file diff --git a/barretenberg/cpp/scripts/analyze_client_ivc_bench.py b/barretenberg/cpp/scripts/analyze_client_ivc_bench.py index d9b5e047b1f..6cedf3509e7 100644 --- a/barretenberg/cpp/scripts/analyze_client_ivc_bench.py +++ b/barretenberg/cpp/scripts/analyze_client_ivc_bench.py @@ -7,8 +7,7 @@ # Single out an independent set of functions accounting for most of BENCHMARK's real_time to_keep = [ - "construct_mock_function_circuit(t)", - "construct_mock_folding_kernel(t)", + "construct_circuits(t)", "ProverInstance(Circuit&)(t)", "ProtogalaxyProver::fold_instances(t)", "Decider::construct_proof(t)", @@ -28,13 +27,13 @@ # For each kept time, get the proportion over all kept times. sum_of_kept_times_ms = sum(float(time) for _, time in bench_components.items())/1e6 -MAX_LABEL_LENGTH = max(len(label) for label in to_keep) +max_label_length = max(len(label) for label in to_keep) column = {"function": "function", "ms": "ms", "%": "% sum"} print( - f"{column['function']:<{MAX_LABEL_LENGTH}}{column['ms']:>8} {column['%']:>8}") + f"{column['function']:<{max_label_length}}{column['ms']:>8} {column['%']:>8}") for key in to_keep: time_ms = bench[key]/1e6 - print(f"{key:<{MAX_LABEL_LENGTH}}{time_ms:>8.0f} {time_ms/sum_of_kept_times_ms:>8.2%}") + print(f"{key:<{max_label_length}}{time_ms:>8.0f} {time_ms/sum_of_kept_times_ms:>8.2%}") # Validate that kept times account for most of the total measured time. total_time_ms = bench["real_time"] @@ -42,3 +41,32 @@ totals = totals.format( sum_of_kept_times_ms, total_time_ms, sum_of_kept_times_ms/total_time_ms) print(totals) + +print("\nMajor contributors:") +print( + f"{column['function']:<{max_label_length}}{column['ms']:>8} {column['%']:>7}") +for key in ['commit(t)', 'compute_combiner(t)', 'compute_perturbator(t)', 'compute_univariate(t)']: + time_ms = bench[key]/1e6 + print(f"{key:<{max_label_length}}{time_ms:>8.0f} {time_ms/sum_of_kept_times_ms:>8.2%}") + + +print('\nBreakdown of ECCVMProver::create_prover:') +for key in ["ECCVMComposer::compute_witness(t)", "ECCVMComposer::create_proving_key(t)"]: + time_ms = bench[key]/1e6 + total_time_ms = bench["ECCVMComposer::create_prover(t)"]/1e6 + print(f"{key:<{max_label_length}}{time_ms:>8.0f} {time_ms/total_time_ms:>8.2%}") + +print('\nBreakdown of ProtogalaxyProver::fold_instances:') +protogalaxy_round_labels = [ + "ProtoGalaxyProver_::preparation_round(t)", + "ProtoGalaxyProver_::perturbator_round(t)", + "ProtoGalaxyProver_::combiner_quotient_round(t)", + "ProtoGalaxyProver_::accumulator_update_round(t)" +] +max_label_length = max(len(label) for label in protogalaxy_round_labels) +for key in protogalaxy_round_labels: + time_ms = bench[key]/1e6 + total_time_ms = bench["ProtogalaxyProver::fold_instances(t)"]/1e6 + print(f"{key:<{max_label_length}}{time_ms:>8.0f} {time_ms/total_time_ms:>8.2%}") + + diff --git a/barretenberg/cpp/scripts/benchmark.sh b/barretenberg/cpp/scripts/benchmark.sh index 93b96377173..6b6758700f4 100755 --- a/barretenberg/cpp/scripts/benchmark.sh +++ b/barretenberg/cpp/scripts/benchmark.sh @@ -2,16 +2,19 @@ set -eu BENCHMARK=${1:-goblin_bench} -COMMAND=${2:-./bin/$BENCHMARK} +COMMAND=${2:-./$BENCHMARK} +PRESET=${3:-clang16} +BUILD_DIR=${4:-build} + # Move above script dir. cd $(dirname $0)/.. # Configure and build. -cmake --preset clang16 -cmake --build --preset clang16 --target $BENCHMARK +cmake --preset $PRESET +cmake --build --preset $PRESET --target $BENCHMARK -cd build +cd $BUILD_DIR # Consistency with _wasm.sh targets / shorter $COMMAND. cp ./bin/$BENCHMARK . $COMMAND \ No newline at end of file diff --git a/barretenberg/cpp/scripts/benchmark_client_ivc.sh b/barretenberg/cpp/scripts/benchmark_client_ivc.sh index 08e43f012ca..17a193c6d82 100755 --- a/barretenberg/cpp/scripts/benchmark_client_ivc.sh +++ b/barretenberg/cpp/scripts/benchmark_client_ivc.sh @@ -21,5 +21,5 @@ cd $BUILD_DIR scp $BB_SSH_KEY $BB_SSH_INSTANCE:$BB_SSH_CPP_PATH/build/$TARGET.json . # Analyze the results -cd $(dirname $0)/.. +cd ../ python3 ./scripts/analyze_client_ivc_bench.py diff --git a/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp index f65385da92e..2ace58eb6e6 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp @@ -2,6 +2,7 @@ #include #include "barretenberg/client_ivc/client_ivc.hpp" +#include "barretenberg/common/op_count.hpp" #include "barretenberg/common/op_count_google_bench.hpp" #include "barretenberg/goblin/mock_circuits.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" @@ -46,9 +47,12 @@ class ClientIVCBench : public benchmark::Fixture { std::vector initial_function_circuits(2); // Construct 2 starting function circuits in parallel - parallel_for(2, [&](size_t circuit_index) { - GoblinMockCircuits::construct_mock_function_circuit(initial_function_circuits[circuit_index]); - }); + { + BB_OP_COUNT_TIME_NAME("construct_circuits"); + parallel_for(2, [&](size_t circuit_index) { + GoblinMockCircuits::construct_mock_function_circuit(initial_function_circuits[circuit_index]); + }); + }; // Prepend queue to the first circuit initial_function_circuits[0].op_queue->prepend_previous_queue(*ivc.goblin.op_queue); @@ -81,25 +85,28 @@ class ClientIVCBench : public benchmark::Fixture { Builder kernel_circuit{ size_hint, ivc.goblin.op_queue }; Builder function_circuit{ size_hint }; // Construct function and kernel circuits in parallel - parallel_for(2, [&](size_t workload_idx) { - // workload index is 0 for kernel and 1 for function - if (workload_idx == 0) { - if (circuit_idx == 0) { - - // Create the first folding kernel which only verifies the accumulation of a - // function circuit - kernel_verifier_accumulator = GoblinMockCircuits::construct_mock_folding_kernel( - kernel_circuit, function_fold_output, {}, kernel_verifier_accumulator); + { + BB_OP_COUNT_TIME_NAME("construct_circuits"); + parallel_for(2, [&](size_t workload_idx) { + // workload index is 0 for kernel and 1 for function + if (workload_idx == 0) { + if (circuit_idx == 0) { + + // Create the first folding kernel which only verifies the accumulation of a + // function circuit + kernel_verifier_accumulator = GoblinMockCircuits::construct_mock_folding_kernel( + kernel_circuit, function_fold_output, {}, kernel_verifier_accumulator); + } else { + // Create kernel circuit containing the recursive folding verification of a function circuit + // and a kernel circuit + kernel_verifier_accumulator = GoblinMockCircuits::construct_mock_folding_kernel( + kernel_circuit, function_fold_output, kernel_fold_output, kernel_verifier_accumulator); + } } else { - // Create kernel circuit containing the recursive folding verification of a function circuit and - // a kernel circuit - kernel_verifier_accumulator = GoblinMockCircuits::construct_mock_folding_kernel( - kernel_circuit, function_fold_output, kernel_fold_output, kernel_verifier_accumulator); + GoblinMockCircuits::construct_mock_function_circuit(function_circuit); } - } else { - GoblinMockCircuits::construct_mock_function_circuit(function_circuit); - } - }); + }); + }; // No need to prepend queue, it's the same after last swap // Accumulate kernel circuit @@ -127,14 +134,20 @@ class ClientIVCBench : public benchmark::Fixture { // Create and accumulate the first folding kernel which only verifies the accumulation of a function circuit Builder kernel_circuit{ size_hint, ivc.goblin.op_queue }; auto kernel_verifier_accumulator = std::make_shared(ivc.vks.first_func_vk); - kernel_verifier_accumulator = GoblinMockCircuits::construct_mock_folding_kernel( - kernel_circuit, function_fold_output, {}, kernel_verifier_accumulator); + { + BB_OP_COUNT_TIME_NAME("construct_circuits"); + kernel_verifier_accumulator = GoblinMockCircuits::construct_mock_folding_kernel( + kernel_circuit, function_fold_output, {}, kernel_verifier_accumulator); + } auto kernel_fold_proof = ivc.accumulate(kernel_circuit); kernel_fold_output = { kernel_fold_proof, ivc.vks.first_kernel_vk }; } else { Builder kernel_circuit{ size_hint, ivc.goblin.op_queue }; - kernel_verifier_accumulator = GoblinMockCircuits::construct_mock_folding_kernel( - kernel_circuit, function_fold_output, kernel_fold_output, kernel_verifier_accumulator); + { + BB_OP_COUNT_TIME_NAME("construct_circuits"); + kernel_verifier_accumulator = GoblinMockCircuits::construct_mock_folding_kernel( + kernel_circuit, function_fold_output, kernel_fold_output, kernel_verifier_accumulator); + } auto kernel_fold_proof = ivc.accumulate(kernel_circuit); kernel_fold_output = { kernel_fold_proof, ivc.vks.kernel_vk }; diff --git a/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/ultra_honk_rounds.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/ultra_honk_rounds.bench.cpp index 11ad5e6e15f..aebc60b1912 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/ultra_honk_rounds.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/ultra_honk_rounds.bench.cpp @@ -45,11 +45,11 @@ BB_PROFILE static void test_round_inner(State& state, GoblinUltraProver& prover, } }; - time_if_index(PREAMBLE, [&] { prover.execute_preamble_round(); }); - time_if_index(WIRE_COMMITMENTS, [&] { prover.execute_wire_commitments_round(); }); - time_if_index(SORTED_LIST_ACCUMULATOR, [&] { prover.execute_sorted_list_accumulator_round(); }); - time_if_index(LOG_DERIVATIVE_INVERSE, [&] { prover.execute_log_derivative_inverse_round(); }); - time_if_index(GRAND_PRODUCT_COMPUTATION, [&] { prover.execute_grand_product_computation_round(); }); + time_if_index(PREAMBLE, [&] { prover.oink_prover.execute_preamble_round(); }); + time_if_index(WIRE_COMMITMENTS, [&] { prover.oink_prover.execute_wire_commitments_round(); }); + time_if_index(SORTED_LIST_ACCUMULATOR, [&] { prover.oink_prover.execute_sorted_list_accumulator_round(); }); + time_if_index(LOG_DERIVATIVE_INVERSE, [&] { prover.oink_prover.execute_log_derivative_inverse_round(); }); + time_if_index(GRAND_PRODUCT_COMPUTATION, [&] { prover.oink_prover.execute_grand_product_computation_round(); }); time_if_index(RELATION_CHECK, [&] { prover.execute_relation_check_rounds(); }); time_if_index(ZEROMORPH, [&] { prover.execute_zeromorph_rounds(); }); } @@ -62,7 +62,10 @@ BB_PROFILE static void test_round(State& state, size_t index) noexcept auto prover = bb::mock_proofs::get_prover( &bb::mock_proofs::generate_basic_arithmetic_circuit, log2_num_gates); for (auto _ : state) { + state.PauseTiming(); test_round_inner(state, prover, index); + state.ResumeTiming(); + // NOTE: google bench is very finnicky, must end in ResumeTiming() for correctness } } #define ROUND_BENCHMARK(round) \ diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.cpp index 3f8d20b019f..bf5b4c7316c 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.cpp @@ -10,6 +10,8 @@ namespace bb { */ template void ECCVMComposer_::compute_witness(CircuitConstructor& circuit_constructor) { + BB_OP_COUNT_TIME_NAME("ECCVMComposer::compute_witness"); + if (computed_witness) { return; } @@ -67,6 +69,8 @@ template std::shared_ptr ECCVMComposer_::compute_proving_key( CircuitConstructor& circuit_constructor) { + BB_OP_COUNT_TIME_NAME("ECCVMComposer::create_proving_key"); + if (proving_key) { return proving_key; } diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.hpp index 03630f5b239..a33446e6caa 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.hpp @@ -70,6 +70,7 @@ template class ECCVMComposer_ { void compute_commitment_key(size_t circuit_size) { + BB_OP_COUNT_TIME_NAME("ECCVMComposer::compute_commitment_key"); commitment_key = std::make_shared(circuit_size); }; }; diff --git a/barretenberg/cpp/src/barretenberg/flavor/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/generated/avm_flavor.hpp index 06c9fe3159a..88ca63d463d 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/generated/avm_flavor.hpp @@ -16,7 +16,10 @@ #include "barretenberg/relations/generated/avm/avm_alu.hpp" #include "barretenberg/relations/generated/avm/avm_main.hpp" #include "barretenberg/relations/generated/avm/avm_mem.hpp" -#include "barretenberg/relations/generated/avm/equiv_inter_reg_alu.hpp" +#include "barretenberg/relations/generated/avm/perm_main_alu.hpp" +#include "barretenberg/relations/generated/avm/perm_main_mem_a.hpp" +#include "barretenberg/relations/generated/avm/perm_main_mem_b.hpp" +#include "barretenberg/relations/generated/avm/perm_main_mem_c.hpp" #include "barretenberg/transcript/transcript.hpp" namespace bb { @@ -38,14 +41,19 @@ class AvmFlavor { using RelationSeparator = FF; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 75; + static constexpr size_t NUM_WITNESS_ENTITIES = 81; static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES; // We have two copies of the witness entities, so we subtract the number of fixed ones (they have no shift), one for // the unshifted and one for the shifted - static constexpr size_t NUM_ALL_ENTITIES = 91; + static constexpr size_t NUM_ALL_ENTITIES = 97; - using Relations = - std::tuple, Avm_vm::avm_mem, Avm_vm::avm_main, equiv_inter_reg_alu_relation>; + using Relations = std::tuple, + Avm_vm::avm_alu, + Avm_vm::avm_main, + perm_main_alu_relation, + perm_main_mem_a_relation, + perm_main_mem_b_relation, + perm_main_mem_c_relation>; static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); @@ -88,6 +96,9 @@ class AvmFlavor { avm_mem_m_last, avm_mem_m_rw, avm_mem_m_in_tag, + avm_mem_m_op_a, + avm_mem_m_op_b, + avm_mem_m_op_c, avm_mem_m_tag_err, avm_mem_m_one_min_inv, avm_alu_alu_clk, @@ -151,9 +162,12 @@ class AvmFlavor { avm_main_mem_idx_b, avm_main_mem_idx_c, avm_main_last, - equiv_inter_reg_alu, - equiv_tag_err, - equiv_tag_err_counts) + perm_main_alu, + perm_main_mem_a, + perm_main_mem_b, + perm_main_mem_c, + incl_main_tag_err, + incl_main_tag_err_counts) RefVector get_wires() { @@ -166,6 +180,9 @@ class AvmFlavor { avm_mem_m_last, avm_mem_m_rw, avm_mem_m_in_tag, + avm_mem_m_op_a, + avm_mem_m_op_b, + avm_mem_m_op_c, avm_mem_m_tag_err, avm_mem_m_one_min_inv, avm_alu_alu_clk, @@ -229,9 +246,12 @@ class AvmFlavor { avm_main_mem_idx_b, avm_main_mem_idx_c, avm_main_last, - equiv_inter_reg_alu, - equiv_tag_err, - equiv_tag_err_counts }; + perm_main_alu, + perm_main_mem_a, + perm_main_mem_b, + perm_main_mem_c, + incl_main_tag_err, + incl_main_tag_err_counts }; }; RefVector get_sorted_polynomials() { return {}; }; }; @@ -250,6 +270,9 @@ class AvmFlavor { avm_mem_m_last, avm_mem_m_rw, avm_mem_m_in_tag, + avm_mem_m_op_a, + avm_mem_m_op_b, + avm_mem_m_op_c, avm_mem_m_tag_err, avm_mem_m_one_min_inv, avm_alu_alu_clk, @@ -313,23 +336,26 @@ class AvmFlavor { avm_main_mem_idx_b, avm_main_mem_idx_c, avm_main_last, - equiv_inter_reg_alu, - equiv_tag_err, - equiv_tag_err_counts, - avm_alu_alu_u16_r4_shift, + perm_main_alu, + perm_main_mem_a, + perm_main_mem_b, + perm_main_mem_c, + incl_main_tag_err, + incl_main_tag_err_counts, + avm_mem_m_tag_shift, + avm_mem_m_val_shift, + avm_mem_m_rw_shift, + avm_mem_m_addr_shift, avm_alu_alu_u16_r5_shift, - avm_alu_alu_u16_r2_shift, + avm_alu_alu_u16_r3_shift, + avm_alu_alu_u16_r4_shift, avm_alu_alu_u16_r7_shift, + avm_alu_alu_u16_r1_shift, avm_alu_alu_u16_r0_shift, - avm_alu_alu_u16_r3_shift, avm_alu_alu_u16_r6_shift, - avm_alu_alu_u16_r1_shift, - avm_mem_m_val_shift, - avm_mem_m_rw_shift, - avm_mem_m_tag_shift, - avm_mem_m_addr_shift, - avm_main_internal_return_ptr_shift, - avm_main_pc_shift) + avm_alu_alu_u16_r2_shift, + avm_main_pc_shift, + avm_main_internal_return_ptr_shift) RefVector get_wires() { @@ -344,6 +370,9 @@ class AvmFlavor { avm_mem_m_last, avm_mem_m_rw, avm_mem_m_in_tag, + avm_mem_m_op_a, + avm_mem_m_op_b, + avm_mem_m_op_c, avm_mem_m_tag_err, avm_mem_m_one_min_inv, avm_alu_alu_clk, @@ -407,23 +436,26 @@ class AvmFlavor { avm_main_mem_idx_b, avm_main_mem_idx_c, avm_main_last, - equiv_inter_reg_alu, - equiv_tag_err, - equiv_tag_err_counts, - avm_alu_alu_u16_r4_shift, + perm_main_alu, + perm_main_mem_a, + perm_main_mem_b, + perm_main_mem_c, + incl_main_tag_err, + incl_main_tag_err_counts, + avm_mem_m_tag_shift, + avm_mem_m_val_shift, + avm_mem_m_rw_shift, + avm_mem_m_addr_shift, avm_alu_alu_u16_r5_shift, - avm_alu_alu_u16_r2_shift, + avm_alu_alu_u16_r3_shift, + avm_alu_alu_u16_r4_shift, avm_alu_alu_u16_r7_shift, + avm_alu_alu_u16_r1_shift, avm_alu_alu_u16_r0_shift, - avm_alu_alu_u16_r3_shift, avm_alu_alu_u16_r6_shift, - avm_alu_alu_u16_r1_shift, - avm_mem_m_val_shift, - avm_mem_m_rw_shift, - avm_mem_m_tag_shift, - avm_mem_m_addr_shift, - avm_main_internal_return_ptr_shift, - avm_main_pc_shift }; + avm_alu_alu_u16_r2_shift, + avm_main_pc_shift, + avm_main_internal_return_ptr_shift }; }; RefVector get_unshifted() { @@ -438,6 +470,9 @@ class AvmFlavor { avm_mem_m_last, avm_mem_m_rw, avm_mem_m_in_tag, + avm_mem_m_op_a, + avm_mem_m_op_b, + avm_mem_m_op_c, avm_mem_m_tag_err, avm_mem_m_one_min_inv, avm_alu_alu_clk, @@ -501,43 +536,32 @@ class AvmFlavor { avm_main_mem_idx_b, avm_main_mem_idx_c, avm_main_last, - equiv_inter_reg_alu, - equiv_tag_err, - equiv_tag_err_counts }; + perm_main_alu, + perm_main_mem_a, + perm_main_mem_b, + perm_main_mem_c, + incl_main_tag_err, + incl_main_tag_err_counts }; }; RefVector get_to_be_shifted() { - return { avm_alu_alu_u16_r4, - avm_alu_alu_u16_r5, - avm_alu_alu_u16_r2, - avm_alu_alu_u16_r7, - avm_alu_alu_u16_r0, - avm_alu_alu_u16_r3, - avm_alu_alu_u16_r6, - avm_alu_alu_u16_r1, - avm_mem_m_val, - avm_mem_m_rw, - avm_mem_m_tag, - avm_mem_m_addr, - avm_main_internal_return_ptr, - avm_main_pc }; + return { avm_mem_m_tag, avm_mem_m_val, + avm_mem_m_rw, avm_mem_m_addr, + avm_alu_alu_u16_r5, avm_alu_alu_u16_r3, + avm_alu_alu_u16_r4, avm_alu_alu_u16_r7, + avm_alu_alu_u16_r1, avm_alu_alu_u16_r0, + avm_alu_alu_u16_r6, avm_alu_alu_u16_r2, + avm_main_pc, avm_main_internal_return_ptr }; }; RefVector get_shifted() { - return { avm_alu_alu_u16_r4_shift, - avm_alu_alu_u16_r5_shift, - avm_alu_alu_u16_r2_shift, - avm_alu_alu_u16_r7_shift, - avm_alu_alu_u16_r0_shift, - avm_alu_alu_u16_r3_shift, - avm_alu_alu_u16_r6_shift, - avm_alu_alu_u16_r1_shift, - avm_mem_m_val_shift, - avm_mem_m_rw_shift, - avm_mem_m_tag_shift, - avm_mem_m_addr_shift, - avm_main_internal_return_ptr_shift, - avm_main_pc_shift }; + return { avm_mem_m_tag_shift, avm_mem_m_val_shift, + avm_mem_m_rw_shift, avm_mem_m_addr_shift, + avm_alu_alu_u16_r5_shift, avm_alu_alu_u16_r3_shift, + avm_alu_alu_u16_r4_shift, avm_alu_alu_u16_r7_shift, + avm_alu_alu_u16_r1_shift, avm_alu_alu_u16_r0_shift, + avm_alu_alu_u16_r6_shift, avm_alu_alu_u16_r2_shift, + avm_main_pc_shift, avm_main_internal_return_ptr_shift }; }; }; @@ -550,20 +574,13 @@ class AvmFlavor { RefVector get_to_be_shifted() { - return { avm_alu_alu_u16_r4, - avm_alu_alu_u16_r5, - avm_alu_alu_u16_r2, - avm_alu_alu_u16_r7, - avm_alu_alu_u16_r0, - avm_alu_alu_u16_r3, - avm_alu_alu_u16_r6, - avm_alu_alu_u16_r1, - avm_mem_m_val, - avm_mem_m_rw, - avm_mem_m_tag, - avm_mem_m_addr, - avm_main_internal_return_ptr, - avm_main_pc }; + return { avm_mem_m_tag, avm_mem_m_val, + avm_mem_m_rw, avm_mem_m_addr, + avm_alu_alu_u16_r5, avm_alu_alu_u16_r3, + avm_alu_alu_u16_r4, avm_alu_alu_u16_r7, + avm_alu_alu_u16_r1, avm_alu_alu_u16_r0, + avm_alu_alu_u16_r6, avm_alu_alu_u16_r2, + avm_main_pc, avm_main_internal_return_ptr }; }; // The plookup wires that store plookup read data. @@ -651,6 +668,9 @@ class AvmFlavor { Base::avm_mem_m_last = "AVM_MEM_M_LAST"; Base::avm_mem_m_rw = "AVM_MEM_M_RW"; Base::avm_mem_m_in_tag = "AVM_MEM_M_IN_TAG"; + Base::avm_mem_m_op_a = "AVM_MEM_M_OP_A"; + Base::avm_mem_m_op_b = "AVM_MEM_M_OP_B"; + Base::avm_mem_m_op_c = "AVM_MEM_M_OP_C"; Base::avm_mem_m_tag_err = "AVM_MEM_M_TAG_ERR"; Base::avm_mem_m_one_min_inv = "AVM_MEM_M_ONE_MIN_INV"; Base::avm_alu_alu_clk = "AVM_ALU_ALU_CLK"; @@ -714,9 +734,12 @@ class AvmFlavor { Base::avm_main_mem_idx_b = "AVM_MAIN_MEM_IDX_B"; Base::avm_main_mem_idx_c = "AVM_MAIN_MEM_IDX_C"; Base::avm_main_last = "AVM_MAIN_LAST"; - Base::equiv_inter_reg_alu = "EQUIV_INTER_REG_ALU"; - Base::equiv_tag_err = "EQUIV_TAG_ERR"; - Base::equiv_tag_err_counts = "EQUIV_TAG_ERR_COUNTS"; + Base::perm_main_alu = "PERM_MAIN_ALU"; + Base::perm_main_mem_a = "PERM_MAIN_MEM_A"; + Base::perm_main_mem_b = "PERM_MAIN_MEM_B"; + Base::perm_main_mem_c = "PERM_MAIN_MEM_C"; + Base::incl_main_tag_err = "INCL_MAIN_TAG_ERR"; + Base::incl_main_tag_err_counts = "INCL_MAIN_TAG_ERR_COUNTS"; }; }; @@ -745,6 +768,9 @@ class AvmFlavor { Commitment avm_mem_m_last; Commitment avm_mem_m_rw; Commitment avm_mem_m_in_tag; + Commitment avm_mem_m_op_a; + Commitment avm_mem_m_op_b; + Commitment avm_mem_m_op_c; Commitment avm_mem_m_tag_err; Commitment avm_mem_m_one_min_inv; Commitment avm_alu_alu_clk; @@ -808,9 +834,12 @@ class AvmFlavor { Commitment avm_main_mem_idx_b; Commitment avm_main_mem_idx_c; Commitment avm_main_last; - Commitment equiv_inter_reg_alu; - Commitment equiv_tag_err; - Commitment equiv_tag_err_counts; + Commitment perm_main_alu; + Commitment perm_main_mem_a; + Commitment perm_main_mem_b; + Commitment perm_main_mem_c; + Commitment incl_main_tag_err; + Commitment incl_main_tag_err_counts; std::vector> sumcheck_univariates; std::array sumcheck_evaluations; @@ -839,6 +868,9 @@ class AvmFlavor { avm_mem_m_last = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_mem_m_rw = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_mem_m_in_tag = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_mem_m_op_a = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_mem_m_op_b = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + avm_mem_m_op_c = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_mem_m_tag_err = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_mem_m_one_min_inv = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_alu_alu_clk = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -902,9 +934,12 @@ class AvmFlavor { avm_main_mem_idx_b = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_mem_idx_c = deserialize_from_buffer(Transcript::proof_data, num_frs_read); avm_main_last = deserialize_from_buffer(Transcript::proof_data, num_frs_read); - equiv_inter_reg_alu = deserialize_from_buffer(Transcript::proof_data, num_frs_read); - equiv_tag_err = deserialize_from_buffer(Transcript::proof_data, num_frs_read); - equiv_tag_err_counts = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + perm_main_alu = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + perm_main_mem_a = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + perm_main_mem_b = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + perm_main_mem_c = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + incl_main_tag_err = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + incl_main_tag_err_counts = deserialize_from_buffer(Transcript::proof_data, num_frs_read); for (size_t i = 0; i < log_n; ++i) { sumcheck_univariates.emplace_back( @@ -937,6 +972,9 @@ class AvmFlavor { serialize_to_buffer(avm_mem_m_last, Transcript::proof_data); serialize_to_buffer(avm_mem_m_rw, Transcript::proof_data); serialize_to_buffer(avm_mem_m_in_tag, Transcript::proof_data); + serialize_to_buffer(avm_mem_m_op_a, Transcript::proof_data); + serialize_to_buffer(avm_mem_m_op_b, Transcript::proof_data); + serialize_to_buffer(avm_mem_m_op_c, Transcript::proof_data); serialize_to_buffer(avm_mem_m_tag_err, Transcript::proof_data); serialize_to_buffer(avm_mem_m_one_min_inv, Transcript::proof_data); serialize_to_buffer(avm_alu_alu_clk, Transcript::proof_data); @@ -1000,9 +1038,12 @@ class AvmFlavor { serialize_to_buffer(avm_main_mem_idx_b, Transcript::proof_data); serialize_to_buffer(avm_main_mem_idx_c, Transcript::proof_data); serialize_to_buffer(avm_main_last, Transcript::proof_data); - serialize_to_buffer(equiv_inter_reg_alu, Transcript::proof_data); - serialize_to_buffer(equiv_tag_err, Transcript::proof_data); - serialize_to_buffer(equiv_tag_err_counts, Transcript::proof_data); + serialize_to_buffer(perm_main_alu, Transcript::proof_data); + serialize_to_buffer(perm_main_mem_a, Transcript::proof_data); + serialize_to_buffer(perm_main_mem_b, Transcript::proof_data); + serialize_to_buffer(perm_main_mem_c, Transcript::proof_data); + serialize_to_buffer(incl_main_tag_err, Transcript::proof_data); + serialize_to_buffer(incl_main_tag_err_counts, Transcript::proof_data); for (size_t i = 0; i < log_n; ++i) { serialize_to_buffer(sumcheck_univariates[i], Transcript::proof_data); diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 97876b0e624..c3b5824f614 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -112,7 +112,6 @@ class GoblinMockCircuits { */ static void construct_mock_function_circuit(GoblinUltraBuilder& builder, bool large = false) { - BB_OP_COUNT_TIME(); // Determine number of times to execute the below operations that constitute the mock circuit logic. Note that // the circuit size does not scale linearly with number of iterations due to e.g. amortization of lookup costs const size_t NUM_ITERATIONS_LARGE = 13; // results in circuit size 2^19 (521327 gates) @@ -234,7 +233,6 @@ class GoblinMockCircuits { const VerifierFoldData& kernel, std::shared_ptr& prev_kernel_accum) { - BB_OP_COUNT_TIME(); using GURecursiveFlavor = GoblinUltraRecursiveFlavor_; using RecursiveVerifierInstances = bb::stdlib::recursion::honk::RecursiveVerifierInstances_; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/avm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/avm_circuit_builder.hpp index c33c5b3f206..7090216f452 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/avm_circuit_builder.hpp @@ -15,8 +15,11 @@ #include "barretenberg/relations/generated/avm/avm_alu.hpp" #include "barretenberg/relations/generated/avm/avm_main.hpp" #include "barretenberg/relations/generated/avm/avm_mem.hpp" -#include "barretenberg/relations/generated/avm/equiv_inter_reg_alu.hpp" -#include "barretenberg/relations/generated/avm/equiv_tag_err.hpp" +#include "barretenberg/relations/generated/avm/incl_main_tag_err.hpp" +#include "barretenberg/relations/generated/avm/perm_main_alu.hpp" +#include "barretenberg/relations/generated/avm/perm_main_mem_a.hpp" +#include "barretenberg/relations/generated/avm/perm_main_mem_b.hpp" +#include "barretenberg/relations/generated/avm/perm_main_mem_c.hpp" namespace bb { @@ -32,6 +35,9 @@ template struct AvmFullRow { FF avm_mem_m_last{}; FF avm_mem_m_rw{}; FF avm_mem_m_in_tag{}; + FF avm_mem_m_op_a{}; + FF avm_mem_m_op_b{}; + FF avm_mem_m_op_c{}; FF avm_mem_m_tag_err{}; FF avm_mem_m_one_min_inv{}; FF avm_alu_alu_clk{}; @@ -95,23 +101,26 @@ template struct AvmFullRow { FF avm_main_mem_idx_b{}; FF avm_main_mem_idx_c{}; FF avm_main_last{}; - FF equiv_inter_reg_alu{}; - FF equiv_tag_err{}; - FF equiv_tag_err_counts{}; - FF avm_alu_alu_u16_r4_shift{}; + FF perm_main_alu{}; + FF perm_main_mem_a{}; + FF perm_main_mem_b{}; + FF perm_main_mem_c{}; + FF incl_main_tag_err{}; + FF incl_main_tag_err_counts{}; + FF avm_mem_m_tag_shift{}; + FF avm_mem_m_val_shift{}; + FF avm_mem_m_rw_shift{}; + FF avm_mem_m_addr_shift{}; FF avm_alu_alu_u16_r5_shift{}; - FF avm_alu_alu_u16_r2_shift{}; + FF avm_alu_alu_u16_r3_shift{}; + FF avm_alu_alu_u16_r4_shift{}; FF avm_alu_alu_u16_r7_shift{}; + FF avm_alu_alu_u16_r1_shift{}; FF avm_alu_alu_u16_r0_shift{}; - FF avm_alu_alu_u16_r3_shift{}; FF avm_alu_alu_u16_r6_shift{}; - FF avm_alu_alu_u16_r1_shift{}; - FF avm_mem_m_val_shift{}; - FF avm_mem_m_rw_shift{}; - FF avm_mem_m_tag_shift{}; - FF avm_mem_m_addr_shift{}; - FF avm_main_internal_return_ptr_shift{}; + FF avm_alu_alu_u16_r2_shift{}; FF avm_main_pc_shift{}; + FF avm_main_internal_return_ptr_shift{}; }; class AvmCircuitBuilder { @@ -124,8 +133,8 @@ class AvmCircuitBuilder { using Polynomial = Flavor::Polynomial; using ProverPolynomials = Flavor::ProverPolynomials; - static constexpr size_t num_fixed_columns = 91; - static constexpr size_t num_polys = 77; + static constexpr size_t num_fixed_columns = 97; + static constexpr size_t num_polys = 83; std::vector rows; void set_trace(std::vector&& trace) { rows = std::move(trace); } @@ -152,6 +161,9 @@ class AvmCircuitBuilder { polys.avm_mem_m_last[i] = rows[i].avm_mem_m_last; polys.avm_mem_m_rw[i] = rows[i].avm_mem_m_rw; polys.avm_mem_m_in_tag[i] = rows[i].avm_mem_m_in_tag; + polys.avm_mem_m_op_a[i] = rows[i].avm_mem_m_op_a; + polys.avm_mem_m_op_b[i] = rows[i].avm_mem_m_op_b; + polys.avm_mem_m_op_c[i] = rows[i].avm_mem_m_op_c; polys.avm_mem_m_tag_err[i] = rows[i].avm_mem_m_tag_err; polys.avm_mem_m_one_min_inv[i] = rows[i].avm_mem_m_one_min_inv; polys.avm_alu_alu_clk[i] = rows[i].avm_alu_alu_clk; @@ -215,25 +227,28 @@ class AvmCircuitBuilder { polys.avm_main_mem_idx_b[i] = rows[i].avm_main_mem_idx_b; polys.avm_main_mem_idx_c[i] = rows[i].avm_main_mem_idx_c; polys.avm_main_last[i] = rows[i].avm_main_last; - polys.equiv_inter_reg_alu[i] = rows[i].equiv_inter_reg_alu; - polys.equiv_tag_err[i] = rows[i].equiv_tag_err; - polys.equiv_tag_err_counts[i] = rows[i].equiv_tag_err_counts; + polys.perm_main_alu[i] = rows[i].perm_main_alu; + polys.perm_main_mem_a[i] = rows[i].perm_main_mem_a; + polys.perm_main_mem_b[i] = rows[i].perm_main_mem_b; + polys.perm_main_mem_c[i] = rows[i].perm_main_mem_c; + polys.incl_main_tag_err[i] = rows[i].incl_main_tag_err; + polys.incl_main_tag_err_counts[i] = rows[i].incl_main_tag_err_counts; } - polys.avm_alu_alu_u16_r4_shift = Polynomial(polys.avm_alu_alu_u16_r4.shifted()); + polys.avm_mem_m_tag_shift = Polynomial(polys.avm_mem_m_tag.shifted()); + polys.avm_mem_m_val_shift = Polynomial(polys.avm_mem_m_val.shifted()); + polys.avm_mem_m_rw_shift = Polynomial(polys.avm_mem_m_rw.shifted()); + polys.avm_mem_m_addr_shift = Polynomial(polys.avm_mem_m_addr.shifted()); polys.avm_alu_alu_u16_r5_shift = Polynomial(polys.avm_alu_alu_u16_r5.shifted()); - polys.avm_alu_alu_u16_r2_shift = Polynomial(polys.avm_alu_alu_u16_r2.shifted()); + polys.avm_alu_alu_u16_r3_shift = Polynomial(polys.avm_alu_alu_u16_r3.shifted()); + polys.avm_alu_alu_u16_r4_shift = Polynomial(polys.avm_alu_alu_u16_r4.shifted()); polys.avm_alu_alu_u16_r7_shift = Polynomial(polys.avm_alu_alu_u16_r7.shifted()); + polys.avm_alu_alu_u16_r1_shift = Polynomial(polys.avm_alu_alu_u16_r1.shifted()); polys.avm_alu_alu_u16_r0_shift = Polynomial(polys.avm_alu_alu_u16_r0.shifted()); - polys.avm_alu_alu_u16_r3_shift = Polynomial(polys.avm_alu_alu_u16_r3.shifted()); polys.avm_alu_alu_u16_r6_shift = Polynomial(polys.avm_alu_alu_u16_r6.shifted()); - polys.avm_alu_alu_u16_r1_shift = Polynomial(polys.avm_alu_alu_u16_r1.shifted()); - polys.avm_mem_m_val_shift = Polynomial(polys.avm_mem_m_val.shifted()); - polys.avm_mem_m_rw_shift = Polynomial(polys.avm_mem_m_rw.shifted()); - polys.avm_mem_m_tag_shift = Polynomial(polys.avm_mem_m_tag.shifted()); - polys.avm_mem_m_addr_shift = Polynomial(polys.avm_mem_m_addr.shifted()); - polys.avm_main_internal_return_ptr_shift = Polynomial(polys.avm_main_internal_return_ptr.shifted()); + polys.avm_alu_alu_u16_r2_shift = Polynomial(polys.avm_alu_alu_u16_r2.shifted()); polys.avm_main_pc_shift = Polynomial(polys.avm_main_pc.shifted()); + polys.avm_main_internal_return_ptr_shift = Polynomial(polys.avm_main_internal_return_ptr.shifted()); return polys; } @@ -298,30 +313,39 @@ class AvmCircuitBuilder { } for (auto r : lookup_result) { if (r != 0) { - info("Lookup ", lookup_name, " failed."); + throw_or_abort(format("Lookup ", lookup_name, " failed.")); return false; } } return true; }; - if (!evaluate_relation.template operator()>("avm_alu", - Avm_vm::get_relation_label_avm_alu)) { - return false; - } if (!evaluate_relation.template operator()>("avm_mem", Avm_vm::get_relation_label_avm_mem)) { return false; } + if (!evaluate_relation.template operator()>("avm_alu", + Avm_vm::get_relation_label_avm_alu)) { + return false; + } if (!evaluate_relation.template operator()>("avm_main", Avm_vm::get_relation_label_avm_main)) { return false; } - if (!evaluate_logderivative.template operator()>("equiv_inter_reg_alu")) { + if (!evaluate_logderivative.template operator()>("PERM_MAIN_ALU")) { + return false; + } + if (!evaluate_logderivative.template operator()>("PERM_MAIN_MEM_A")) { + return false; + } + if (!evaluate_logderivative.template operator()>("PERM_MAIN_MEM_B")) { + return false; + } + if (!evaluate_logderivative.template operator()>("PERM_MAIN_MEM_C")) { return false; } - if (!evaluate_logderivative.template operator()>("equiv_tag_err")) { + if (!evaluate_logderivative.template operator()>("INCL_MAIN_TAG_ERR")) { return false; } diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.cpp index 44546102f99..351c3ed0eb4 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.cpp @@ -559,6 +559,8 @@ template msgpack::sbuffer StandardCircuitBuilder_::export_circ cir.wires.push_back(tmp_w); } + cir.real_variable_index = this->real_variable_index; + msgpack::sbuffer buffer; msgpack::pack(buffer, cir); return buffer; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp index ee41b73f7ab..82b8dcc4b0b 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp @@ -115,7 +115,8 @@ template class StandardCircuitBuilder_ : public CircuitBuilderBase std::vector variables; std::vector> selectors; std::vector> wires; - MSGPACK_FIELDS(modulus, public_inps, vars_of_interest, variables, selectors, wires); + std::vector real_variable_index; + MSGPACK_FIELDS(modulus, public_inps, vars_of_interest, variables, selectors, wires, real_variable_index); } circuit_schema; }; diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp index 65df1840efa..172c02009ed 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp @@ -1,93 +1,29 @@ #include "protogalaxy_prover.hpp" #include "barretenberg/flavor/flavor.hpp" +#include "barretenberg/ultra_honk/oink_prover.hpp" namespace bb { template void ProtoGalaxyProver_::finalise_and_send_instance(std::shared_ptr instance, const std::string& domain_separator) { - instance->initialize_prover_polynomials(); + OinkProver oink_prover(instance, commitment_key, transcript, domain_separator + '_'); - const auto instance_size = static_cast(instance->proving_key->circuit_size); - const auto num_public_inputs = static_cast(instance->proving_key->num_public_inputs); - transcript->send_to_verifier(domain_separator + "_instance_size", instance_size); - transcript->send_to_verifier(domain_separator + "_public_input_size", num_public_inputs); + // Add circuit size public input size and public inputs to transcript + oink_prover.execute_preamble_round(); - for (size_t i = 0; i < instance->proving_key->public_inputs.size(); ++i) { - auto public_input_i = instance->proving_key->public_inputs[i]; - transcript->send_to_verifier(domain_separator + "_public_input_" + std::to_string(i), public_input_i); - } - transcript->send_to_verifier(domain_separator + "_pub_inputs_offset", - static_cast(instance->proving_key->pub_inputs_offset)); - - auto& witness_commitments = instance->witness_commitments; - - // Commit to the first three wire polynomials of the instance - // We only commit to the fourth wire polynomial after adding memory recordss - witness_commitments.w_l = commitment_key->commit(instance->proving_key->w_l); - witness_commitments.w_r = commitment_key->commit(instance->proving_key->w_r); - witness_commitments.w_o = commitment_key->commit(instance->proving_key->w_o); - - auto wire_comms = witness_commitments.get_wires(); - auto commitment_labels = instance->commitment_labels; - auto wire_labels = commitment_labels.get_wires(); - for (size_t idx = 0; idx < 3; ++idx) { - transcript->send_to_verifier(domain_separator + "_" + wire_labels[idx], wire_comms[idx]); - } - - if constexpr (IsGoblinFlavor) { - // Commit to Goblin ECC op wires - witness_commitments.ecc_op_wire_1 = commitment_key->commit(instance->proving_key->ecc_op_wire_1); - witness_commitments.ecc_op_wire_2 = commitment_key->commit(instance->proving_key->ecc_op_wire_2); - witness_commitments.ecc_op_wire_3 = commitment_key->commit(instance->proving_key->ecc_op_wire_3); - witness_commitments.ecc_op_wire_4 = commitment_key->commit(instance->proving_key->ecc_op_wire_4); - - auto op_wire_comms = instance->witness_commitments.get_ecc_op_wires(); - auto labels = commitment_labels.get_ecc_op_wires(); - for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { - transcript->send_to_verifier(domain_separator + "_" + labels[idx], op_wire_comms[idx]); - } - // Commit to DataBus columns - witness_commitments.calldata = commitment_key->commit(instance->proving_key->calldata); - witness_commitments.calldata_read_counts = commitment_key->commit(instance->proving_key->calldata_read_counts); - transcript->send_to_verifier(domain_separator + "_" + commitment_labels.calldata, - instance->witness_commitments.calldata); - transcript->send_to_verifier(domain_separator + "_" + commitment_labels.calldata_read_counts, - instance->witness_commitments.calldata_read_counts); - } - - auto eta = transcript->template get_challenge(domain_separator + "_eta"); - instance->compute_sorted_accumulator_polynomials(eta); - - // Commit to the sorted witness-table accumulator and the finalized (i.e. with memory records) fourth wire - // polynomial - witness_commitments.sorted_accum = commitment_key->commit(instance->prover_polynomials.sorted_accum); - witness_commitments.w_4 = commitment_key->commit(instance->prover_polynomials.w_4); + // Compute first three wire commitments + oink_prover.execute_wire_commitments_round(); - transcript->send_to_verifier(domain_separator + "_" + commitment_labels.sorted_accum, - witness_commitments.sorted_accum); - transcript->send_to_verifier(domain_separator + "_" + commitment_labels.w_4, witness_commitments.w_4); - - auto [beta, gamma] = - transcript->template get_challenges(domain_separator + "_beta", domain_separator + "_gamma"); - - if constexpr (IsGoblinFlavor) { - // Compute and commit to the logderivative inverse used in DataBus - instance->compute_logderivative_inverse(beta, gamma); - instance->witness_commitments.lookup_inverses = - commitment_key->commit(instance->prover_polynomials.lookup_inverses); - transcript->send_to_verifier(domain_separator + "_" + commitment_labels.lookup_inverses, - instance->witness_commitments.lookup_inverses); - } + // Compute sorted list accumulator and commitment + oink_prover.execute_sorted_list_accumulator_round(); - instance->compute_grand_product_polynomials(beta, gamma); + // Fiat-Shamir: beta & gamma + oink_prover.execute_log_derivative_inverse_round(); - witness_commitments.z_perm = commitment_key->commit(instance->prover_polynomials.z_perm); - witness_commitments.z_lookup = commitment_key->commit(instance->prover_polynomials.z_lookup); + // Compute grand product(s) and commitments. + oink_prover.execute_grand_product_computation_round(); - transcript->send_to_verifier(domain_separator + "_" + commitment_labels.z_perm, - instance->witness_commitments.z_perm); - transcript->send_to_verifier(domain_separator + "_" + commitment_labels.z_lookup, - instance->witness_commitments.z_lookup); + // Generate relation separators alphas for sumcheck for (size_t idx = 0; idx < NUM_SUBRELATIONS - 1; idx++) { instance->alphas[idx] = transcript->template get_challenge(domain_separator + "_alpha_" + std::to_string(idx)); @@ -199,11 +135,13 @@ std::shared_ptr ProtoGalaxyProver_ void ProtoGalaxyProver_::preparation_round() { + BB_OP_COUNT_TIME_NAME("ProtoGalaxyProver_::preparation_round"); prepare_for_folding(); }; template void ProtoGalaxyProver_::perturbator_round() { + BB_OP_COUNT_TIME_NAME("ProtoGalaxyProver_::perturbator_round"); state.accumulator = get_accumulator(); FF delta = transcript->template get_challenge("delta"); state.deltas = compute_round_challenge_pows(state.accumulator->proving_key->log_circuit_size, delta); @@ -221,6 +159,7 @@ template void ProtoGalaxyProver_::pertu template void ProtoGalaxyProver_::combiner_quotient_round() { + BB_OP_COUNT_TIME_NAME("ProtoGalaxyProver_::combiner_quotient_round"); auto perturbator_challenge = transcript->template get_challenge("perturbator_challenge"); instances.next_gate_challenges = update_gate_challenges(perturbator_challenge, state.accumulator->gate_challenges, state.deltas); @@ -239,6 +178,7 @@ template void ProtoGalaxyProver_::combi template void ProtoGalaxyProver_::accumulator_update_round() { + BB_OP_COUNT_TIME_NAME("ProtoGalaxyProver_::accumulator_update_round"); FF combiner_challenge = transcript->template get_challenge("combiner_quotient_challenge"); std::shared_ptr next_accumulator = compute_next_accumulator(instances, state.combiner_quotient, combiner_challenge, state.compressed_perturbator); diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp index 667460b5b20..cf08f67d30a 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp @@ -8,11 +8,13 @@ void ProtoGalaxyVerifier_::receive_and_finalise_instance(cons { // Get circuit parameters and the public inputs inst->verification_key->circuit_size = - transcript->template receive_from_prover(domain_separator + "_instance_size"); + transcript->template receive_from_prover(domain_separator + "_circuit_size"); inst->verification_key->log_circuit_size = static_cast(numeric::get_msb(inst->verification_key->circuit_size)); inst->verification_key->num_public_inputs = transcript->template receive_from_prover(domain_separator + "_public_input_size"); + inst->verification_key->pub_inputs_offset = + transcript->template receive_from_prover(domain_separator + "_pub_inputs_offset"); inst->verification_key->public_inputs.clear(); for (size_t i = 0; i < inst->verification_key->num_public_inputs; ++i) { auto public_input_i = @@ -20,9 +22,6 @@ void ProtoGalaxyVerifier_::receive_and_finalise_instance(cons inst->verification_key->public_inputs.emplace_back(public_input_i); } - inst->verification_key->pub_inputs_offset = - transcript->template receive_from_prover(domain_separator + "_pub_inputs_offset"); - // Get commitments to first three wire polynomials auto labels = inst->commitment_labels; auto& witness_commitments = inst->witness_commitments; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_alu.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_alu.hpp index a9566f3e20d..3357e7144e5 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_alu.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_alu.hpp @@ -7,77 +7,77 @@ namespace bb::Avm_vm { template struct Avm_aluRow { - FF avm_alu_alu_u128_tag{}; - FF avm_alu_alu_u16_r6{}; - FF avm_alu_alu_u16_tag{}; - FF avm_alu_alu_cf{}; - FF avm_alu_alu_u16_r4_shift{}; + FF avm_alu_alu_op_eq{}; + FF avm_alu_alu_u16_r5{}; + FF avm_alu_alu_op_sub{}; FF avm_alu_alu_u16_r5_shift{}; + FF avm_alu_alu_u16_r4{}; + FF avm_alu_alu_u16_r7{}; + FF avm_alu_alu_u8_tag{}; + FF avm_alu_alu_u16_r3_shift{}; + FF avm_alu_alu_u64_r0{}; + FF avm_alu_alu_ia{}; + FF avm_alu_alu_u32_tag{}; + FF avm_alu_alu_in_tag{}; + FF avm_alu_alu_u16_r2{}; + FF avm_alu_alu_u128_tag{}; + FF avm_alu_alu_u16_r0{}; FF avm_alu_alu_sel{}; + FF avm_alu_alu_ff_tag{}; + FF avm_alu_alu_op_eq_diff_inv{}; + FF avm_alu_alu_ic{}; FF avm_alu_alu_op_mul{}; - FF avm_alu_alu_u64_tag{}; - FF avm_alu_alu_u16_r2{}; + FF avm_alu_alu_cf{}; + FF avm_alu_alu_u16_r4_shift{}; + FF avm_alu_alu_u16_r6{}; FF avm_alu_alu_ib{}; - FF avm_alu_alu_u16_r2_shift{}; FF avm_alu_alu_u16_r7_shift{}; - FF avm_alu_alu_u16_r5{}; - FF avm_alu_alu_u8_r1{}; - FF avm_alu_alu_in_tag{}; - FF avm_alu_alu_u16_r3{}; - FF avm_alu_alu_u32_tag{}; - FF avm_alu_alu_ff_tag{}; - FF avm_alu_alu_u16_r1{}; - FF avm_alu_alu_u16_r0{}; - FF avm_alu_alu_u16_r0_shift{}; - FF avm_alu_alu_op_eq_diff_inv{}; FF avm_alu_alu_op_add{}; - FF avm_alu_alu_op_sub{}; - FF avm_alu_alu_op_not{}; - FF avm_alu_alu_u16_r3_shift{}; - FF avm_alu_alu_op_eq{}; + FF avm_alu_alu_u16_r1_shift{}; FF avm_alu_alu_u8_r0{}; + FF avm_alu_alu_op_not{}; + FF avm_alu_alu_u16_tag{}; + FF avm_alu_alu_u16_r1{}; + FF avm_alu_alu_u16_r0_shift{}; FF avm_alu_alu_u16_r6_shift{}; - FF avm_alu_alu_u64_r0{}; - FF avm_alu_alu_ic{}; - FF avm_alu_alu_u16_r7{}; - FF avm_alu_alu_u8_tag{}; - FF avm_alu_alu_u16_r1_shift{}; - FF avm_alu_alu_u16_r4{}; - FF avm_alu_alu_ia{}; + FF avm_alu_alu_u64_tag{}; + FF avm_alu_alu_u8_r1{}; + FF avm_alu_alu_u16_r3{}; + FF avm_alu_alu_u16_r2_shift{}; }; inline std::string get_relation_label_avm_alu(int index) { switch (index) { + case 18: + return "ALU_OP_NOT"; + case 19: return "ALU_RES_IS_BOOL"; - case 12: - return "ALU_MUL_COMMON_1"; + case 9: + return "ALU_ADD_SUB_1"; + + case 10: + return "ALU_ADD_SUB_2"; case 13: return "ALU_MUL_COMMON_2"; - case 17: - return "ALU_FF_NOT_XOR"; - - case 18: - return "ALU_OP_NOT"; - - case 16: - return "ALU_MULTIPLICATION_OUT_U128"; - case 20: return "ALU_OP_EQ"; - case 9: - return "ALU_ADD_SUB_1"; - - case 10: - return "ALU_ADD_SUB_2"; + case 17: + return "ALU_FF_NOT_XOR"; case 11: return "ALU_MULTIPLICATION_FF"; + + case 12: + return "ALU_MUL_COMMON_1"; + + case 16: + return "ALU_MULTIPLICATION_OUT_U128"; } return std::to_string(index); } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp index 24df5d3d40c..b48711ef2c7 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_main.hpp @@ -7,64 +7,64 @@ namespace bb::Avm_vm { template struct Avm_mainRow { - FF avm_main_sel_op_mul{}; - FF avm_main_rwa{}; - FF avm_main_mem_op_b{}; - FF avm_main_sel_internal_return{}; - FF avm_main_internal_return_ptr_shift{}; FF avm_main_mem_idx_b{}; - FF avm_main_ia{}; - FF avm_main_pc{}; - FF avm_main_alu_sel{}; + FF avm_main_rwc{}; FF avm_main_first{}; + FF avm_main_sel_jump{}; + FF avm_main_tag_err{}; + FF avm_main_mem_op_c{}; + FF avm_main_mem_op_b{}; + FF avm_main_mem_op_a{}; FF avm_main_sel_op_not{}; + FF avm_main_pc{}; + FF avm_main_sel_op_add{}; + FF avm_main_sel_internal_return{}; + FF avm_main_pc_shift{}; + FF avm_main_ic{}; + FF avm_main_internal_return_ptr_shift{}; FF avm_main_inv{}; - FF avm_main_tag_err{}; - FF avm_main_sel_op_eq{}; - FF avm_main_ib{}; FF avm_main_sel_internal_call{}; - FF avm_main_rwc{}; - FF avm_main_op_err{}; - FF avm_main_mem_idx_a{}; - FF avm_main_internal_return_ptr{}; - FF avm_main_sel_jump{}; + FF avm_main_rwa{}; FF avm_main_sel_halt{}; - FF avm_main_ic{}; - FF avm_main_sel_op_add{}; - FF avm_main_rwb{}; + FF avm_main_sel_op_mul{}; FF avm_main_sel_op_div{}; - FF avm_main_mem_op_a{}; - FF avm_main_mem_op_c{}; FF avm_main_sel_op_sub{}; - FF avm_main_pc_shift{}; + FF avm_main_mem_idx_a{}; + FF avm_main_rwb{}; + FF avm_main_op_err{}; + FF avm_main_ia{}; + FF avm_main_internal_return_ptr{}; + FF avm_main_alu_sel{}; + FF avm_main_sel_op_eq{}; + FF avm_main_ib{}; }; inline std::string get_relation_label_avm_main(int index) { switch (index) { - case 20: - return "SUBOP_DIVISION_ZERO_ERR2"; - case 34: return "PC_INCREMENT"; + case 23: + return "RETURN_POINTER_INCREMENT"; + case 29: return "RETURN_POINTER_DECREMENT"; - case 19: - return "SUBOP_DIVISION_ZERO_ERR1"; - case 18: return "SUBOP_DIVISION_FF"; + case 21: + return "SUBOP_ERROR_RELEVANT_OP"; + case 35: return "INTERNAL_RETURN_POINTER_CONSISTENCY"; - case 23: - return "RETURN_POINTER_INCREMENT"; + case 20: + return "SUBOP_DIVISION_ZERO_ERR2"; - case 21: - return "SUBOP_ERROR_RELEVANT_OP"; + case 19: + return "SUBOP_DIVISION_ZERO_ERR1"; } return std::to_string(index); } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_mem.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_mem.hpp index 97125695b32..dafa996d6fa 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_mem.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/avm_mem.hpp @@ -7,40 +7,44 @@ namespace bb::Avm_vm { template struct Avm_memRow { - FF avm_mem_m_rw{}; - FF avm_mem_m_in_tag{}; - FF avm_mem_m_lastAccess{}; - FF avm_mem_m_val_shift{}; - FF avm_mem_m_val{}; - FF avm_mem_m_rw_shift{}; - FF avm_mem_m_tag_err{}; FF avm_mem_m_tag_shift{}; - FF avm_mem_m_tag{}; - FF avm_mem_m_one_min_inv{}; + FF avm_mem_m_val_shift{}; + FF avm_mem_m_op_a{}; FF avm_mem_m_addr{}; + FF avm_mem_m_lastAccess{}; + FF avm_mem_m_tag{}; + FF avm_mem_m_rw_shift{}; + FF avm_mem_m_in_tag{}; FF avm_mem_m_last{}; + FF avm_mem_m_tag_err{}; FF avm_mem_m_addr_shift{}; + FF avm_mem_m_val{}; + FF avm_mem_m_one_min_inv{}; + FF avm_mem_m_op_b{}; + FF avm_mem_m_sub_clk{}; + FF avm_mem_m_op_c{}; + FF avm_mem_m_rw{}; }; inline std::string get_relation_label_avm_mem(int index) { switch (index) { - case 4: - return "MEM_LAST_ACCESS_DELIMITER"; - - case 7: - return "MEM_ZERO_INIT"; - - case 8: + case 13: return "MEM_IN_TAG_CONSISTENCY_1"; - case 5: + case 10: return "MEM_READ_WRITE_VAL_CONSISTENCY"; - case 6: + case 11: return "MEM_READ_WRITE_TAG_CONSISTENCY"; case 9: + return "MEM_LAST_ACCESS_DELIMITER"; + + case 12: + return "MEM_ZERO_INIT"; + + case 14: return "MEM_IN_TAG_CONSISTENCY_2"; } return std::to_string(index); @@ -50,8 +54,8 @@ template class avm_memImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 3, 3, 3, 3, 3, 4, 4, 4, 3, 3, + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3, }; template @@ -97,7 +101,7 @@ template class avm_memImpl { { Avm_DECLARE_VIEWS(4); - auto tmp = ((-avm_mem_m_lastAccess + FF(1)) * (avm_mem_m_addr_shift - avm_mem_m_addr)); + auto tmp = (avm_mem_m_op_a * (-avm_mem_m_op_a + FF(1))); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -105,8 +109,7 @@ template class avm_memImpl { { Avm_DECLARE_VIEWS(5); - auto tmp = (((-avm_mem_m_lastAccess + FF(1)) * (-avm_mem_m_rw_shift + FF(1))) * - (avm_mem_m_val_shift - avm_mem_m_val)); + auto tmp = (avm_mem_m_op_b * (-avm_mem_m_op_b + FF(1))); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -114,8 +117,7 @@ template class avm_memImpl { { Avm_DECLARE_VIEWS(6); - auto tmp = (((-avm_mem_m_lastAccess + FF(1)) * (-avm_mem_m_rw_shift + FF(1))) * - (avm_mem_m_tag_shift - avm_mem_m_tag)); + auto tmp = (avm_mem_m_op_c * (-avm_mem_m_op_c + FF(1))); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -123,7 +125,7 @@ template class avm_memImpl { { Avm_DECLARE_VIEWS(7); - auto tmp = ((avm_mem_m_lastAccess * (-avm_mem_m_rw_shift + FF(1))) * avm_mem_m_val_shift); + auto tmp = (avm_mem_m_sub_clk - (((avm_mem_m_rw * FF(3)) + avm_mem_m_op_b) + (avm_mem_m_op_c * FF(2)))); tmp *= scaling_factor; std::get<7>(evals) += tmp; } @@ -131,7 +133,8 @@ template class avm_memImpl { { Avm_DECLARE_VIEWS(8); - auto tmp = (((avm_mem_m_in_tag - avm_mem_m_tag) * (-avm_mem_m_one_min_inv + FF(1))) - avm_mem_m_tag_err); + auto tmp = (((avm_mem_m_op_a + avm_mem_m_op_b) + avm_mem_m_op_c) * + (((avm_mem_m_op_a + avm_mem_m_op_b) + avm_mem_m_op_c) - FF(1))); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -139,10 +142,52 @@ template class avm_memImpl { { Avm_DECLARE_VIEWS(9); - auto tmp = ((-avm_mem_m_tag_err + FF(1)) * avm_mem_m_one_min_inv); + auto tmp = ((-avm_mem_m_lastAccess + FF(1)) * (avm_mem_m_addr_shift - avm_mem_m_addr)); tmp *= scaling_factor; std::get<9>(evals) += tmp; } + // Contribution 10 + { + Avm_DECLARE_VIEWS(10); + + auto tmp = (((-avm_mem_m_lastAccess + FF(1)) * (-avm_mem_m_rw_shift + FF(1))) * + (avm_mem_m_val_shift - avm_mem_m_val)); + tmp *= scaling_factor; + std::get<10>(evals) += tmp; + } + // Contribution 11 + { + Avm_DECLARE_VIEWS(11); + + auto tmp = (((-avm_mem_m_lastAccess + FF(1)) * (-avm_mem_m_rw_shift + FF(1))) * + (avm_mem_m_tag_shift - avm_mem_m_tag)); + tmp *= scaling_factor; + std::get<11>(evals) += tmp; + } + // Contribution 12 + { + Avm_DECLARE_VIEWS(12); + + auto tmp = ((avm_mem_m_lastAccess * (-avm_mem_m_rw_shift + FF(1))) * avm_mem_m_val_shift); + tmp *= scaling_factor; + std::get<12>(evals) += tmp; + } + // Contribution 13 + { + Avm_DECLARE_VIEWS(13); + + auto tmp = (((avm_mem_m_in_tag - avm_mem_m_tag) * (-avm_mem_m_one_min_inv + FF(1))) - avm_mem_m_tag_err); + tmp *= scaling_factor; + std::get<13>(evals) += tmp; + } + // Contribution 14 + { + Avm_DECLARE_VIEWS(14); + + auto tmp = ((-avm_mem_m_tag_err + FF(1)) * avm_mem_m_one_min_inv); + tmp *= scaling_factor; + std::get<14>(evals) += tmp; + } } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp index 838e689b718..3cfe1455ce2 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp @@ -13,6 +13,9 @@ [[maybe_unused]] auto avm_mem_m_last = View(new_term.avm_mem_m_last); \ [[maybe_unused]] auto avm_mem_m_rw = View(new_term.avm_mem_m_rw); \ [[maybe_unused]] auto avm_mem_m_in_tag = View(new_term.avm_mem_m_in_tag); \ + [[maybe_unused]] auto avm_mem_m_op_a = View(new_term.avm_mem_m_op_a); \ + [[maybe_unused]] auto avm_mem_m_op_b = View(new_term.avm_mem_m_op_b); \ + [[maybe_unused]] auto avm_mem_m_op_c = View(new_term.avm_mem_m_op_c); \ [[maybe_unused]] auto avm_mem_m_tag_err = View(new_term.avm_mem_m_tag_err); \ [[maybe_unused]] auto avm_mem_m_one_min_inv = View(new_term.avm_mem_m_one_min_inv); \ [[maybe_unused]] auto avm_alu_alu_clk = View(new_term.avm_alu_alu_clk); \ @@ -76,20 +79,23 @@ [[maybe_unused]] auto avm_main_mem_idx_b = View(new_term.avm_main_mem_idx_b); \ [[maybe_unused]] auto avm_main_mem_idx_c = View(new_term.avm_main_mem_idx_c); \ [[maybe_unused]] auto avm_main_last = View(new_term.avm_main_last); \ - [[maybe_unused]] auto equiv_inter_reg_alu = View(new_term.equiv_inter_reg_alu); \ - [[maybe_unused]] auto equiv_tag_err = View(new_term.equiv_tag_err); \ - [[maybe_unused]] auto equiv_tag_err_counts = View(new_term.equiv_tag_err_counts); \ - [[maybe_unused]] auto avm_alu_alu_u16_r4_shift = View(new_term.avm_alu_alu_u16_r4_shift); \ + [[maybe_unused]] auto perm_main_alu = View(new_term.perm_main_alu); \ + [[maybe_unused]] auto perm_main_mem_a = View(new_term.perm_main_mem_a); \ + [[maybe_unused]] auto perm_main_mem_b = View(new_term.perm_main_mem_b); \ + [[maybe_unused]] auto perm_main_mem_c = View(new_term.perm_main_mem_c); \ + [[maybe_unused]] auto incl_main_tag_err = View(new_term.incl_main_tag_err); \ + [[maybe_unused]] auto incl_main_tag_err_counts = View(new_term.incl_main_tag_err_counts); \ + [[maybe_unused]] auto avm_mem_m_tag_shift = View(new_term.avm_mem_m_tag_shift); \ + [[maybe_unused]] auto avm_mem_m_val_shift = View(new_term.avm_mem_m_val_shift); \ + [[maybe_unused]] auto avm_mem_m_rw_shift = View(new_term.avm_mem_m_rw_shift); \ + [[maybe_unused]] auto avm_mem_m_addr_shift = View(new_term.avm_mem_m_addr_shift); \ [[maybe_unused]] auto avm_alu_alu_u16_r5_shift = View(new_term.avm_alu_alu_u16_r5_shift); \ - [[maybe_unused]] auto avm_alu_alu_u16_r2_shift = View(new_term.avm_alu_alu_u16_r2_shift); \ + [[maybe_unused]] auto avm_alu_alu_u16_r3_shift = View(new_term.avm_alu_alu_u16_r3_shift); \ + [[maybe_unused]] auto avm_alu_alu_u16_r4_shift = View(new_term.avm_alu_alu_u16_r4_shift); \ [[maybe_unused]] auto avm_alu_alu_u16_r7_shift = View(new_term.avm_alu_alu_u16_r7_shift); \ + [[maybe_unused]] auto avm_alu_alu_u16_r1_shift = View(new_term.avm_alu_alu_u16_r1_shift); \ [[maybe_unused]] auto avm_alu_alu_u16_r0_shift = View(new_term.avm_alu_alu_u16_r0_shift); \ - [[maybe_unused]] auto avm_alu_alu_u16_r3_shift = View(new_term.avm_alu_alu_u16_r3_shift); \ [[maybe_unused]] auto avm_alu_alu_u16_r6_shift = View(new_term.avm_alu_alu_u16_r6_shift); \ - [[maybe_unused]] auto avm_alu_alu_u16_r1_shift = View(new_term.avm_alu_alu_u16_r1_shift); \ - [[maybe_unused]] auto avm_mem_m_val_shift = View(new_term.avm_mem_m_val_shift); \ - [[maybe_unused]] auto avm_mem_m_rw_shift = View(new_term.avm_mem_m_rw_shift); \ - [[maybe_unused]] auto avm_mem_m_tag_shift = View(new_term.avm_mem_m_tag_shift); \ - [[maybe_unused]] auto avm_mem_m_addr_shift = View(new_term.avm_mem_m_addr_shift); \ - [[maybe_unused]] auto avm_main_internal_return_ptr_shift = View(new_term.avm_main_internal_return_ptr_shift); \ - [[maybe_unused]] auto avm_main_pc_shift = View(new_term.avm_main_pc_shift); + [[maybe_unused]] auto avm_alu_alu_u16_r2_shift = View(new_term.avm_alu_alu_u16_r2_shift); \ + [[maybe_unused]] auto avm_main_pc_shift = View(new_term.avm_main_pc_shift); \ + [[maybe_unused]] auto avm_main_internal_return_ptr_shift = View(new_term.avm_main_internal_return_ptr_shift); diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/equiv_tag_err.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/incl_main_tag_err.hpp similarity index 92% rename from barretenberg/cpp/src/barretenberg/relations/generated/avm/equiv_tag_err.hpp rename to barretenberg/cpp/src/barretenberg/relations/generated/avm/incl_main_tag_err.hpp index 858ecfafa09..050f662d86b 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/equiv_tag_err.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/incl_main_tag_err.hpp @@ -23,7 +23,7 @@ namespace bb { * FF>>;)` * */ -class equiv_tag_err_lookup_settings { +class incl_main_tag_err_lookup_settings { public: /** * @brief The number of read terms (how many lookups we perform) in each row @@ -133,8 +133,8 @@ class equiv_tag_err_lookup_settings { template static inline auto get_const_entities(const AllEntities& in) { - return std::forward_as_tuple(in.equiv_tag_err, - in.equiv_tag_err_counts, + return std::forward_as_tuple(in.incl_main_tag_err, + in.incl_main_tag_err_counts, in.avm_mem_m_tag_err, in.avm_main_tag_err, in.avm_mem_m_clk, @@ -151,8 +151,8 @@ class equiv_tag_err_lookup_settings { template static inline auto get_nonconst_entities(AllEntities& in) { - return std::forward_as_tuple(in.equiv_tag_err, - in.equiv_tag_err_counts, + return std::forward_as_tuple(in.incl_main_tag_err, + in.incl_main_tag_err_counts, in.avm_mem_m_tag_err, in.avm_main_tag_err, in.avm_mem_m_clk, @@ -160,7 +160,8 @@ class equiv_tag_err_lookup_settings { } }; -template using equiv_tag_err_relation = GenericLookupRelation; -template using equiv_tag_err = GenericLookup; +template +using incl_main_tag_err_relation = GenericLookupRelation; +template using incl_main_tag_err = GenericLookup; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/equiv_inter_reg_alu.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp similarity index 93% rename from barretenberg/cpp/src/barretenberg/relations/generated/avm/equiv_inter_reg_alu.hpp rename to barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp index e0c5b799aeb..a83ab5eafeb 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/equiv_inter_reg_alu.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp @@ -9,7 +9,7 @@ namespace bb { -class equiv_inter_reg_alu_permutation_settings { +class perm_main_alu_permutation_settings { public: // This constant defines how many columns are bundled together to form each set. constexpr static size_t COLUMNS_PER_SET = 10; @@ -46,7 +46,7 @@ class equiv_inter_reg_alu_permutation_settings { template static inline auto get_const_entities(const AllEntities& in) { - return std::forward_as_tuple(in.equiv_inter_reg_alu, + return std::forward_as_tuple(in.perm_main_alu, in.avm_main_alu_sel, in.avm_main_alu_sel, in.avm_alu_alu_sel, @@ -92,7 +92,7 @@ class equiv_inter_reg_alu_permutation_settings { template static inline auto get_nonconst_entities(AllEntities& in) { - return std::forward_as_tuple(in.equiv_inter_reg_alu, + return std::forward_as_tuple(in.perm_main_alu, in.avm_main_alu_sel, in.avm_main_alu_sel, in.avm_alu_alu_sel, @@ -120,7 +120,7 @@ class equiv_inter_reg_alu_permutation_settings { }; template -using equiv_inter_reg_alu_relation = GenericPermutationRelation; -template using equiv_inter_reg_alu = GenericPermutation; +using perm_main_alu_relation = GenericPermutationRelation; +template using perm_main_alu = GenericPermutation; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_a.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_a.hpp new file mode 100644 index 00000000000..5d52373810e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_a.hpp @@ -0,0 +1,106 @@ + + +#pragma once + +#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" + +#include +#include + +namespace bb { + +class perm_main_mem_a_permutation_settings { + public: + // This constant defines how many columns are bundled together to form each set. + constexpr static size_t COLUMNS_PER_SET = 5; + + /** + * @brief If this method returns true on a row of values, then the inverse polynomial at this index. Otherwise the + * value needs to be set to zero. + * + * @details If this is true then permutation takes place in this row + */ + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.avm_main_mem_op_a == 1 || in.avm_mem_m_op_a == 1); + } + + /** + * @brief Get all the entities for the permutation when we don't need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + + template static inline auto get_const_entities(const AllEntities& in) + { + + return std::forward_as_tuple(in.perm_main_mem_a, + in.avm_main_mem_op_a, + in.avm_main_mem_op_a, + in.avm_mem_m_op_a, + in.avm_main_clk, + in.avm_main_mem_idx_a, + in.avm_main_ia, + in.avm_main_rwa, + in.avm_main_in_tag, + in.avm_mem_m_clk, + in.avm_mem_m_addr, + in.avm_mem_m_val, + in.avm_mem_m_rw, + in.avm_mem_m_in_tag); + } + + /** + * @brief Get all the entities for the permutation when need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + + template static inline auto get_nonconst_entities(AllEntities& in) + { + + return std::forward_as_tuple(in.perm_main_mem_a, + in.avm_main_mem_op_a, + in.avm_main_mem_op_a, + in.avm_mem_m_op_a, + in.avm_main_clk, + in.avm_main_mem_idx_a, + in.avm_main_ia, + in.avm_main_rwa, + in.avm_main_in_tag, + in.avm_mem_m_clk, + in.avm_mem_m_addr, + in.avm_mem_m_val, + in.avm_mem_m_rw, + in.avm_mem_m_in_tag); + } +}; + +template +using perm_main_mem_a_relation = GenericPermutationRelation; +template using perm_main_mem_a = GenericPermutation; + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_b.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_b.hpp new file mode 100644 index 00000000000..071d5a6eb53 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_b.hpp @@ -0,0 +1,106 @@ + + +#pragma once + +#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" + +#include +#include + +namespace bb { + +class perm_main_mem_b_permutation_settings { + public: + // This constant defines how many columns are bundled together to form each set. + constexpr static size_t COLUMNS_PER_SET = 5; + + /** + * @brief If this method returns true on a row of values, then the inverse polynomial at this index. Otherwise the + * value needs to be set to zero. + * + * @details If this is true then permutation takes place in this row + */ + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.avm_main_mem_op_b == 1 || in.avm_mem_m_op_b == 1); + } + + /** + * @brief Get all the entities for the permutation when we don't need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + + template static inline auto get_const_entities(const AllEntities& in) + { + + return std::forward_as_tuple(in.perm_main_mem_b, + in.avm_main_mem_op_b, + in.avm_main_mem_op_b, + in.avm_mem_m_op_b, + in.avm_main_clk, + in.avm_main_mem_idx_b, + in.avm_main_ib, + in.avm_main_rwb, + in.avm_main_in_tag, + in.avm_mem_m_clk, + in.avm_mem_m_addr, + in.avm_mem_m_val, + in.avm_mem_m_rw, + in.avm_mem_m_in_tag); + } + + /** + * @brief Get all the entities for the permutation when need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + + template static inline auto get_nonconst_entities(AllEntities& in) + { + + return std::forward_as_tuple(in.perm_main_mem_b, + in.avm_main_mem_op_b, + in.avm_main_mem_op_b, + in.avm_mem_m_op_b, + in.avm_main_clk, + in.avm_main_mem_idx_b, + in.avm_main_ib, + in.avm_main_rwb, + in.avm_main_in_tag, + in.avm_mem_m_clk, + in.avm_mem_m_addr, + in.avm_mem_m_val, + in.avm_mem_m_rw, + in.avm_mem_m_in_tag); + } +}; + +template +using perm_main_mem_b_relation = GenericPermutationRelation; +template using perm_main_mem_b = GenericPermutation; + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_c.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_c.hpp new file mode 100644 index 00000000000..41f22dc0193 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_c.hpp @@ -0,0 +1,106 @@ + + +#pragma once + +#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" + +#include +#include + +namespace bb { + +class perm_main_mem_c_permutation_settings { + public: + // This constant defines how many columns are bundled together to form each set. + constexpr static size_t COLUMNS_PER_SET = 5; + + /** + * @brief If this method returns true on a row of values, then the inverse polynomial at this index. Otherwise the + * value needs to be set to zero. + * + * @details If this is true then permutation takes place in this row + */ + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.avm_main_mem_op_c == 1 || in.avm_mem_m_op_c == 1); + } + + /** + * @brief Get all the entities for the permutation when we don't need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + + template static inline auto get_const_entities(const AllEntities& in) + { + + return std::forward_as_tuple(in.perm_main_mem_c, + in.avm_main_mem_op_c, + in.avm_main_mem_op_c, + in.avm_mem_m_op_c, + in.avm_main_clk, + in.avm_main_mem_idx_c, + in.avm_main_ic, + in.avm_main_rwc, + in.avm_main_in_tag, + in.avm_mem_m_clk, + in.avm_mem_m_addr, + in.avm_mem_m_val, + in.avm_mem_m_rw, + in.avm_mem_m_in_tag); + } + + /** + * @brief Get all the entities for the permutation when need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + + template static inline auto get_nonconst_entities(AllEntities& in) + { + + return std::forward_as_tuple(in.perm_main_mem_c, + in.avm_main_mem_op_c, + in.avm_main_mem_op_c, + in.avm_mem_m_op_c, + in.avm_main_clk, + in.avm_main_mem_idx_c, + in.avm_main_ic, + in.avm_main_rwc, + in.avm_main_in_tag, + in.avm_mem_m_clk, + in.avm_mem_m_addr, + in.avm_mem_m_val, + in.avm_mem_m_rw, + in.avm_mem_m_in_tag); + } +}; + +template +using perm_main_mem_c_relation = GenericPermutationRelation; +template using perm_main_mem_c = GenericPermutation; + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit.cpp b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit.cpp index 7ff95288576..d8c2c666a6c 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit.cpp +++ b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit.cpp @@ -3,53 +3,7 @@ namespace smt_circuit { /** - * @brief Get the CircuitSchema object - * @details Initialize the CircuitSchmea from the binary file - * that contains an msgpack compatible buffer. - * - * @param filename - * @return CircuitSchema - */ -CircuitSchema unpack_from_file(const std::string& filename) -{ - std::ifstream fin; - fin.open(filename, std::ios::in | std::ios::binary); - if (!fin.is_open()) { - throw std::invalid_argument("file not found"); - } - if (fin.tellg() == -1) { - throw std::invalid_argument("something went wrong"); - } - - fin.ignore(std::numeric_limits::max()); // ohboy - std::streamsize fsize = fin.gcount(); - fin.clear(); - fin.seekg(0, std::ios_base::beg); - info("File size: ", fsize); - - CircuitSchema cir; - char* encoded_data = (char*)aligned_alloc(64, static_cast(fsize)); - fin.read(encoded_data, fsize); - msgpack::unpack((const char*)encoded_data, static_cast(fsize)).get().convert(cir); - return cir; -} - -/** - * @brief Get the CircuitSchema object - * @details Initialize the CircuitSchmea from the msgpack compatible buffer. - * - * @param buf - * @return CircuitSchema - */ -CircuitSchema unpack_from_buffer(const msgpack::sbuffer& buf) -{ - CircuitSchema cir; - msgpack::unpack(buf.data(), buf.size()).get().convert(cir); - return cir; -} - -/** - * @brief Check your circuit for witness uniqness + * @brief Check your circuit for witness uniqueness * * @details Creates two Circuit objects that represent the same * circuit, however you can choose which variables should be (not) equal in both cases, @@ -57,19 +11,19 @@ CircuitSchema unpack_from_buffer(const msgpack::sbuffer& buf) * * @param circuit_info * @param s pointer to the global solver - * @param equal all the variables that should be equal in both circuits - * @param nequal all the variables that should be different in both circuits - * @param eqall all the variables that should not be equal at the same time - * @param neqall all the variables that should not be different at the same time + * @param equal The list of names of variables which should be equal in both circuits(each is equal) + * @param not_equal The list of names of variables which should not be equal in both circuits(each is not equal) + * @param equal_at_the_same_time The list of variables, where at least one pair has to be equal + * @param not_equal_at_the_same_time The list of variables, where at least one pair has to be distinct * @return std::pair */ template -std::pair, Circuit> unique_witness(CircuitSchema& circuit_info, - Solver* s, - const std::vector& equal, - const std::vector& not_equal, - const std::vector& equal_at_the_same_time, - const std::vector& not_equal_at_the_same_time) +std::pair, Circuit> unique_witness_ext(CircuitSchema& circuit_info, + Solver* s, + const std::vector& equal, + const std::vector& not_equal, + const std::vector& equal_at_the_same_time, + const std::vector& not_equal_at_the_same_time) { Circuit c1(circuit_info, s, "circuit1"); Circuit c2(circuit_info, s, "circuit2"); @@ -107,7 +61,7 @@ std::pair, Circuit> unique_witness(CircuitSchema& circuit_info, return { c1, c2 }; } -template std::pair, Circuit> unique_witness( +template std::pair, Circuit> unique_witness_ext( CircuitSchema& circuit_info, Solver* s, const std::vector& equal = {}, @@ -115,7 +69,7 @@ template std::pair, Circuit> unique_witness( const std::vector& equal_at_the_same_time = {}, const std::vector& not_eqaul_at_the_same_time = {}); -template std::pair, Circuit> unique_witness( +template std::pair, Circuit> unique_witness_ext( CircuitSchema& circuit_info, Solver* s, const std::vector& equal = {}, @@ -123,4 +77,54 @@ template std::pair, Circuit> unique_witness( const std::vector& equal_at_the_same_time = {}, const std::vector& not_eqaul_at_the_same_time = {}); +/** + * @brief Check your circuit for witness uniqueness + * + * @details Creates two Circuit objects that represent the same + * circuit, however you can choose which variables should be equal in both cases, + * other witness members will be marked as not equal at the same time + * or basically they will have to differ by at least one element. + * + * @param circuit_info + * @param s pointer to the global solver + * @param equal The list of names of variables which should be equal in both circuits(each is equal) + * @return std::pair + */ +template +std::pair, Circuit> unique_witness(CircuitSchema& circuit_info, + Solver* s, + const std::vector& equal) +{ + Circuit c1(circuit_info, s, "circuit1"); + Circuit c2(circuit_info, s, "circuit2"); + + for (const auto& term : equal) { + c1[term] == c2[term]; + } + + std::vector neqs; + for (const auto& node : c1.symbolic_vars) { + uint32_t i = node.first; + if (std::find(equal.begin(), equal.end(), std::string(c1.variable_names[i])) != equal.end()) { + continue; + } + Bool tmp = Bool(c1[i]) != Bool(c2[i]); + neqs.push_back(tmp); + } + + if (neqs.size() > 1) { + batch_or(neqs).assert_term(); + } else if (neqs.size() == 1) { + neqs[0].assert_term(); + } + return { c1, c2 }; +} + +template std::pair, Circuit> unique_witness(CircuitSchema& circuit_info, + Solver* s, + const std::vector& equal = {}); + +template std::pair, Circuit> unique_witness(CircuitSchema& circuit_info, + Solver* s, + const std::vector& equal = {}); }; // namespace smt_circuit \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit.hpp b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit.hpp index 57ed452b7ba..d8f7f5f3777 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit.hpp +++ b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit.hpp @@ -1,30 +1,20 @@ #pragma once -#include #include #include #include #include -#include "barretenberg/serialize/cbind.hpp" -#include "barretenberg/serialize/msgpack.hpp" - #include "barretenberg/smt_verification/terms/bool.hpp" #include "barretenberg/smt_verification/terms/ffiterm.hpp" #include "barretenberg/smt_verification/terms/ffterm.hpp" +#include "subcircuits.hpp" + namespace smt_circuit { using namespace smt_solver; using namespace smt_terms; - -struct CircuitSchema { - std::string modulus; - std::vector public_inps; - std::unordered_map vars_of_interest; - std::vector variables; - std::vector> selectors; - std::vector> wires; - MSGPACK_FIELDS(modulus, public_inps, vars_of_interest, variables, selectors, wires); -}; +using namespace smt_circuit_schema; +using namespace smt_subcircuits; /** * @brief Symbolic Circuit class. @@ -37,16 +27,19 @@ struct CircuitSchema { template class Circuit { private: void init(); - void add_gates(); + + size_t prepare_gates(size_t cursor); + void univariate_handler(bb::fr q_m, bb::fr q_1, bb::fr q_2, bb::fr q_3, bb::fr q_c, uint32_t w); public: - std::vector variables; // circuit witness - std::vector public_inps; // public inputs from the circuit - std::unordered_map vars_of_interest; // names of the variables - std::unordered_map terms; // inverse map of the previous memeber - std::vector> selectors; // selectors from the circuit - std::vector> wires_idxs; // values of the gates' wires - std::vector vars; // all the symbolic variables from the circuit + std::vector variables; // circuit witness + std::vector public_inps; // public inputs from the circuit + std::unordered_map variable_names; // names of the variables + std::unordered_map variable_names_inverse; // inverse map of the previous memeber + std::vector> selectors; // selectors from the circuit + std::vector> wires_idxs; // values of the gates' wires + std::unordered_map symbolic_vars; // all the symbolic variables from the circuit + std::vector real_variable_index; // indexes for assert_equal'd wires Solver* solver; // pointer to the solver std::string tag; // tag of the symbolic circuit. @@ -56,9 +49,12 @@ template class Circuit { explicit Circuit(CircuitSchema& circuit_info, Solver* solver, const std::string& tag = ""); FF operator[](const std::string& name); - FF operator[](const uint32_t& idx) { return vars[idx]; }; - inline uint32_t get_num_gates() const { return static_cast(selectors.size()); }; - inline uint32_t get_num_vars() const { return static_cast(vars.size()); }; + FF operator[](const uint32_t& idx) { return symbolic_vars[this->real_variable_index[idx]]; }; + inline size_t get_num_gates() const { return selectors.size(); }; + inline size_t get_num_real_vars() const { return symbolic_vars.size(); }; + inline size_t get_num_vars() const { return variables.size(); }; + + bool simulate_circuit_eval(std::vector& witness) const; }; /** @@ -70,9 +66,12 @@ template class Circuit { */ template Circuit::Circuit(CircuitSchema& circuit_info, Solver* solver, const std::string& tag) - : public_inps(circuit_info.public_inps) - , vars_of_interest(circuit_info.vars_of_interest) + : variables(circuit_info.variables) + , public_inps(circuit_info.public_inps) + , variable_names(circuit_info.vars_of_interest) + , selectors(circuit_info.selectors) , wires_idxs(circuit_info.wires) + , real_variable_index(circuit_info.real_variable_index) , solver(solver) , tag(tag) { @@ -82,37 +81,23 @@ Circuit::Circuit(CircuitSchema& circuit_info, Solver* solver, const std::str } } - for (auto var : circuit_info.variables) { - std::stringstream buf; // TODO(alex): looks bad. Would be great to create tostring() converter - buf << var; - std::string tmp = buf.str(); - tmp[1] = '0'; // avoiding `x` in 0x prefix - variables.push_back(tmp); + for (auto& x : variable_names) { + variable_names_inverse.insert({ x.second, x.first }); } - for (auto& x : vars_of_interest) { - terms.insert({ x.second, x.first }); - } - - vars_of_interest.insert({ 0, "zero" }); - vars_of_interest.insert({ 1, "one" }); - terms.insert({ "zero", 0 }); - terms.insert({ "one", 1 }); - - for (auto sel : circuit_info.selectors) { - std::vector tmp_sel; - for (size_t j = 0; j < 5; j++) { - std::stringstream buf; // TODO(alex): #2 - buf << sel[j]; - std::string q_i = buf.str(); - q_i[1] = '0'; // avoiding `x` in 0x prefix - tmp_sel.push_back(q_i); - } - selectors.push_back(tmp_sel); - } + variable_names.insert({ 0, "zero" }); + variable_names.insert({ 1, "one" }); + variable_names_inverse.insert({ "zero", 0 }); + variable_names_inverse.insert({ "one", 1 }); this->init(); - this->add_gates(); + + // Perform all relaxation for gates or + // add gate in its normal state to solver + size_t i = 0; + while (i < this->get_num_gates()) { + i = this->prepare_gates(i); + } } /** @@ -124,80 +109,129 @@ template void Circuit::init() { size_t num_vars = variables.size(); - vars.push_back(FF::Var("zero" + this->tag, this->solver)); - vars.push_back(FF::Var("one" + this->tag, this->solver)); + symbolic_vars.insert({ 0, FF::Var("zero" + this->tag, this->solver) }); + symbolic_vars.insert({ 1, FF::Var("one" + this->tag, this->solver) }); - for (size_t i = 2; i < num_vars; i++) { - if (vars_of_interest.contains(static_cast(i))) { - std::string name = vars_of_interest[static_cast(i)]; - vars.push_back(FF::Var(name + this->tag, this->solver)); + for (uint32_t i = 2; i < num_vars; i++) { + uint32_t real_idx = this->real_variable_index[i]; + if (this->symbolic_vars.contains(real_idx)) { + continue; + } + + if (variable_names.contains(real_idx)) { + std::string name = variable_names[real_idx]; + symbolic_vars.insert({ real_idx, FF::Var(name + this->tag, this->solver) }); } else { - vars.push_back(FF::Var("var_" + std::to_string(i) + this->tag, this->solver)); + symbolic_vars.insert({ real_idx, FF::Var("var_" + std::to_string(i) + this->tag, this->solver) }); } } - vars[0] == FF::Const("0", this->solver); - vars[1] == FF::Const("1", this->solver); + symbolic_vars[0] == bb::fr(0); + symbolic_vars[1] == bb::fr(1); +} + +/** + * @brief Relaxes univariate polynomial constraints. + * TODO(alex): probably won't be necessary in the nearest future + * because of new solver + * + * @param q_m multiplication selector + * @param q_1 l selector + * @param q_2 r selector + * @param q_3 o selector + * @param q_c constant + * @param w witness index + */ +template +void Circuit::univariate_handler(bb::fr q_m, bb::fr q_1, bb::fr q_2, bb::fr q_3, bb::fr q_c, uint32_t w) +{ + bb::fr b = q_1 + q_2 + q_3; + + if (q_m == 0) { + symbolic_vars[w] == -q_c / b; + return; + } - for (auto i : public_inps) { - vars[i] == FF::Const(variables[i], this->solver); + std::pair d = (b * b - bb::fr(4) * q_m * q_c).sqrt(); + if (!d.first) { + throw std::invalid_argument("There're no roots of quadratic polynomial"); + } + bb::fr x1 = (-b + d.second) / (bb::fr(2) * q_m); + bb::fr x2 = (-b - d.second) / (bb::fr(2) * q_m); + + if (d.second == 0) { + symbolic_vars[w] == FF(x1, this->solver); + } else { + ((Bool(symbolic_vars[w]) == Bool(FF(x1, this->solver))) | + (Bool(symbolic_vars[w]) == Bool(FF(x2, this->solver)))) + .assert_term(); } } /** * @brief Adds all the gate constraints to the solver. + * Relaxes constraint system for non-ff solver engines + * via removing subcircuits that were already proved being correct. * */ -template void Circuit::add_gates() +template size_t Circuit::prepare_gates(size_t cursor) { - for (size_t i = 0; i < get_num_gates(); i++) { - FF q_m = FF::Const(selectors[i][0], this->solver); - FF q_1 = FF::Const(selectors[i][1], this->solver); - FF q_2 = FF::Const(selectors[i][2], this->solver); - FF q_3 = FF::Const(selectors[i][3], this->solver); - FF q_c = FF::Const(selectors[i][4], this->solver); - - uint32_t w_l = wires_idxs[i][0]; - uint32_t w_r = wires_idxs[i][1]; - uint32_t w_o = wires_idxs[i][2]; - - // Binary gate. Relaxes the solver. - // TODO(alex): Probably we can add other basic gates here too to relax the stuff. - // TODO(alex): Theoretically this can be applyed after we ensure that the block of polynomial equations holds - // and then simplify that block in future to relax the solver constraint system. Seems like a hard one to - // implement or actually to automate, but I'll think on it for a while. it will probably require to split - // add_gates and init methods into more complex/generalized parts. - if (w_l == w_r && w_r == w_o) { - if (std::string(q_m) == "1" && std::string(q_1) == "0" && std::string(q_2) == "0" && - std::string(q_3) == "-1" && std::string(q_c) == "0") { // squaring gate - (Bool(vars[w_l]) == Bool(vars[0]) | Bool(vars[w_l]) == Bool(vars[1])).assert_term(); - } - } + // TODO(alex): Here'll be the operator relaxation that is coming + // in the next pr - FF eq = vars[0]; + bb::fr q_m = this->selectors[cursor][0]; + bb::fr q_1 = this->selectors[cursor][1]; + bb::fr q_2 = this->selectors[cursor][2]; + bb::fr q_3 = this->selectors[cursor][3]; + bb::fr q_c = this->selectors[cursor][4]; - // mult selector - if (std::string(q_m) != "0") { - eq += q_m * vars[w_l] * vars[w_r]; + uint32_t w_l = this->wires_idxs[cursor][0]; + uint32_t w_r = this->wires_idxs[cursor][1]; + uint32_t w_o = this->wires_idxs[cursor][2]; + + bool univariate_flag = w_l == w_r && w_r == w_o; + univariate_flag |= w_l == w_r && q_3 == 0; + univariate_flag |= w_l == w_o && q_2 == 0 && q_m == 0; + univariate_flag |= w_r == w_o && q_1 == 0 && q_m == 0; + univariate_flag |= q_m == 0 && q_1 == 0 && q_3 == 0; + univariate_flag |= q_m == 0 && q_2 == 0 && q_3 == 0; + univariate_flag |= q_m == 0 && q_1 == 0 && q_2 == 0; + + // Univariate gate. Relaxes the solver. Or is it? + // TODO(alex): Test the effect of this relaxation after the tests are merged. + if (univariate_flag) { + if (q_m == 1 && q_1 == 0 && q_2 == 0 && q_3 == -1 && q_c == 0) { + (Bool(symbolic_vars[w_l]) == Bool(symbolic_vars[0]) | Bool(symbolic_vars[w_l]) == Bool(symbolic_vars[1])) + .assert_term(); + } else { + this->univariate_handler(q_m, q_1, q_2, q_3, q_c, w_l); } - // w_l selector - if (std::string(q_1) != "0") { - eq += q_1 * vars[w_l]; + } else { + FF eq = symbolic_vars[0]; + + // mul selector + if (q_m != 0) { + eq += symbolic_vars[w_l] * symbolic_vars[w_r] * q_m; // TODO(alex): Is there a way to do lmul? + } + // left selector + if (q_1 != 0) { + eq += symbolic_vars[w_l] * q_1; } - // w_r selector - if (std::string(q_2) != "0") { - eq += q_2 * vars[w_r]; + // right selector + if (q_2 != 0) { + eq += symbolic_vars[w_r] * q_2; } - // w_o selector - if (std::string(q_3) != "0") { - eq += q_3 * vars[w_o]; + // out selector + if (q_3 != 0) { + eq += symbolic_vars[w_o] * q_3; } - // w_c selector - if (std::string(q_c) != "0") { + // constant selector + if (q_c != 0) { eq += q_c; } - eq == vars[0]; + eq == symbolic_vars[0]; } + return cursor + 1; } /** @@ -208,22 +242,78 @@ template void Circuit::add_gates() */ template FF Circuit::operator[](const std::string& name) { - if (!this->terms.contains(name)) { - throw std::length_error("No such an item " + name + " in vars or it vas not declared as interesting"); + if (!this->variable_names_inverse.contains(name)) { + throw std::invalid_argument("No such an item `" + name + "` in vars or it vas not declared as interesting"); + } + uint32_t idx = this->variable_names_inverse[name]; + return this->symbolic_vars[idx]; +} + +/** + * @brief Similar functionality to old .check_circuit() method + * in standard circuit builder. + * + * @param witness + * @return true + * @return false + */ +template bool Circuit::simulate_circuit_eval(std::vector& witness) const +{ + if (witness.size() != this->get_num_vars()) { + throw std::invalid_argument("Witness size should be " + std::to_string(this->get_num_vars()) + ", not " + + std::to_string(witness.size())); + } + for (size_t i = 0; i < this->selectors.size(); i++) { + bb::fr res = 0; + bb::fr x = witness[this->wires_idxs[i][0]]; + bb::fr y = witness[this->wires_idxs[i][1]]; + bb::fr o = witness[this->wires_idxs[i][2]]; + res += this->selectors[i][0] * x * y; + res += this->selectors[i][1] * x; + res += this->selectors[i][2] * y; + res += this->selectors[i][3] * o; + res += this->selectors[i][4]; + if (res != 0) { + return false; + } } - uint32_t idx = this->terms[name]; - return this->vars[idx]; + return true; } -CircuitSchema unpack_from_buffer(const msgpack::sbuffer& buf); -CircuitSchema unpack_from_file(const std::string& fname); +template +std::pair, Circuit> unique_witness_ext(CircuitSchema& circuit_info, + Solver* s, + const std::vector& equal = {}, + const std::vector& not_equal = {}, + const std::vector& equal_at_the_same_time = {}, + const std::vector& not_equal_at_the_same_time = {}); + +extern template std::pair, Circuit> unique_witness_ext( + CircuitSchema& circuit_info, + Solver* s, + const std::vector& equal = {}, + const std::vector& not_equal = {}, + const std::vector& equal_at_the_same_time = {}, + const std::vector& not_equal_at_the_same_time = {}); + +extern template std::pair, Circuit> unique_witness_ext( + CircuitSchema& circuit_info, + Solver* s, + const std::vector& equal = {}, + const std::vector& not_equal = {}, + const std::vector& equal_at_the_same_time = {}, + const std::vector& not_equal_at_the_same_time = {}); template std::pair, Circuit> unique_witness(CircuitSchema& circuit_info, Solver* s, - const std::vector& equal = {}, - const std::vector& not_equal = {}, - const std::vector& equal_at_the_same_time = {}, - const std::vector& not_eqaul_at_the_same_time = {}); + const std::vector& equal = {}); + +extern template std::pair, Circuit> unique_witness(CircuitSchema& circuit_info, + Solver* s, + const std::vector& equal = {}); + +extern template std::pair, Circuit> unique_witness( + CircuitSchema& circuit_info, Solver* s, const std::vector& equal = {}); }; // namespace smt_circuit diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit_schema.cpp b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit_schema.cpp new file mode 100644 index 00000000000..919ebd3b4c3 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit_schema.cpp @@ -0,0 +1,100 @@ +#include "circuit_schema.hpp" + +namespace smt_circuit_schema { + +/** + * @brief Get the CircuitSchema object + * @details Initialize the CircuitSchema from the binary file + * that contains an msgpack compatible buffer. + * + * @param filename + * @return CircuitSchema + */ +CircuitSchema unpack_from_file(const std::string& filename) +{ + std::ifstream fin; + fin.open(filename, std::ios::ate | std::ios::binary); + if (!fin.is_open()) { + throw std::invalid_argument("file not found"); + } + if (fin.tellg() == -1) { + throw std::invalid_argument("something went wrong"); + } + + uint64_t fsize = static_cast(fin.tellg()); + fin.seekg(0, std::ios_base::beg); + + CircuitSchema cir; + char* encoded_data = new char[fsize]; + fin.read(encoded_data, static_cast(fsize)); + msgpack::unpack(encoded_data, fsize).get().convert(cir); + return cir; +} + +/** + * @brief Translates the schema to python format + * @details Returns the contents of the .py file + * that can be further imported by python script + * + * @example output.py + * variables = ["zero", "one", "my_input1", "var3", ..., "var_n"] - variable names + * public = [[0, 0x000...0], [1, 0x000...1], [2, 0x000..abcd]] - (index, value) + * gates = [ + * [[0x000...0, 0x000...1, 0x000...0, 0x000...0, 0x000...0], [0, 0, 0]], ... + * ] + */ +void print_schema_for_use_in_python(CircuitSchema& cir) +{ + info("variable_names = ["); + for (uint32_t i = 0; i < static_cast(cir.variables.size()); i++) { + if (cir.vars_of_interest.contains(i)) { + info('"', cir.vars_of_interest[i], "\","); + } else { + info("\"v", i, "\","); + } + } + info("]"); + info("public = ["); + for (auto i : cir.public_inps) { + info("[", i, ", ", cir.variables[i], "],"); + } + info("]"); + info("gates = ["); + + for (size_t i = 0; i < cir.selectors.size(); i++) { + info("[", + "[", + cir.selectors[i][0], + ", ", + cir.selectors[i][1], + ", ", + cir.selectors[i][2], + ", ", + cir.selectors[i][3], + ", ", + cir.selectors[i][4], + "], [", + cir.wires[i][0], + ", ", + cir.wires[i][1], + ", ", + cir.wires[i][2], + "]],"); + } + info("]"); +} + +/** + * @brief Get the CircuitSchema object + * @details Initialize the CircuitSchema from the msgpack compatible buffer. + * + * @param buf + * @return CircuitSchema + */ +CircuitSchema unpack_from_buffer(const msgpack::sbuffer& buf) +{ + CircuitSchema cir; + msgpack::unpack(buf.data(), buf.size()).get().convert(cir); + return cir; +} +} // namespace smt_circuit_schema \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit_schema.hpp b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit_schema.hpp new file mode 100644 index 00000000000..930ff36eaff --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit_schema.hpp @@ -0,0 +1,39 @@ +#pragma once +#include + +#include "barretenberg/serialize/cbind.hpp" +#include "barretenberg/serialize/msgpack.hpp" + +namespace smt_circuit_schema { + +/** + * @brief Serialized state of a circuit + * + * @details Used to transfer the state of the circuit + * to Symbolic Circuit class. + * Symbolic circuit is then used to produce SMT statements + * that describe needed properties of the circuit. + * + * @param modulus Modulus of the field we are working with + * @param public_inps Public inputs to the current circuit + * @param vars_of_interes Map wires indicies to their given names + * @param variables List of wires values in the current circuit + * @param selectors List of selectors in the current circuit + * @param wires List of wires indicies for each selector + * @param real_variable_index Encoded copy constraints + */ +struct CircuitSchema { + std::string modulus; + std::vector public_inps; + std::unordered_map vars_of_interest; + std::vector variables; + std::vector> selectors; + std::vector> wires; + std::vector real_variable_index; + MSGPACK_FIELDS(modulus, public_inps, vars_of_interest, variables, selectors, wires, real_variable_index); +}; + +CircuitSchema unpack_from_buffer(const msgpack::sbuffer& buf); +CircuitSchema unpack_from_file(const std::string& filename); +void print_schema_for_use_in_python(CircuitSchema& cir); +} // namespace smt_circuit_schema \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/subcircuits.cpp b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/subcircuits.cpp new file mode 100644 index 00000000000..2870a623a53 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/subcircuits.cpp @@ -0,0 +1,24 @@ +#include "subcircuits.hpp" + +namespace smt_subcircuits { + +CircuitSchema get_standard_range_constraint_circuit(size_t n) +{ + bb::StandardCircuitBuilder builder = bb::StandardCircuitBuilder(); + uint32_t a_idx = builder.add_variable(bb::fr::random_element()); + builder.set_variable_name(a_idx, "a"); + builder.create_range_constraint(a_idx, n); + return unpack_from_buffer(builder.export_circuit()); +} + +CircuitSchema get_standard_logic_circuit(size_t n, bool is_xor) +{ + bb::StandardCircuitBuilder builder = bb::StandardCircuitBuilder(); + uint32_t a_idx = builder.add_variable(bb::fr::random_element()); + uint32_t b_idx = builder.add_variable(bb::fr::random_element()); + builder.set_variable_name(a_idx, "a"); + builder.set_variable_name(b_idx, "b"); + builder.create_logic_constraint(a_idx, b_idx, n, is_xor); + return unpack_from_buffer(builder.export_circuit()); +} +} // namespace smt_subcircuits \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/subcircuits.hpp b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/subcircuits.hpp new file mode 100644 index 00000000000..4e49113887a --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/subcircuits.hpp @@ -0,0 +1,11 @@ +#pragma once +#include "barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp" + +#include "barretenberg/smt_verification/circuit/circuit_schema.hpp" + +namespace smt_subcircuits { +using namespace smt_circuit_schema; + +CircuitSchema get_standard_range_constraint_circuit(size_t n); +CircuitSchema get_standard_logic_circuit(size_t n, bool is_xor); +} // namespace smt_subcircuits \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/smt_bigfield.test.cpp b/barretenberg/cpp/src/barretenberg/smt_verification/smt_bigfield.test.cpp index 330340e3505..1578c2474b1 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/smt_bigfield.test.cpp +++ b/barretenberg/cpp/src/barretenberg/smt_verification/smt_bigfield.test.cpp @@ -208,10 +208,10 @@ TEST(bigfield, unique_square) Solver s(circuit_info.modulus); std::pair, Circuit> cs = - unique_witness(circuit_info, - &s, - { "a_limb_0", "a_limb_1", "a_limb_2", "a_limb_3" }, - { "c_limb_0", "c_limb_1", "c_limb_2", "c_limb_3" }); + unique_witness_ext(circuit_info, + &s, + { "a_limb_0", "a_limb_1", "a_limb_2", "a_limb_3" }, + { "c_limb_0", "c_limb_1", "c_limb_2", "c_limb_3" }); auto start = std::chrono::high_resolution_clock::now(); bool res = s.check(); diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/smt_examples.test.cpp b/barretenberg/cpp/src/barretenberg/smt_verification/smt_examples.test.cpp index e62f94195e1..b8a28418023 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/smt_examples.test.cpp +++ b/barretenberg/cpp/src/barretenberg/smt_verification/smt_examples.test.cpp @@ -143,7 +143,7 @@ TEST(circuit_verifiaction, unique_witness) smt_solver::Solver s(circuit_info.modulus); std::pair, smt_circuit::Circuit> cirs = - smt_circuit::unique_witness(circuit_info, &s, { "ev" }, { "z" }); + smt_circuit::unique_witness_ext(circuit_info, &s, { "ev" }, { "z" }); bool res = s.check(); ASSERT_TRUE(res); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/protogalaxy_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/protogalaxy_recursive_verifier.cpp index b460fe76b5b..2eb8fd4f209 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/protogalaxy_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/protogalaxy_recursive_verifier.cpp @@ -9,13 +9,17 @@ void ProtoGalaxyRecursiveVerifier_::receive_and_finalise_inst const std::shared_ptr& inst, const std::string& domain_separator) { // Get circuit parameters and the public inputs - const auto instance_size = transcript->template receive_from_prover(domain_separator + "_instance_size"); + const auto instance_size = transcript->template receive_from_prover(domain_separator + "_circuit_size"); const auto public_input_size = transcript->template receive_from_prover(domain_separator + "_public_input_size"); inst->verification_key->circuit_size = uint32_t(instance_size.get_value()); inst->verification_key->log_circuit_size = static_cast(numeric::get_msb(inst->verification_key->circuit_size)); inst->verification_key->num_public_inputs = uint32_t(public_input_size.get_value()); + const auto pub_inputs_offset = + transcript->template receive_from_prover(domain_separator + "_pub_inputs_offset"); + inst->verification_key->pub_inputs_offset = uint32_t(pub_inputs_offset.get_value()); + inst->verification_key->public_inputs.clear(); for (size_t i = 0; i < inst->verification_key->num_public_inputs; ++i) { auto public_input_i = @@ -23,11 +27,6 @@ void ProtoGalaxyRecursiveVerifier_::receive_and_finalise_inst inst->verification_key->public_inputs.emplace_back(public_input_i); } - const auto pub_inputs_offset = - transcript->template receive_from_prover(domain_separator + "_pub_inputs_offset"); - - inst->verification_key->pub_inputs_offset = uint32_t(pub_inputs_offset.get_value()); - // Get commitments to first three wire polynomials auto labels = inst->commitment_labels; auto& witness_commitments = inst->witness_commitments; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index 8f308808749..2a3441812d5 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -106,6 +106,8 @@ template class SumcheckProverRound { const bb::PowPolynomial& pow_polynomial, const RelationSeparator alpha) { + BB_OP_COUNT_TIME(); + // Compute the constant contribution of pow polynomials for each edge. This is the product of the partial // evaluation result c_l (i.e. pow(u_0,...,u_{l-1})) where u_0,...,u_{l-1} are the verifier challenges from // previous rounds) and the elements of pow(\vec{β}) not containing β_0,..., β_l. diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp new file mode 100644 index 00000000000..bfb1d0ad97f --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp @@ -0,0 +1,133 @@ +#include "barretenberg/ultra_honk/oink_prover.hpp" + +namespace bb { + +/** + * @brief Add circuit size, public input size, and public inputs to transcript + * + */ +template void OinkProver::execute_preamble_round() +{ + const auto circuit_size = static_cast(instance->proving_key->circuit_size); + const auto num_public_inputs = static_cast(instance->proving_key->num_public_inputs); + transcript->send_to_verifier(domain_separator + "circuit_size", circuit_size); + transcript->send_to_verifier(domain_separator + "public_input_size", num_public_inputs); + transcript->send_to_verifier(domain_separator + "pub_inputs_offset", + static_cast(instance->proving_key->pub_inputs_offset)); + + ASSERT(instance->proving_key->num_public_inputs == instance->proving_key->public_inputs.size()); + + for (size_t i = 0; i < instance->proving_key->num_public_inputs; ++i) { + auto public_input_i = instance->proving_key->public_inputs[i]; + transcript->send_to_verifier(domain_separator + "public_input_" + std::to_string(i), public_input_i); + } +} + +/** + * @brief Commit to the wire polynomials (part of the witness), with the exception of the fourth wire, which is + * only commited to after adding memory records. In the Goblin Flavor, we also commit to the ECC OP wires and the + * DataBus columns. + */ +template void OinkProver::execute_wire_commitments_round() +{ + auto& witness_commitments = instance->witness_commitments; + + // Commit to the first three wire polynomials of the instance + // We only commit to the fourth wire polynomial after adding memory recordss + witness_commitments.w_l = commitment_key->commit(instance->proving_key->w_l); + witness_commitments.w_r = commitment_key->commit(instance->proving_key->w_r); + witness_commitments.w_o = commitment_key->commit(instance->proving_key->w_o); + + auto wire_comms = witness_commitments.get_wires(); + auto& commitment_labels = instance->commitment_labels; + auto wire_labels = commitment_labels.get_wires(); + for (size_t idx = 0; idx < 3; ++idx) { + transcript->send_to_verifier(domain_separator + wire_labels[idx], wire_comms[idx]); + } + + if constexpr (IsGoblinFlavor) { + // Commit to Goblin ECC op wires + witness_commitments.ecc_op_wire_1 = commitment_key->commit(instance->proving_key->ecc_op_wire_1); + witness_commitments.ecc_op_wire_2 = commitment_key->commit(instance->proving_key->ecc_op_wire_2); + witness_commitments.ecc_op_wire_3 = commitment_key->commit(instance->proving_key->ecc_op_wire_3); + witness_commitments.ecc_op_wire_4 = commitment_key->commit(instance->proving_key->ecc_op_wire_4); + + auto op_wire_comms = witness_commitments.get_ecc_op_wires(); + auto labels = commitment_labels.get_ecc_op_wires(); + for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { + transcript->send_to_verifier(domain_separator + labels[idx], op_wire_comms[idx]); + } + // Commit to DataBus columns + witness_commitments.calldata = commitment_key->commit(instance->proving_key->calldata); + witness_commitments.calldata_read_counts = commitment_key->commit(instance->proving_key->calldata_read_counts); + transcript->send_to_verifier(domain_separator + commitment_labels.calldata, witness_commitments.calldata); + transcript->send_to_verifier(domain_separator + commitment_labels.calldata_read_counts, + witness_commitments.calldata_read_counts); + } +} + +/** + * @brief Compute sorted witness-table accumulator and commit to the resulting polynomials. + * + */ +template void OinkProver::execute_sorted_list_accumulator_round() +{ + auto& witness_commitments = instance->witness_commitments; + const auto& commitment_labels = instance->commitment_labels; + + auto eta = transcript->template get_challenge(domain_separator + "eta"); + instance->compute_sorted_accumulator_polynomials(eta); + + // Commit to the sorted witness-table accumulator and the finalized (i.e. with memory records) fourth wire + // polynomial + witness_commitments.sorted_accum = commitment_key->commit(instance->prover_polynomials.sorted_accum); + witness_commitments.w_4 = commitment_key->commit(instance->prover_polynomials.w_4); + + transcript->send_to_verifier(domain_separator + commitment_labels.sorted_accum, witness_commitments.sorted_accum); + transcript->send_to_verifier(domain_separator + commitment_labels.w_4, witness_commitments.w_4); +} + +/** + * @brief Compute log derivative inverse polynomial and its commitment, if required + * + */ +template void OinkProver::execute_log_derivative_inverse_round() +{ + auto& witness_commitments = instance->witness_commitments; + const auto& commitment_labels = instance->commitment_labels; + + auto [beta, gamma] = transcript->template get_challenges(domain_separator + "beta", domain_separator + "gamma"); + instance->relation_parameters.beta = beta; + instance->relation_parameters.gamma = gamma; + if constexpr (IsGoblinFlavor) { + // Compute and commit to the logderivative inverse used in DataBus + instance->compute_logderivative_inverse(beta, gamma); + witness_commitments.lookup_inverses = commitment_key->commit(instance->prover_polynomials.lookup_inverses); + transcript->send_to_verifier(domain_separator + commitment_labels.lookup_inverses, + witness_commitments.lookup_inverses); + } +} + +/** + * @brief Compute permutation and lookup grand product polynomials and their commitments + * + */ +template void OinkProver::execute_grand_product_computation_round() +{ + auto& witness_commitments = instance->witness_commitments; + const auto& commitment_labels = instance->commitment_labels; + + instance->compute_grand_product_polynomials(instance->relation_parameters.beta, + instance->relation_parameters.gamma); + + witness_commitments.z_perm = commitment_key->commit(instance->prover_polynomials.z_perm); + witness_commitments.z_lookup = commitment_key->commit(instance->prover_polynomials.z_lookup); + + transcript->send_to_verifier(domain_separator + commitment_labels.z_perm, witness_commitments.z_perm); + transcript->send_to_verifier(domain_separator + commitment_labels.z_lookup, witness_commitments.z_lookup); +} + +template class OinkProver; +template class OinkProver; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.hpp new file mode 100644 index 00000000000..470794d8237 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.hpp @@ -0,0 +1,49 @@ +#pragma once +#include + +#include "barretenberg/flavor/goblin_ultra.hpp" +#include "barretenberg/flavor/ultra.hpp" +#include "barretenberg/sumcheck/instance/prover_instance.hpp" +#include "barretenberg/transcript/transcript.hpp" + +namespace bb { + +/** + * @brief Class for all the oink rounds, which are shared between the folding prover and ultra prover. + * @details This class contains execute_preamble_round(), execute_wire_commitments_round(), + * execute_sorted_list_accumulator_round(), execute_log_derivative_inverse_round(), and + * execute_grand_product_computation_round(). + * + * @tparam Flavor + */ +template class OinkProver { + using CommitmentKey = typename Flavor::CommitmentKey; + using Instance = ProverInstance_; + using Transcript = typename Flavor::Transcript; + using FF = typename Flavor::FF; + + public: + std::shared_ptr instance; + std::shared_ptr transcript; + std::shared_ptr commitment_key; + std::string domain_separator; + + OinkProver(const std::shared_ptr>& inst, + const std::shared_ptr& commitment_key, + const std::shared_ptr& transcript, + std::string domain_separator = "") + : instance(inst) + , transcript(transcript) + , commitment_key(commitment_key) + , domain_separator(std::move(domain_separator)) + { + instance->initialize_prover_polynomials(); + } + + void execute_preamble_round(); + void execute_wire_commitments_round(); + void execute_sorted_list_accumulator_round(); + void execute_log_derivative_inverse_round(); + void execute_grand_product_computation_round(); +}; +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp index f6d800558b5..fe78a0d7d88 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp @@ -15,9 +15,8 @@ UltraProver_::UltraProver_(const std::shared_ptr& inst, const : instance(std::move(inst)) , transcript(transcript) , commitment_key(instance->proving_key->commitment_key) -{ - instance->initialize_prover_polynomials(); -} + , oink_prover(inst, commitment_key, transcript, "") +{} /** * Create UltraProver_ from a circuit. @@ -31,130 +30,8 @@ UltraProver_::UltraProver_(Builder& circuit) : instance(std::make_shared(circuit)) , transcript(std::make_shared()) , commitment_key(instance->proving_key->commitment_key) -{ - instance->initialize_prover_polynomials(); -} - -/** - * @brief Add circuit size, public input size, and public inputs to transcript - * - */ -template void UltraProver_::execute_preamble_round() -{ - auto proving_key = instance->proving_key; - const auto circuit_size = static_cast(proving_key->circuit_size); - const auto num_public_inputs = static_cast(proving_key->num_public_inputs); - - transcript->send_to_verifier("circuit_size", circuit_size); - transcript->send_to_verifier("public_input_size", num_public_inputs); - transcript->send_to_verifier("pub_inputs_offset", static_cast(proving_key->pub_inputs_offset)); - - for (size_t i = 0; i < proving_key->num_public_inputs; ++i) { - auto public_input_i = proving_key->public_inputs[i]; - transcript->send_to_verifier("public_input_" + std::to_string(i), public_input_i); - } -} - -/** - * @brief Commit to the wire polynomials (part of the witness), with the exception of the fourth wire, which is - * only commited to after adding memory records. In the Goblin Flavor, we also commit to the ECC OP wires and the - * DataBus columns. - */ -template void UltraProver_::execute_wire_commitments_round() -{ - auto& witness_commitments = instance->witness_commitments; - auto& proving_key = instance->proving_key; - - // Commit to the first three wire polynomials - // We only commit to the fourth wire polynomial after adding memory recordss - witness_commitments.w_l = commitment_key->commit(proving_key->w_l); - witness_commitments.w_r = commitment_key->commit(proving_key->w_r); - witness_commitments.w_o = commitment_key->commit(proving_key->w_o); - - auto wire_comms = witness_commitments.get_wires(); - auto labels = commitment_labels.get_wires(); - for (size_t idx = 0; idx < 3; ++idx) { - transcript->send_to_verifier(labels[idx], wire_comms[idx]); - } - - if constexpr (IsGoblinFlavor) { - // Commit to Goblin ECC op wires - witness_commitments.ecc_op_wire_1 = commitment_key->commit(proving_key->ecc_op_wire_1); - witness_commitments.ecc_op_wire_2 = commitment_key->commit(proving_key->ecc_op_wire_2); - witness_commitments.ecc_op_wire_3 = commitment_key->commit(proving_key->ecc_op_wire_3); - witness_commitments.ecc_op_wire_4 = commitment_key->commit(proving_key->ecc_op_wire_4); - - auto op_wire_comms = instance->witness_commitments.get_ecc_op_wires(); - auto labels = commitment_labels.get_ecc_op_wires(); - for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { - transcript->send_to_verifier(labels[idx], op_wire_comms[idx]); - } - - // Commit to DataBus columns - witness_commitments.calldata = commitment_key->commit(proving_key->calldata); - witness_commitments.calldata_read_counts = commitment_key->commit(proving_key->calldata_read_counts); - transcript->send_to_verifier(commitment_labels.calldata, instance->witness_commitments.calldata); - transcript->send_to_verifier(commitment_labels.calldata_read_counts, - instance->witness_commitments.calldata_read_counts); - } -} - -/** - * @brief Compute sorted witness-table accumulator and commit to the resulting polynomials. - * - */ -template void UltraProver_::execute_sorted_list_accumulator_round() -{ - FF eta = transcript->template get_challenge("eta"); - - instance->compute_sorted_accumulator_polynomials(eta); - - auto& witness_commitments = instance->witness_commitments; - // Commit to the sorted witness-table accumulator and the finalized (i.e. with memory records) fourth wire - // polynomial - witness_commitments.sorted_accum = commitment_key->commit(instance->prover_polynomials.sorted_accum); - witness_commitments.w_4 = commitment_key->commit(instance->prover_polynomials.w_4); - - transcript->send_to_verifier(commitment_labels.sorted_accum, instance->witness_commitments.sorted_accum); - transcript->send_to_verifier(commitment_labels.w_4, instance->witness_commitments.w_4); -} - -/** - * @brief Compute log derivative inverse polynomial and its commitment, if required - * - */ -template void UltraProver_::execute_log_derivative_inverse_round() -{ - auto& proving_key = instance->proving_key; - - // Compute and store challenges beta and gamma - auto [beta, gamma] = transcript->template get_challenges("beta", "gamma"); - relation_parameters.beta = beta; - relation_parameters.gamma = gamma; - - if constexpr (IsGoblinFlavor) { - instance->compute_logderivative_inverse(beta, gamma); - instance->witness_commitments.lookup_inverses = commitment_key->commit(proving_key->lookup_inverses); - transcript->send_to_verifier(commitment_labels.lookup_inverses, instance->witness_commitments.lookup_inverses); - } -} - -/** - * @brief Compute permutation and lookup grand product polynomials and their commitments - * - */ -template void UltraProver_::execute_grand_product_computation_round() -{ - auto& proving_key = instance->proving_key; - - instance->compute_grand_product_polynomials(relation_parameters.beta, relation_parameters.gamma); - - auto& witness_commitments = instance->witness_commitments; - witness_commitments.z_perm = commitment_key->commit(proving_key->z_perm); - witness_commitments.z_lookup = commitment_key->commit(proving_key->z_lookup); - transcript->send_to_verifier(commitment_labels.z_perm, instance->witness_commitments.z_perm); - transcript->send_to_verifier(commitment_labels.z_lookup, instance->witness_commitments.z_lookup); -} + , oink_prover(instance, commitment_key, transcript, "") +{} /** * @brief Run Sumcheck resulting in u = (u_1,...,u_d) challenges and all evaluations at u being calculated. @@ -203,19 +80,19 @@ template HonkProof& UltraProver_::export_proof() template HonkProof& UltraProver_::construct_proof() { // Add circuit size public input size and public inputs to transcript-> - execute_preamble_round(); + oink_prover.execute_preamble_round(); // Compute first three wire commitments - execute_wire_commitments_round(); + oink_prover.execute_wire_commitments_round(); // Compute sorted list accumulator and commitment - execute_sorted_list_accumulator_round(); + oink_prover.execute_sorted_list_accumulator_round(); // Fiat-Shamir: beta & gamma - execute_log_derivative_inverse_round(); + oink_prover.execute_log_derivative_inverse_round(); // Compute grand product(s) and commitments. - execute_grand_product_computation_round(); + oink_prover.execute_grand_product_computation_round(); // Fiat-Shamir: alpha // Run sumcheck subprotocol. diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp index dd822986f11..46aa631f6cb 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp @@ -7,6 +7,7 @@ #include "barretenberg/sumcheck/instance/prover_instance.hpp" #include "barretenberg/sumcheck/sumcheck_output.hpp" #include "barretenberg/transcript/transcript.hpp" +#include "barretenberg/ultra_honk/oink_prover.hpp" namespace bb { @@ -25,6 +26,21 @@ template class UltraProver_ { using Instance = ProverInstance; using Transcript = typename Flavor::Transcript; using RelationSeparator = typename Flavor::RelationSeparator; + using ZeroMorph = ZeroMorphProver_; + + std::shared_ptr instance; + + std::shared_ptr transcript; + + bb::RelationParameters relation_parameters; + + Polynomial quotient_W; + + SumcheckOutput sumcheck_output; + + std::shared_ptr commitment_key; + + OinkProver oink_prover; explicit UltraProver_(const std::shared_ptr&, const std::shared_ptr& transcript = std::make_shared()); @@ -42,22 +58,6 @@ template class UltraProver_ { HonkProof& export_proof(); HonkProof& construct_proof(); - std::shared_ptr instance; - - std::shared_ptr transcript; - - bb::RelationParameters relation_parameters; - - CommitmentLabels commitment_labels; - - Polynomial quotient_W; - - SumcheckOutput sumcheck_output; - - std::shared_ptr commitment_key; - - using ZeroMorph = ZeroMorphProver_; - private: HonkProof proof; }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp index a694bb7a490..60e47489a4e 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp @@ -46,14 +46,16 @@ void log_avm_trace(std::vector const& trace, size_t beg, size_t end, bool e info("alu_ic ", trace.at(i).avm_alu_alu_ic); info("=======MAIN TRACE===================================================================="); + info("clk: ", trace.at(i).avm_main_clk); info("ia: ", trace.at(i).avm_main_ia); info("ib: ", trace.at(i).avm_main_ib); info("ic: ", trace.at(i).avm_main_ic); + info("in_tag ", trace.at(i).avm_main_in_tag); + info("tag_err ", trace.at(i).avm_main_tag_err); info("first: ", trace.at(i).avm_main_first); info("last: ", trace.at(i).avm_main_last); info("=======MEM_OP_A======================================================================"); - info("clk: ", trace.at(i).avm_main_clk); info("mem_op_a: ", trace.at(i).avm_main_mem_op_a); info("mem_idx_a: ", trace.at(i).avm_main_mem_idx_a); info("rwa: ", trace.at(i).avm_main_rwa); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp index cc7012bb618..d4ec8c3ace1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -50,10 +50,12 @@ void AvmTraceBuilder::op_add(uint32_t a_offset, uint32_t b_offset, uint32_t dst_ bool tag_match = read_a.tag_match && read_b.tag_match; // a + b = c - FF a = tag_match ? read_a.val : FF(0); - FF b = tag_match ? read_b.val : FF(0); + FF a = read_a.val; + FF b = read_b.val; - // In case of a memory tag error, we must not generate an entry in the ALU table. + // In case of a memory tag error, we do not perform the computation. + // Therefore, we do not create any entry in ALU table and store the value 0 as + // output (c) in memory. FF c = tag_match ? alu_trace_builder.op_add(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. @@ -97,10 +99,12 @@ void AvmTraceBuilder::op_sub(uint32_t a_offset, uint32_t b_offset, uint32_t dst_ bool tag_match = read_a.tag_match && read_b.tag_match; // a - b = c - FF a = tag_match ? read_a.val : FF(0); - FF b = tag_match ? read_b.val : FF(0); + FF a = read_a.val; + FF b = read_b.val; - // In case of a memory tag error, we must not generate an entry in the ALU table. + // In case of a memory tag error, we do not perform the computation. + // Therefore, we do not create any entry in ALU table and store the value 0 as + // output (c) in memory. FF c = tag_match ? alu_trace_builder.op_sub(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. @@ -144,10 +148,12 @@ void AvmTraceBuilder::op_mul(uint32_t a_offset, uint32_t b_offset, uint32_t dst_ bool tag_match = read_a.tag_match && read_b.tag_match; // a * b = c - FF a = tag_match ? read_a.val : FF(0); - FF b = tag_match ? read_b.val : FF(0); + FF a = read_a.val; + FF b = read_b.val; - // In case of a memory tag error, we must not generate an entry in the ALU table. + // In case of a memory tag error, we do not perform the computation. + // Therefore, we do not create any entry in ALU table and store the value 0 as + // output (c) in memory. FF c = tag_match ? alu_trace_builder.op_mul(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. @@ -248,14 +254,15 @@ void AvmTraceBuilder::op_not(uint32_t a_offset, uint32_t dst_offset, AvmMemoryTa auto read_a = mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IA, a_offset, in_tag); // ~a = c - FF a = read_a.tag_match ? read_a.val : FF(0); + FF a = read_a.val; - // In case of a memory tag error, we must not generate an entry in the ALU table. + // In case of a memory tag error, we do not perform the computation. + // Therefore, we do not create any entry in ALU table and store the value 0 as + // output (c) in memory. FF c = read_a.tag_match ? alu_trace_builder.op_not(a, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. mem_trace_builder.write_into_memory(clk, IntermRegister::IC, dst_offset, c, in_tag); - main_trace.push_back(Row{ .avm_main_clk = clk, .avm_main_pc = FF(pc++), @@ -291,10 +298,12 @@ void AvmTraceBuilder::op_eq(uint32_t a_offset, uint32_t b_offset, uint32_t dst_o bool tag_match = read_a.tag_match && read_b.tag_match; // c = a == b ? 1 : 0 - FF a = tag_match ? read_a.val : FF(0); - FF b = tag_match ? read_b.val : FF(0); + FF a = read_a.val; + FF b = read_b.val; - // In case of a memory tag error, we must not generate an entry in the ALU table. + // In case of a memory tag error, we do not perform the computation. + // Therefore, we do not create any entry in ALU table and store the value 0 as + // output (c) in memory. FF c = tag_match ? alu_trace_builder.op_eq(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. @@ -533,9 +542,9 @@ std::vector AvmTraceBuilder::return_op(uint32_t ret_offset, uint32_t ret_siz .avm_main_sel_halt = FF(1), .avm_main_in_tag = FF(static_cast(AvmMemoryTag::FF)), .avm_main_tag_err = FF(static_cast(!tag_match)), - .avm_main_ia = tag_match ? ia : FF(0), - .avm_main_ib = tag_match ? ib : FF(0), - .avm_main_ic = tag_match ? ic : FF(0), + .avm_main_ia = ia, + .avm_main_ib = ib, + .avm_main_ic = ic, .avm_main_mem_op_a = FF(mem_op_a), .avm_main_mem_op_b = FF(mem_op_b), .avm_main_mem_op_c = FF(mem_op_c), @@ -620,15 +629,16 @@ void AvmTraceBuilder::internal_call(uint32_t jmp_dest) internal_call_stack.push(stored_pc); // Add the return location to the memory trace - mem_trace_builder.write_into_memory(clk, IntermRegister::IB, internal_return_ptr, FF(stored_pc), AvmMemoryTag::FF); + mem_trace_builder.write_into_memory(clk, IntermRegister::IB, internal_return_ptr, FF(stored_pc), AvmMemoryTag::U32); main_trace.push_back(Row{ .avm_main_clk = clk, .avm_main_pc = FF(pc), .avm_main_internal_return_ptr = FF(internal_return_ptr), .avm_main_sel_internal_call = FF(1), + .avm_main_in_tag = FF(static_cast(AvmMemoryTag::U32)), .avm_main_ia = FF(jmp_dest), - .avm_main_ib = stored_pc, + .avm_main_ib = FF(stored_pc), .avm_main_mem_op_b = FF(1), .avm_main_rwb = FF(1), .avm_main_mem_idx_b = FF(internal_return_ptr), @@ -655,16 +665,17 @@ void AvmTraceBuilder::internal_return() // Internal return pointer is decremented // We want to load the value pointed by the internal pointer - auto read_a = - mem_trace_builder.read_and_load_from_memory(clk, IntermRegister::IA, internal_return_ptr - 1, AvmMemoryTag::FF); + auto read_a = mem_trace_builder.read_and_load_from_memory( + clk, IntermRegister::IA, internal_return_ptr - 1, AvmMemoryTag::U32); main_trace.push_back(Row{ .avm_main_clk = clk, .avm_main_pc = pc, .avm_main_internal_return_ptr = FF(internal_return_ptr), .avm_main_sel_internal_return = FF(1), + .avm_main_in_tag = FF(static_cast(AvmMemoryTag::U32)), .avm_main_tag_err = FF(static_cast(!read_a.tag_match)), - .avm_main_ia = read_a.tag_match ? read_a.val : FF(0), + .avm_main_ia = read_a.val, .avm_main_mem_op_a = FF(1), .avm_main_rwa = FF(0), .avm_main_mem_idx_a = FF(internal_return_ptr - 1), @@ -687,7 +698,7 @@ void AvmTraceBuilder::internal_return() void AvmTraceBuilder::finalise_mem_trace_lookup_counts(std::map const& tag_err_lookup_counts) { for (auto const& [clk, count] : tag_err_lookup_counts) { - main_trace.at(clk).equiv_tag_err_counts = count; + main_trace.at(clk).incl_main_tag_err_counts = count; } } @@ -740,6 +751,17 @@ std::vector AvmTraceBuilder::finalize() dest.avm_mem_m_tag_err = FF(static_cast(src.m_tag_err)); dest.avm_mem_m_one_min_inv = src.m_one_min_inv; + if (src.m_sub_clk == AvmMemTraceBuilder::SUB_CLK_LOAD_A || + src.m_sub_clk == AvmMemTraceBuilder::SUB_CLK_STORE_A) { + dest.avm_mem_m_op_a = FF(1); + } else if (src.m_sub_clk == AvmMemTraceBuilder::SUB_CLK_LOAD_B || + src.m_sub_clk == AvmMemTraceBuilder::SUB_CLK_STORE_B) { + dest.avm_mem_m_op_b = FF(1); + } else if (src.m_sub_clk == AvmMemTraceBuilder::SUB_CLK_LOAD_C || + src.m_sub_clk == AvmMemTraceBuilder::SUB_CLK_STORE_C) { + dest.avm_mem_m_op_c = FF(1); + } + if (i + 1 < mem_trace_size) { auto const& next = mem_trace.at(i + 1); dest.avm_mem_m_lastAccess = FF(static_cast(src.m_addr != next.m_addr)); @@ -802,6 +824,7 @@ std::vector AvmTraceBuilder::finalize() } } + // Deriving redundant selectors/tags for the main trace. for (Row& r : main_trace) { if ((r.avm_main_sel_op_add == FF(1) || r.avm_main_sel_op_sub == FF(1) || r.avm_main_sel_op_mul == FF(1) || r.avm_main_sel_op_eq == FF(1) || r.avm_main_sel_op_not == FF(1)) && diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index a5f95192e4e..0ee66fee2ad 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -63,6 +63,9 @@ bool AvmVerifier::verify_proof(const HonkProof& proof) commitments.avm_mem_m_rw = transcript->template receive_from_prover(commitment_labels.avm_mem_m_rw); commitments.avm_mem_m_in_tag = transcript->template receive_from_prover(commitment_labels.avm_mem_m_in_tag); + commitments.avm_mem_m_op_a = transcript->template receive_from_prover(commitment_labels.avm_mem_m_op_a); + commitments.avm_mem_m_op_b = transcript->template receive_from_prover(commitment_labels.avm_mem_m_op_b); + commitments.avm_mem_m_op_c = transcript->template receive_from_prover(commitment_labels.avm_mem_m_op_c); commitments.avm_mem_m_tag_err = transcript->template receive_from_prover(commitment_labels.avm_mem_m_tag_err); commitments.avm_mem_m_one_min_inv = @@ -176,11 +179,17 @@ bool AvmVerifier::verify_proof(const HonkProof& proof) commitments.avm_main_mem_idx_c = transcript->template receive_from_prover(commitment_labels.avm_main_mem_idx_c); commitments.avm_main_last = transcript->template receive_from_prover(commitment_labels.avm_main_last); - commitments.equiv_inter_reg_alu = - transcript->template receive_from_prover(commitment_labels.equiv_inter_reg_alu); - commitments.equiv_tag_err = transcript->template receive_from_prover(commitment_labels.equiv_tag_err); - commitments.equiv_tag_err_counts = - transcript->template receive_from_prover(commitment_labels.equiv_tag_err_counts); + commitments.perm_main_alu = transcript->template receive_from_prover(commitment_labels.perm_main_alu); + commitments.perm_main_mem_a = + transcript->template receive_from_prover(commitment_labels.perm_main_mem_a); + commitments.perm_main_mem_b = + transcript->template receive_from_prover(commitment_labels.perm_main_mem_b); + commitments.perm_main_mem_c = + transcript->template receive_from_prover(commitment_labels.perm_main_mem_c); + commitments.incl_main_tag_err = + transcript->template receive_from_prover(commitment_labels.incl_main_tag_err); + commitments.incl_main_tag_err_counts = + transcript->template receive_from_prover(commitment_labels.incl_main_tag_err_counts); // Execute Sumcheck Verifier const size_t log_circuit_size = numeric::get_msb(circuit_size); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp index 5f9f206f31f..d71343f2c97 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp @@ -1,12 +1,10 @@ #include "avm_common.test.hpp" - #include "barretenberg/numeric/uint128/uint128.hpp" -#include "barretenberg/vm/avm_trace/avm_helper.hpp" -using namespace bb; -using namespace bb::numeric; +namespace tests_avm { +using namespace bb::avm_trace; + namespace { -using namespace tests_avm; void common_validate_arithmetic_op(Row const& main_row, Row const& alu_row, @@ -246,9 +244,6 @@ std::vector gen_mutated_trace_eq( } } // anonymous namespace -namespace tests_avm { -using namespace bb::avm_trace; - class AvmArithmeticTests : public ::testing::Test { public: AvmTraceBuilder trace_builder; diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp index d4b2860e2d3..7fae3fa13cb 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp @@ -1,15 +1,13 @@ #include "avm_common.test.hpp" - #include "barretenberg/numeric/uint128/uint128.hpp" #include #include #include -using namespace bb; -using namespace bb::numeric; +namespace tests_avm { +using namespace bb::avm_trace; namespace { -using namespace tests_avm; Row common_validate_op_not(std::vector const& trace, FF const& a, @@ -72,9 +70,6 @@ std::vector gen_mutated_trace_not(FF const& a, FF const& c_mutated, avm_tra } } // namespace -namespace tests_avm { -using namespace bb::avm_trace; - class AvmBitwiseTests : public ::testing::Test { public: AvmTraceBuilder trace_builder; diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp index ed1c81377ab..8ac2da28f08 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp @@ -1,7 +1,5 @@ #include "avm_common.test.hpp" -using namespace bb; - namespace tests_avm { using namespace bb::avm_trace; diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp index 1e9028c6fcb..ecf10ed57e0 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp @@ -3,18 +3,15 @@ #include "barretenberg/common/utils.hpp" #include "barretenberg/vm/avm_trace/avm_common.hpp" #include "barretenberg/vm/avm_trace/avm_deserialization.hpp" -#include "barretenberg/vm/avm_trace/avm_helper.hpp" #include "barretenberg/vm/avm_trace/avm_opcode.hpp" -#include "barretenberg/vm/tests/helpers.test.hpp" -#include "gmock/gmock.h" #include +#include #include #include #include namespace tests_avm { -using namespace bb; using namespace bb::avm_trace; using namespace testing; diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_inter_table.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_inter_table.test.cpp new file mode 100644 index 00000000000..9940e88eca0 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_inter_table.test.cpp @@ -0,0 +1,384 @@ +#include "avm_common.test.hpp" +#include "barretenberg/vm/avm_trace/avm_common.hpp" +#include "barretenberg/vm/avm_trace/avm_mem_trace.hpp" +#include "barretenberg/vm/tests/helpers.test.hpp" +#include +#include +#include + +using namespace bb; + +namespace tests_avm { +using namespace bb::avm_trace; + +class AvmInterTableTests : public ::testing::Test { + public: + AvmTraceBuilder trace_builder; + + protected: + // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. + void SetUp() override { srs::init_crs_factory("../srs_db/ignition"); }; +}; + +/****************************************************************************** + * + * INTER-TABLE NEGATIVE TESTS + * + ****************************************************************************** + * These negative unit tests aim to catch violations related to inter-table + * relations. Inter-table relations are implemented through permutation and + * lookup relations. Each permutation and lookup relation defined in the AVM + * has to be negatively tested in the current test suite. + * The built trace in each test needs to be as correct as possible except the + * relation being tested. + ******************************************************************************/ + +// Error tag propagation from memory trace back to the main trace. +TEST_F(AvmInterTableTests, tagErrNotCopiedInMain) +{ + // Equality operation on U128 and second operand is of type U16. + trace_builder.set(32, 18, AvmMemoryTag::U128); + trace_builder.set(32, 76, AvmMemoryTag::U16); + trace_builder.op_eq(18, 76, 65, AvmMemoryTag::U128); + trace_builder.halt(); + auto trace = trace_builder.finalize(); + + // Find the row with equality operation and mutate the error tag. + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_eq == 1; }); + ASSERT_EQ(row->avm_main_tag_err, FF(1)); // Sanity check that the error tag is set. + row->avm_main_tag_err = 0; + row->avm_main_alu_sel = 1; // We have to activate ALU trace if no error tag is present. + auto const clk = row->avm_main_clk; + + // Create a valid ALU entry for this equality operation. + auto& alu_row = trace.at(1); + alu_row.avm_alu_alu_clk = clk; + alu_row.avm_alu_alu_sel = 1; + alu_row.avm_alu_alu_ia = 32; + alu_row.avm_alu_alu_ib = 32; + alu_row.avm_alu_alu_ic = 1; + alu_row.avm_alu_alu_op_eq = 1; + alu_row.avm_alu_alu_in_tag = static_cast(AvmMemoryTag::U128); + alu_row.avm_alu_alu_u128_tag = 1; + + // Adjust the output of the computation as it would have been performed without tag check. + row->avm_main_ic = 1; + // Find the memory row pertaining to write operation from Ic. + auto mem_row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { + return r.avm_mem_m_clk == clk && r.avm_mem_m_sub_clk == AvmMemTraceBuilder::SUB_CLK_STORE_C; + }); + + // Adjust the output in the memory trace. + mem_row->avm_mem_m_val = 1; + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "INCL_MAIN_TAG_ERR"); +} + +/****************************************************************************** + * MAIN <-------> ALU + ******************************************************************************/ +class AvmPermMainAluNegativeTests : public AvmInterTableTests { + protected: + std::vector trace; + size_t main_idx; + size_t mem_idx; + size_t alu_idx; + + void SetUp() override + { + AvmInterTableTests::SetUp(); + + trace_builder.set(19, 0, AvmMemoryTag::U64); + trace_builder.set(15, 1, AvmMemoryTag::U64); + trace_builder.op_add(0, 1, 1, AvmMemoryTag::U64); // 19 + 15 = 34 + trace_builder.op_add(0, 1, 1, AvmMemoryTag::U64); // 19 + 34 = 53 + trace_builder.op_mul(0, 1, 2, AvmMemoryTag::U64); // 19 * 53 = 1007 + trace_builder.return_op(0, 0); + + trace = trace_builder.finalize(); + + // Find the row with multiplication operation and retrieve clk. + auto row = + std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_mul == FF(1); }); + + ASSERT_TRUE(row != trace.end()); + ASSERT_EQ(row->avm_main_ic, 1007); // Sanity check + auto clk = row->avm_main_clk; + + // Find the corresponding Alu trace row + auto alu_row = + std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.avm_alu_alu_clk == clk; }); + ASSERT_TRUE(alu_row != trace.end()); + + // Find memory trace entry related to storing output (intermediate register Ic) in memory. + auto mem_row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { + return r.avm_mem_m_clk == clk && r.avm_mem_m_op_c == FF(1) && r.avm_mem_m_rw == FF(1); + }); + ASSERT_TRUE(mem_row != trace.end()); + + main_idx = static_cast(row - trace.begin()); + alu_idx = static_cast(alu_row - trace.begin()); + mem_idx = static_cast(mem_row - trace.begin()); + } +}; + +TEST_F(AvmPermMainAluNegativeTests, wrongAluOutputCopyInMain) +{ + // Mutate the multiplication output. Note that the output alu counterpart is still valid + // and pass the multiplication relation. + trace.at(main_idx).avm_main_ic = 1008; + trace.at(mem_idx).avm_mem_m_val = 1008; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_ALU"); +} + +TEST_F(AvmPermMainAluNegativeTests, wrongCopyToAluIaInput) +{ + // Mutate the input of alu_ia and adapt the output ic accordingly. + trace.at(alu_idx).avm_alu_alu_ia = 20; + trace.at(alu_idx).avm_alu_alu_ic = 1060; // 20 * 53; required to pass the alu mul relation + trace.at(alu_idx).avm_alu_alu_u8_r0 = 36; // 1060 % 256 = 36 + trace.at(alu_idx).avm_alu_alu_u8_r1 = 4; // 4 * 256 = 1024 + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_ALU"); +} + +TEST_F(AvmPermMainAluNegativeTests, wrongCopyToAluIbInput) +{ + // Mutate the input of alu_ia and adapt the output ic accordingly. + trace.at(alu_idx).avm_alu_alu_ib = 10; + trace.at(alu_idx).avm_alu_alu_ic = 190; // 19 * 10; required to pass the alu mul relation + trace.at(alu_idx).avm_alu_alu_u8_r0 = 190; + trace.at(alu_idx).avm_alu_alu_u8_r1 = 0; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_ALU"); +} + +TEST_F(AvmPermMainAluNegativeTests, wrongCopyToAluOpSelector) +{ + trace.at(alu_idx).avm_alu_alu_op_mul = 0; + trace.at(alu_idx).avm_alu_alu_op_add = 1; + trace.at(alu_idx).avm_alu_alu_ic = 72; // 19 + 53 + trace.at(alu_idx).avm_alu_alu_u8_r0 = 72; + trace.at(alu_idx).avm_alu_alu_u8_r1 = 0; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_ALU"); +} + +TEST_F(AvmPermMainAluNegativeTests, removeAluSelector) +{ + trace.at(alu_idx).avm_alu_alu_sel = 0; + trace.at(alu_idx).avm_alu_alu_op_mul = 0; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_ALU"); +} + +/****************************************************************************** + * MAIN <-------> ALU + ******************************************************************************/ +class AvmPermMainMemNegativeTests : public AvmInterTableTests { + protected: + std::vector trace; + size_t main_idx; + size_t mem_idx_a; + size_t mem_idx_b; + size_t mem_idx_c; + size_t alu_idx; + + // Helper function to generate a trace with a subtraction + // for c = a - b at arbitray chosen addresses 52 (a), 11 (b), 55 (c). + void executeSub(uint128_t const a, uint128_t const b) + { + trace_builder.set(a, 52, AvmMemoryTag::U8); + trace_builder.set(b, 11, AvmMemoryTag::U8); + trace_builder.op_sub(52, 11, 55, AvmMemoryTag::U8); + trace_builder.return_op(0, 0); + + trace = trace_builder.finalize(); + + // Find the row with subtraction operation and retrieve clk. + auto row = + std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.avm_main_sel_op_sub == FF(1); }); + + ASSERT_TRUE(row != trace.end()); + auto clk = row->avm_main_clk; + + // Find the corresponding Alu trace row + auto alu_row = + std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { return r.avm_alu_alu_clk == clk; }); + ASSERT_TRUE(alu_row != trace.end()); + + // Find memory trace entry related to storing output (intermediate register Ic) in memory. + auto mem_row_c = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { + return r.avm_mem_m_clk == clk && r.avm_mem_m_op_c == FF(1) && r.avm_mem_m_rw == FF(1); + }); + ASSERT_TRUE(mem_row_c != trace.end()); + + // Find memory trace entry related to loading first input (intermediate register Ia) in memory. + auto mem_row_a = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { + return r.avm_mem_m_clk == clk && r.avm_mem_m_op_a == FF(1) && r.avm_mem_m_rw == FF(0); + }); + ASSERT_TRUE(mem_row_a != trace.end()); + + // Find memory trace entry related to loading second input (intermediate register Ib) in memory. + auto mem_row_b = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { + return r.avm_mem_m_clk == clk && r.avm_mem_m_op_b == FF(1) && r.avm_mem_m_rw == FF(0); + }); + ASSERT_TRUE(mem_row_b != trace.end()); + + main_idx = static_cast(row - trace.begin()); + alu_idx = static_cast(alu_row - trace.begin()); + mem_idx_a = static_cast(mem_row_a - trace.begin()); + mem_idx_b = static_cast(mem_row_b - trace.begin()); + mem_idx_c = static_cast(mem_row_c - trace.begin()); + } +}; + +TEST_F(AvmPermMainMemNegativeTests, wrongValueIaInMem) +{ + executeSub(21, 3); + trace.at(mem_idx_a).avm_mem_m_val = 26; // Correct value: 21 + trace.at(mem_idx_a - 1).avm_mem_m_val = 26; // We need to adjust the write operation beforehand (set opcode). + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_MEM_A"); +} + +TEST_F(AvmPermMainMemNegativeTests, wrongValueIbInMem) +{ + executeSub(21, 3); + trace.at(mem_idx_b).avm_mem_m_val = 7; // Correct value: 3 + trace.at(mem_idx_b - 1).avm_mem_m_val = 7; // We need to adjust the write operation beforehand (set opcode). + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_MEM_B"); +} + +TEST_F(AvmPermMainMemNegativeTests, wrongValueIcInMem) +{ + executeSub(21, 3); + trace.at(mem_idx_c).avm_mem_m_val = 17; // Correct value: 18 = 21 - 3 + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_MEM_C"); +} + +TEST_F(AvmPermMainMemNegativeTests, wrongAddressIaInMain) +{ + executeSub(21, 3); + trace.at(main_idx).avm_main_mem_idx_a = 28; // Correct address: 52 + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_MEM_A"); +} + +TEST_F(AvmPermMainMemNegativeTests, wrongAddressIbInMain) +{ + executeSub(21, 3); + trace.at(main_idx).avm_main_mem_idx_b = 2; // Correct address: 11 + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_MEM_B"); +} + +TEST_F(AvmPermMainMemNegativeTests, wrongAddressIcInMain) +{ + executeSub(21, 3); + trace.at(main_idx).avm_main_mem_idx_c = 75; // Correct address: 55 + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_MEM_C"); +} + +TEST_F(AvmPermMainMemNegativeTests, wrongInTagIaInMem) +{ + executeSub(21, 3); + auto wrong_in_tag = static_cast(AvmMemoryTag::U32); + trace.at(mem_idx_a).avm_mem_m_in_tag = wrong_in_tag; // Correct value: AvmMemoryTag::U8 + trace.at(mem_idx_a).avm_mem_m_tag = wrong_in_tag; + + // We need to adjust the write operation beforehand (set opcode). + trace.at(mem_idx_a - 1).avm_mem_m_in_tag = wrong_in_tag; + trace.at(mem_idx_a - 1).avm_mem_m_tag = wrong_in_tag; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_MEM_A"); +} + +TEST_F(AvmPermMainMemNegativeTests, wrongInTagIbInMem) +{ + executeSub(21, 3); + auto wrong_in_tag = static_cast(AvmMemoryTag::U16); + trace.at(mem_idx_b).avm_mem_m_in_tag = wrong_in_tag; // Correct value: AvmMemoryTag::U8 + trace.at(mem_idx_b).avm_mem_m_tag = wrong_in_tag; + + // We need to adjust the write operation beforehand (set opcode). + trace.at(mem_idx_b - 1).avm_mem_m_in_tag = wrong_in_tag; + trace.at(mem_idx_b - 1).avm_mem_m_tag = wrong_in_tag; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_MEM_B"); +} + +TEST_F(AvmPermMainMemNegativeTests, wrongInTagIcInMem) +{ + executeSub(21, 3); + auto wrong_in_tag = static_cast(AvmMemoryTag::U128); + trace.at(mem_idx_c).avm_mem_m_in_tag = wrong_in_tag; // Correct value: AvmMemoryTag::U8 + trace.at(mem_idx_c).avm_mem_m_tag = wrong_in_tag; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_MEM_C"); +} + +TEST_F(AvmPermMainMemNegativeTests, wrongRwIaInMem) +{ + executeSub(21, 3); + trace.at(mem_idx_a).avm_mem_m_rw = 1; // Write instead of read. + + // Adjust sub_clk value + trace.at(mem_idx_a).avm_mem_m_sub_clk = AvmMemTraceBuilder::SUB_CLK_STORE_A; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_MEM_A"); +} + +TEST_F(AvmPermMainMemNegativeTests, wrongRwIbInMem) +{ + executeSub(21, 3); + trace.at(mem_idx_b).avm_mem_m_rw = 1; // Write instead of read. + + // Adjust sub_clk value + trace.at(mem_idx_b).avm_mem_m_sub_clk = AvmMemTraceBuilder::SUB_CLK_STORE_B; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_MEM_B"); +} + +TEST_F(AvmPermMainMemNegativeTests, wrongRwIcInMem) +{ + // For this test, we need the result to be zero. Otherwise, swapping + // a write for a read of Ic below leads to a violation that the memory + // is initialized with zero values. + executeSub(11, 11); + trace.at(mem_idx_c).avm_mem_m_rw = 0; // Read instead of write. + + // Adjust sub_clk value + trace.at(mem_idx_c).avm_mem_m_sub_clk = AvmMemTraceBuilder::SUB_CLK_LOAD_C; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_MEM_C"); +} + +TEST_F(AvmPermMainMemNegativeTests, wrongClkIaInMem) +{ + executeSub(87, 23); + trace.at(mem_idx_a).avm_mem_m_clk = 11; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_MEM_A"); +} + +TEST_F(AvmPermMainMemNegativeTests, wrongClkIbInMem) +{ + executeSub(87, 23); + trace.at(mem_idx_b).avm_mem_m_clk = 21; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_MEM_B"); +} + +TEST_F(AvmPermMainMemNegativeTests, wrongClkIcInMem) +{ + executeSub(87, 23); + trace.at(mem_idx_c).avm_mem_m_clk = 7; + + EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "PERM_MAIN_MEM_C"); +} + +} // namespace tests_avm \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp index 677770a1222..d93dc15bddf 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp @@ -1,8 +1,6 @@ #include "avm_common.test.hpp" #include "barretenberg/vm/avm_trace/avm_common.hpp" -using namespace bb; - namespace tests_avm { using namespace bb::avm_trace; @@ -44,8 +42,8 @@ TEST_F(AvmMemoryTests, mismatchedTagAddOperation) EXPECT_TRUE(row != trace.end()); // All intermediate registers should be set to zero. - EXPECT_EQ(row->avm_main_ia, FF(0)); - EXPECT_EQ(row->avm_main_ib, FF(0)); + EXPECT_EQ(row->avm_main_ia, FF(98)); + EXPECT_EQ(row->avm_main_ib, FF(12)); EXPECT_EQ(row->avm_main_ic, FF(0)); auto clk = row->avm_main_clk; @@ -122,7 +120,8 @@ TEST_F(AvmMemoryTests, mismatchedTagEqOperation) // in the memory trace TEST_F(AvmMemoryTests, mLastAccessViolation) { - trace_builder.calldata_copy(0, 2, 0, std::vector{ 4, 9 }); + trace_builder.set(4, 0, AvmMemoryTag::U8); + trace_builder.set(9, 1, AvmMemoryTag::U8); // Memory layout: [4,9,0,0,0,0,....] trace_builder.op_sub(1, 0, 2, AvmMemoryTag::U8); // [4,9,5,0,0,0.....] @@ -152,7 +151,8 @@ TEST_F(AvmMemoryTests, mLastAccessViolation) // written into memory TEST_F(AvmMemoryTests, readWriteConsistencyValViolation) { - trace_builder.calldata_copy(0, 2, 0, std::vector{ 4, 9 }); + trace_builder.set(4, 0, AvmMemoryTag::U8); + trace_builder.set(9, 1, AvmMemoryTag::U8); // Memory layout: [4,9,0,0,0,0,....] trace_builder.op_mul(1, 0, 2, AvmMemoryTag::U8); // [4,9,36,0,0,0.....] @@ -174,7 +174,6 @@ TEST_F(AvmMemoryTests, readWriteConsistencyValViolation) EXPECT_TRUE(row != trace.end()); row->avm_mem_m_val = FF(35); - EXPECT_THROW_WITH_MESSAGE(validate_trace_proof(std::move(trace)), "MEM_READ_WRITE_VAL_CONSISTENCY"); } @@ -182,7 +181,8 @@ TEST_F(AvmMemoryTests, readWriteConsistencyValViolation) // written into memory TEST_F(AvmMemoryTests, readWriteConsistencyTagViolation) { - trace_builder.calldata_copy(0, 2, 0, std::vector{ 4, 9 }); + trace_builder.set(4, 0, AvmMemoryTag::U8); + trace_builder.set(9, 1, AvmMemoryTag::U8); // Memory layout: [4,9,0,0,0,0,....] trace_builder.op_mul(1, 0, 2, AvmMemoryTag::U8); // [4,9,36,0,0,0.....] diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp index 883062de23e..55aca7f4bf3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp @@ -1,7 +1,5 @@ #include "avm_common.test.hpp" -using namespace bb; - namespace tests_avm { /** * @brief Helper routine proving and verifying a proof based on the supplied trace @@ -12,7 +10,6 @@ void validate_trace_proof(std::vector&& trace) { auto circuit_builder = AvmCircuitBuilder(); circuit_builder.set_trace(std::move(trace)); - EXPECT_TRUE(circuit_builder.check_circuit()); // TODO(#4944): uncomment the following lines to revive full verification diff --git a/barretenberg/sol/scripts/install_foundry.sh b/barretenberg/sol/scripts/install_foundry.sh index e085beb76d5..e5f878288bd 100755 --- a/barretenberg/sol/scripts/install_foundry.sh +++ b/barretenberg/sol/scripts/install_foundry.sh @@ -6,6 +6,7 @@ FOUNDRY_BIN_DIR="$FOUNDRY_DIR/bin" BIN_URL="https://raw.githubusercontent.com/foundry-rs/foundry/master/foundryup/foundryup" BIN_PATH="$FOUNDRY_BIN_DIR/foundryup" FOUNDRY_MAN_DIR="$FOUNDRY_DIR/share/man/man1" +FOUNDRY_VERSION="nightly-de33b6af53005037b463318d2628b5cfcaf39916" # Clean rm -rf $FOUNDRY_DIR @@ -18,4 +19,4 @@ chmod +x $BIN_PATH export PATH=$FOUNDRY_BIN_DIR:$PATH # Use version. -foundryup +foundryup --version $FOUNDRY_VERSION diff --git a/barretenberg/ts/CHANGELOG.md b/barretenberg/ts/CHANGELOG.md index 71c48c7cd02..5b5afc85a13 100644 --- a/barretenberg/ts/CHANGELOG.md +++ b/barretenberg/ts/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [0.27.1](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.27.0...barretenberg.js-v0.27.1) (2024-03-12) + + +### Miscellaneous + +* **barretenberg.js:** Synchronize aztec-packages versions + +## [0.27.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.26.6...barretenberg.js-v0.27.0) (2024-03-12) + + +### Miscellaneous + +* Move alpine containers to ubuntu ([#5026](https://github.com/AztecProtocol/aztec-packages/issues/5026)) ([d483e67](https://github.com/AztecProtocol/aztec-packages/commit/d483e678e4b2558f74c3b79083cf2257d6eafe0c)), closes [#4708](https://github.com/AztecProtocol/aztec-packages/issues/4708) + ## [0.26.6](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.26.5...barretenberg.js-v0.26.6) (2024-03-08) diff --git a/barretenberg/ts/package.json b/barretenberg/ts/package.json index 33295f00aff..983e39a36bf 100644 --- a/barretenberg/ts/package.json +++ b/barretenberg/ts/package.json @@ -1,6 +1,6 @@ { "name": "@aztec/bb.js", - "version": "0.26.6", + "version": "0.27.1", "homepage": "https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg/ts", "license": "MIT", "type": "module", diff --git a/boxes/.gitignore b/boxes/.gitignore index 0b262eb6853..c5cccc475bc 100644 --- a/boxes/.gitignore +++ b/boxes/.gitignore @@ -3,4 +3,4 @@ node_modules dest -src/contracts/target +boxes/**/contracts/target diff --git a/boxes/README.md b/boxes/README.md index b09840fd0a6..c86e754a29f 100644 --- a/boxes/README.md +++ b/boxes/README.md @@ -14,7 +14,20 @@ If you have [node](https://nodejs.org/en/download) installed, you can open a ter `npx create-aztec-app` -The script will install the sandbox, run it, and clone the boilerplate you chose. If at any time you encounter problems, refer to the guides at [docs.aztec.network](https://docs.aztec.network) for more information. +or + +`npm create aztec-app` + +The script will install the sandbox, run it, and clone the boilerplate you chose. You can pass some options: + +| Option | Description | +| --- | --- | +| -d, --debug | Displays some more information for debug reasons. | +| -gh, --github_token | You can pass a github_token in case you hit API rate limit | +| -v, --version | You can specify a semver version, or "MASTER" | +| -h, --help | Shows up this help menu | + + If at any time you encounter problems, refer to the guides at [docs.aztec.network](https://docs.aztec.network) for more information. ## Templates @@ -23,6 +36,10 @@ Currently there are two boxes: - React - A React boilerplate with a minimal UI. - Vanilla JS and HTML - Some say if you get something working in vanilla JS and HTML, you can make it work on any framework. If you can't find the box you need, this could be a good starting point. +And one contract-only box: + +- Token - An example token contract on Aztec + ## Support Need any support? Reach out on [discord](https://discord.gg/DgWG2DBMyB), [discourse](https://discourse.aztec.network/) or [twitter](https://twitter.com/aztecnetwork). diff --git a/boxes/bin.js b/boxes/bin.js index 0f018333ec0..b4e614ccfd3 100755 --- a/boxes/bin.js +++ b/boxes/bin.js @@ -1,10 +1,14 @@ #!/usr/bin/env node import { Command } from "commander"; const program = new Command(); -import { chooseAndCloneBox } from "./scripts/steps/chooseBox.js"; +import { chooseProject } from "./scripts/steps/chooseBox.js"; import { sandboxRun } from "./scripts/steps/sandbox/run.js"; import { sandboxInstallOrUpdate } from "./scripts/steps/sandbox/install.js"; -import { axios } from "./scripts/utils.js"; +import axios from "axios"; +import pino from "pino"; +import pretty from "pino-pretty"; +import ora from "ora"; +import { AZTEC_REPO } from "./scripts/config.js"; const getLatestStable = async () => { const { data } = await axios.get( @@ -13,29 +17,86 @@ const getLatestStable = async () => { return data[0].tag_name.split("-v")[1]; }; -// versioning is confusing here because "latest" and "master" point to the same thing at times -// so let's clarify a bit: -// -// if the user has set a version (ex. "master" or "0.23.0"), use that -// otherwise use the stable release (ex. 0.24.0) -const latestStable = await getLatestStable(); -const versionToInstall = process.env.VERSION || latestStable; - -// if the user has set a semver version (matches the regex), fetch that tag (i.e. aztec-packages-v0.23.0) -// otherwise use the version as the tag -const tagToUse = versionToInstall.match(/^\d+\.\d+\.\d+$/) - ? `aztec-packages-v${versionToInstall}` - : versionToInstall; - -program.action(async () => { +const init = async ({ debug, github_token, version }) => { + const axiosOpts = { + timeout: 5000, + headers: github_token ? { Authorization: `token ${github_token}` } : {}, + }; + + const prettyOpts = { + sync: true, + colorize: true, + include: debug ? "time" : "", + customLevels: "success:80", + customColors: "success:bgGreen", + }; + + const prettyStream = pretty(prettyOpts); + const logger = pino( + { + customLevels: { + success: 80, + }, + level: debug ? "debug" : "info", + }, + prettyStream, + ); + + global.debug = (msg) => logger.debug(msg); + global.info = (msg) => logger.info(msg); + global.success = (msg) => logger.success(msg); + + global.warn = (msg) => logger.warn(msg); + global.error = (msg) => logger.error(msg); + + global.github = async ({ path, raw = false }) => { + try { + const url = raw + ? `https://raw.githubusercontent.com/${AZTEC_REPO}/${path}` + : `https://api.github.com/repos/${AZTEC_REPO}/contents/${path}`; + const { data } = await axios.get(url, axiosOpts); + global.debug(data); + return data; + } catch (e) { + global.error(e); + } + }; + + // versioning is confusing here because "latest" and "master" point to the same thing at times + // so let's clarify a bit: + // + // if the user has set a version (ex. "master" or "0.23.0"), use that + // otherwise use the stable release (ex. 0.24.0) + global.latestStable = await getLatestStable(); + global.version = version || global.latestStable; + + // if the user has set a semver version (matches the regex), fetch that tag (i.e. aztec-packages-v0.23.0) + // otherwise use the version as the tag + global.tag = global.version.match(/^\d+\.\d+\.\d+$/) + ? `aztec-packages-v${global.version}` + : global.version; + + global.debug(`Version: ${global.version}`); + global.debug(`Tag: ${global.tag}`); + global.debug(`LatestStable: ${global.latestStable}`); + + global.spinner = ora({ color: "blue" }); +}; + +program.option("-d, --debug", "output extra debugging"); +program.option("-gh, --github_token ", "a github token"); +program.option("-v, --version ", "a version number or master tag"); +program.action(async (options) => { + // SETUP: Initialize global variables + await init(options); + // STEP 1: Choose the boilerplate - await chooseAndCloneBox(tagToUse, versionToInstall); + await chooseProject(); // STEP 2: Install the Sandbox - await sandboxInstallOrUpdate(latestStable, versionToInstall); + await sandboxInstallOrUpdate(); // STEP 3: Running the Sandbox - await sandboxRun(versionToInstall); + await sandboxRun(); }); - program.parse(); diff --git a/boxes/boxes/react/src/contracts/target/boxreact-BoxReact.json b/boxes/boxes/react/src/contracts/target/boxreact-BoxReact.json deleted file mode 100644 index 012a6be45cd..00000000000 --- a/boxes/boxes/react/src/contracts/target/boxreact-BoxReact.json +++ /dev/null @@ -1 +0,0 @@ -{"noir_version":"0.24.0+cbbc2eb02547deca473e1e0661ff6f9ee20e38ae","name":"BoxReact","functions":[{"name":"getNumber","function_type":"Unconstrained","is_internal":false,"abi":{"parameters":[{"name":"owner","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]},"visibility":"private"}],"param_witnesses":{"owner":[{"start":0,"end":1}]},"return_type":{"abi_type":{"kind":"struct","path":"value_note::value_note::ValueNote","fields":[{"name":"value","type":{"kind":"field"}},{"name":"owner","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"randomness","type":{"kind":"field"}},{"name":"header","type":{"kind":"struct","path":"aztec::note::note_header::NoteHeader","fields":[{"name":"contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"nonce","type":{"kind":"field"}},{"name":"storage_slot","type":{"kind":"field"}},{"name":"is_transient","type":{"kind":"boolean"}}]}}]},"visibility":"public"},"return_witnesses":[1,2,3,4,5,6,7]},"bytecode":"H4sIAAAAAAAA/+2daXQc13Xnq4HG2mjsAEEsZIELuAAkuwFS+9KiJEqiJEqkJEriIpLivoDgAu6yvCVOvMV2YtmJ48TZrCR2Eid2nNhOHGeVrVh27FhecjLfZs5kPs6ZmQ9z5pyhx9V4f+GPh9ctVLte63J86xwSt+57r+7v3nr13qtXr6obgiBIBTNbLcm8QVcwf3M/3ZZP8Fi5BgdnDfkTbWnzt878rTd/o7L39czIjXScMCm+jblb6gnAjm2GWJEnYmqh9FR6rk/FMum5/kW62vScwxR16fRcvyNdXXpuDCJdPdmGriE9Ny7txIJ8jWQvDJKrHxnyDZsdu5DktIPnenI8uWwwvy41UgzDhH2vCxbuOxiyVI4ZGzwx1sdgbCDGegdjoyfGhhiMjX55inWowWGr2ZPvTcHCfW928KQS9r3JYavFk++ZYOG+gyFL5Zgx64mxJQZjlv62OBhbPTFmYzC2EmOW2PC3zRNjawzGNmJEOW6H2j0xtsVgbCfGNmLD3w5PjO0xGDuIEeU4jp3JM45nyO5CGDuJp9sTT2cMnm7i6UqeJ+/Jz1x0jJ5gflxhK0vpXAd6PPiYIrs4NvaZ8UbijXg6LNYM5esQwghdl1+e8YzFE23lrqse4lnkiacnBs8i4ulNnifvyc/idd4XzI8rbGUpna+bPg8+psgujo19ZryRePkaAmuG8nULYYSu1y/PeMbiibZy11Uf8fR74umLwdNPPIuT58l78rN4nQ8E8+MKW1lK5+tmwIOPKbKLY2OfGW8kXr6GwJqhfIuEMEK32DNPxuKJtnLXlYuRz+ugJ8aBGIyDxDhAbPg75IlxMAbjEDGiHMdxiSfGoRiMS4hxiNjwd6knxiUxGJcSI8pxHENPjEtjMIbEuJTY8HfYE2MYg3GYGKHnOC7zxDgcg3EZMQ4TG/4u98S4LAbjcmJEOY7jCk+My2MwriDG5cSGvys9Ma6IwbiSGFGO4zjiiXFlDMYRYlzpYFzliXEkBuMqYhxxMK72xLgqBuNqYlzlYFzjiXF1DMY1xLjawbjWE+OaGIxriXGNg3HUE+PaGIyjxLjWwTjmiXE0BuMYMY46GNd5YhyLwbiOGMccjOs9Ma6LwbieGNc5GDd4Ylwfg3EDMa53MOY8MW6IwZgjxg0OxrwnxlwMxjwx5hyM454Y8zEYx4kx72Cc8MQ4HoNxghjHiQ1/N3pinIjBuJEYJxyMmzwxbozBuIkYUY7P9U3JMxbnKDfFYLyJeG5JnmdjhmwshOcW4rk5eZ68Jz+Lzc2twfy4wlaW0rkO3OrBxxTZxbGxz4zKq7y3Es8mizVD+TYJYYTuZs88GYsn2sq1W7c6eArJ8eSyjnhEtm5P3vdiH3JbsHDfbyeeOxPn2ZjLkI2F8NxJPHckzjPThyTv50wfclcwP66wlaV0bjPu8uBjiuzi2NhnxoXyNt5gvBpfja/GV+Nbilfjq/HV+Gp8S/FqfDW+Gl+Nbyleja/GV+Or8S3Fq/HV+Gp8Nb6leDW+Gl+Nr8a3FK/GV+Or8dX4luLV+Gp8Nb4a31K8Gl+Nr8ZX41uKV+Or8dX4anxL8Wp84/NGPLdZrBnKd5sQRuju8MyTsXiiLWXthyS7GHmt/N3JMxbXyt8Vg/Fu4rkneZ7i+1Z3x+C5h3gKyfPkPflZXCu/OZgfV9jKUjq3RZs9+Jgiuzg29plxobyNNxivxjc+L/c9YM1QvruEMEJX8MyTsXiirVy75WLktv7e5BmLbf3mGIz3Es/9yfMU2/p7Y/DcTzz3Jc+T9+Rnsa3fEsyPK2xlKZ3boi0efEyRXRwb+8yovMq7hXg2W6wZyrdZCCN093nmyVg80Vau3XIxclv/QPKMxbZ+SwzGB4jnocR5xovvwD4Qg+ch4nkwcZ6Ztj55P2fa+q3B/LjCVpbS+dre6sHHFNnFsbHPjAvlbbzBeDW+Gl+Nr8a3FK/GV+Or8dX4luLV+Gp8Nb4a31K8Gl+Nr8ZX41uKV+Or8dX4/mzFl5/dgDVD+bYIYYTuQc88GYsn2lLWfkiyi5GflTycPGPxWcnWGIwPE8+jifNMFJ+VPByD51HieSRxnplnJcn7OfOsZFswP66wlaV0bou2efAxRXZxbOwz4/+vvI03GK/WB7+8Wh+UV+uD8pbi1fqgvFoflLcUr9YH5dX6oLyleLU+KK/WB+Utxav1QXm1PihvKV6tD8qr9UF5S/FqfVBerQ/KW4pXQn2IeLZarBnKt1UII3SPeObJWDzRlrL2Q5JdjLxW6LHkGYtrhbbFYHyMeLYnz1P8hsZjMXi2E8/jyfPkPflZXCu0I5gfV9jKUjq3RTs8+Jgiuzg29plReZV3B/Fss1gzlG+bEEboHvfMk7F4oq1cu+Vi5Lb+ieQZi239jhiMTxDPU8nzFNv6J2LwPEU8TybPk/fkZ7Gt3xnMjytsZSmdr+2dHnxMkV0cG/vMqLzKu5N4dlisGcq3QwgjdE965slYPNFWrt1yMXJb/3TyjMW2fmcMxqeJ59nkeYpt/dMxeJ4lnmeS58l78rPY1u8K5scVtrKUztf2Lg8+psgujo19ZlRe5d1FPDst1gzl2ymEEbpnPPNkLJ5oK9duuRi5rd/tiXFXDMbdxOiqe3s8Me6OwbiHGHcTG/7u9cS4JwbjXmJEOY7jc8kzFvv1vTEYnyOe/Z54novBs5949iXPk/fkZ7FfPxDMjytsZSmd68ABDz6myC6OjX1mvJF4I569FmuG8u0VwgjdPr884xmLJ9rKXVcHiOegJ54DMXgOEs/zyfPkPflZvM4PBfPjCltZSufr5pAHH1NkF8fGPjPeSLx8DYE1Q/n2C2GE7nm/POMZiyfayl1Xh4jniCeeQzF4jhDP4eR58p78LF7nR4P5cYWtLKXzdXPUg48psotjY58ZbyRevobAmqF8B4UwQnfYM0/G4om2cteVi5HP6zFPjEdjMB4jxqPEhr/HPTEei8F4nBhRjuN4whPj8RiMJ4jxOLHh70lPjCdiMJ4kRpTjOJ7yxHgyBuMpYjxJbPg76YnxVAzGSWJEOY7jaU+MkzEYTxPjJLHh75QnxtMxGKeIEeU4jmc8MU7FYDxDjFPEhr9nPTGeicF4lhhRjuN4zhPj2RiM54jxrIPxvCfGczEYzxPjOQfjtCfG8zEYp4nxvIPxgifG6RiMF4hx2sF40RPjhRiMF4nxgoPxkifGizEYLxEjyjUT42VPjJdiMF4mRpTjOF7xxHg5BuMVYrzsYLzqifFKDMarxHjFwXjNE+PVGIzXiPGqg/EFT4zXYjC+QIzXHIwvJs9YnG95IQbji8TztuR58p78zEXHfbs51vUEeaNjvCOYfw7hQ5bS306xe4eH2KXILo6N/XeQfqG8NQJ4Pdkeb/3JMZrIf7YXWFzvNH/TpMd1GfnwLiPXmX3kb6a8yPNDU7AtmIk1tjVk/53J+5svd03DHvMsF8ZzRRjPkDCe88J4OoTxTArjyQjjOSqMZ7cwnu3CeO4XxnOLMJ6cMJ61wnhWCOO5KoxniTCeaWE83cJ4TgvjaRHGc0wYT60wnj3CeHYI49kijOc2YTx5YTyjwnhWCuO5JoxnqTCeC8J4FgnjmRLGkxXGc1wYT50wnr3CeJ4SxvOQMJ47hfGMC+MZE8YzIoznRWE8oTCei8J4+oXxnBHG0yqM54QwnnphPPuF8ewUxrNVGM9dwngmhPGsE8azShjPsDCeS8J4BoTxnBXG0yaM56QwngZhPAeF8TwrjOdRYTz3COPZKIxnvTCe1cJ4lgnjuSyMZ1AYzzlhPO3CeE4J42kSxnNEGM8uYTzbhPFsFsazSRjPBmE8KQE8mWD+u1cZSm8mHd4nqSXdu41cR7qfM3I96X7eyA2ke4+Rm0j3CyTj7y8auYV07zVylnTvM3Ir6d5v5DbSfcDI7aT7oJE7SPdLRu4m3YeMvIh0HzZyP+k+YuQB0v2ykQdJ9ytGHiLdR428hHQvGXkp6T5m5JB0HzfyMOl+1cjLSPdrRl5Ouk8YeQXpft3IK0n3SSOPkO43jLyKdL9p5NWk+5SR15Dut4y8lnS/beRR0v2OkcdI97tGXke63zPyetJ92sgbSPeykXOk+30j50n3B0YeJ90fGnmCdJ8x8kbSfdbIm0j3R0a+hXR/bOTbSPcnRr6TdJ8z8l2k+1Mj30O6PzPyZtJ93sj3k+4LRt5Cuj838kOk+6KRt5LuL4z8KOn+0sjbSPclI28n3ZeNvIN0XzHyU6T7KyPvJN1fG/lZ0n3VyLtI9zdG3k26rxl5D+n+1sh7Sfd3Rt5Pur838kHS/YORj5DuH418lHT/ZORjpHvFyMdJ93UjnyDdN4x8knSvGvkU6f7ZyJOk+6aRT5PuNSNPke5bRj5Dum8b+Szp/sXI50j3HSOfJ913jTxNun818gXSfc/IF0n3upEvke77Rr5Muh8Y+Qrpfmjkq6T7kZGvke7fjPwi6fDuKfeN6OveRTq8h/lu0qH/+znSof/7edKh/3sP6fD+J/d96BN/kXToi99LOvST7yMd+sn3kw795AdIh37yg6RDP/lLpEM/+SHSoZ/8MOk6jfwR0nUZ+ZdJh/70V0jXY+SPkq7XyC+RDv3ux0jXZ+SPk26xkX+VdOiff4106J8/QTr0z79OOvTPnyQd+uffIB36598kXWjkT5EO/fNvkQ7982+TDv3z75AO/fPvkg798++RDv3zp0mH/vll0qF//n3SoX/+A9Khf/5D0o0a+TOkQ//8WdKhf/4j0qF//mPSoX/+E9Khf/4c6dA//ynp0D//GenQP3+edOifv0A69M9/TrqbjPxF0t1s5L8gHfrxvyQdvn/+JdKhb/8y6W438ldId4eR/4p0GAP8NekwBvgq6e428t+QrmDkr5EOY4W/JR3GCn9HunuN/Peku8/I/0A6jCn+kXQYU/wT6R4w8iuke9DIXycdxh7fIB3GHq+S7mEj/zPp8BuH3yQdxiivkQ5jlG+RDr/r9W3S4Xe0/oV0GMt8h3QYy3yXdPjtmH8lHX6r5Xukw5jnddJhzPN90uH3CX5AOvwewA9Jh7HRj0iHsRH6vqgv+lrDbDoYa6gMfOF7PvicJh1iw/eBiCHfB36LbEOHc9JIOjBy3OALxxc+83lAbPh8IYZ8XhFrPv84J685+Ph+HWXCINn7dbYV0j7stRDHa0J4Ngjj2SSMZ7Mwnm3CeHYJ4zkijKdJGM8pYTztwnjOCeMZFMZzWRjPMmE8q4XxrBfGs1EYzz3CeB4VxvOsMJ6DwngahPGcFMbTJoznrDCeAWE8l4TxDAvjWSWMZ50wnglhPHcJ49kqjGenMJ79wnjqhfGcEMbTKoznjDCefmE8F4XxhMJ4XhTGMyKMZ0wYz7gwnjuF8TwkjOcpYTx7hfHUCeM5LownK4xnShjPImE8F4TxLBXGc00Yz0phPKPCePLCeG4TxrNFGM8OYTx7hPHUCuM5JoynRRjPaWE83cJ4poXxLBHGc1UYzwphPGuF8eSE8dwijOd+YTzbhfHsFsZzVBhPRhjPpDCeDmE854XxDAnjuSKMZ7kwnjUWD7+39m+kw3sI/A4O3gXgd3WwHp/f6cGaeH73B+vS+R0hrA3nd4nw/g6/6457NH4PHe/v8DvimDvm97fx/JrfrcaaNX7vGe/vNNHfSIf58TBI7FwdjOyhX8KWsvZDkvnb93uS58l78rP4G8LPkX9JHTc6xj6Kz24rTllKf45it89D7FJkF8fG/j6H7cYg2Tjsf5M47Hew7K9yHPY7bCf4m9LFOBx4kzgccLAcqHIcmHGhvPtuMN7nbjDeGy2++28wXq2/Gl+tvz8dL4/PCkGy47ODyft0ayaYG99oS1n7Icn8LebnPcTYk5/Fccch8uOA5U+W0rldOeTBxxTZxbGxz4wL5d2nvF55tT4or9aHny1eT/1Q3pNPxfHBYWJPijdLcaqh4x/xdF4C67xggz3muVsYz63CeCaE8awTxrNKGM+wMJ4BYTzPCOPpEcazQxhPmzCeR4TxNAnj2SKMp1YYT0EYz23CeDYK41kvjGe1MJ5lwngGhfE8K4ynVxjPE8J42oXxPCqMp1kYzwPCeNLCeO4RxnO7MJ5Nwng2CONZI4xnuTCeIWE8u4TxLBLG86Qwng5hPNuE8WSE8TwojKdOGM9mYTx3COO5SRhPThjPWmE8K4TxLBHG0yeM5ylhPJ3CeB4TxtMijOchYTz1wnjuFcZzpzCem4Xx5IXxjArjWSmMZ6kwnsXCeHYK4+kSxvO4MJ6sMJ6twngahPHcJ4znLmE8twjjGRfGMyaMZ0QYTyiMp18Yz9PCeLqF8WwXxtMqjOdhYTyNwnjuF8aTEsCTCea/r8rfsOFvyeB7XrtJd8zIe0iH74jvJR1+y+QA6fD7Zc+T7pSj7KSRD5IO38Y8RDp8n/sw6fDODfuLdbFHSYe1K8dIh+dLx0lXb+QTpMM49iTpUPdPkQ7rlSdJhzVFp0mH537wJzr+y82z6ShfQ2Vgh3//e8ph77SDCzLXR5QJg2TrI9sKaR/2WojjlBCe+4XxNArjeVgYT6swnu3CeLqF8TwtjKdfGE8ojGdEGM+YMJ5xYTy3COO5SxjPfcJ4GoTxbBXGkxXG87gwni5hPDuF8SwWxrNUGM9KYTyjwnjywnhuFsZzpzCee4Xx1AvjeUgYT4swnseE8XQK43lKGE+fMJ4lwnhWCONZK4wnJ4znJmE8dwjj2SyMp04Yz4PCeDLCeLYJ4+kQxvOkMJ5Fwnh2CeMZEsazXBjPGmE8G4TxbBLGc7swnnuE8aSF8TwgjKdZGM+jwnjahfE8IYynVxjPs8J4BoXxLBPGs1oYz3phPBuF8dwmjKcgjKdWGM8WYTxNwngeEcbTJoxnhzCeHmE8zwjjGRDGMyyMZ5UwnnXCeCaE8dwqjOduYTw1Dh68a1NIjqf4G0AnEvdzUy7yDe8Q1Ztjgx/20pRnv5mwQD8JfbThnZ6TFJ9JKx/7UQiSO1/RcY95is9RKz7gP0bxQZ6jVnyg5/icoPgct/KxH4UgsfiM+3mPbyY+Z6z4gP8IxQd5TlvxgZ7jc4zic9TKx34UgsTiMxEd96yn+Jyz4gP+sxQf5LlgxQd6js8Ris8ZKx/7UQgSi8/G6LjnPcVn2ooP+M9TfJDnBSs+0HN8zlJ8zln52I9CkFh8NkXHveApPhet+ID/AsUHed5txQd6js95is+0lY/9KASJxeem6LiXPMXnshUf8F+i+CDP+6z4QM/xuUDxuWjlYz8KQWLxuTk67hVP8blqxQf8Vyg+yPMRKz7Qc3wuUXwuW/kaKV8qSHY8hveD68yxJy2uNOX5OPnB7yXz+9LIy+9aw48zpEOczpHumpGnSfeCkS+S7m1Gvkw6jBknSYd5K37XGs/OrpIO63eukA5rdq+RDu/pvEA6vJsLpiajazH7YZDs+QI/jo192PNpu8Gy3WDZzlJ6TRV4AosnKMOTEcbTKIynVhhPWhhPkzCeOmE8zcJ46oXxNAjjSQngKfUtGqTzt03AniYdvvtQRzqMsepJh/UODaTj36KArsbBB4Ys6cDQSjowtJEODO2kA0MHMZ1rn03HWscaKoP3GzgeeKeR44HvGHA8MHfO8Rgk29Dxb7tAh/cYmkiHdxebSReSjL+YI+dYwudFpENs+kiHGC4mHWLdTzqckwHSwd4g6fD+zBDp8M7sEtLhOxlLSYdnMyHpsD5kmHSQ+boKqWzByLmfbiteV2wrpH3YayGOYSE8DcJ46oXxNAvjqRPG0ySMJy2Mp1YYT6Mwnowwnpoq8qA/xbHbLB6ftrOW7WwVbXdatjuraLvbst1dRdu9lu3eKtrWuqZ1rVq2ta5pXbNtL0nc9qYc3+NiS1n7nM6/W7Y0cZ6ZdRnJ+zmzHmaI/EvquNExBh2xgg9ZSud5iEEPsUuRXRwb+4MO29eDZOMwYNm24zDgYBmochyYUXmVV3nl8Q4pr1derb/Kq7zKW4pX21+/vFp/lVd5lbcUr7a/fnm1/iqv8ipvKV5tf/3yav1VXuVV3lK82v765dX6q7zKq7yleLX99cur9Vd5lVd5S/Fq++uXV+uv8iqv8pbi1fbXL6/WX+VVXuUtxavtr19erb/Kq7zKW4pXQnsW2e5P3PahjRnLdrSlrP2Q5H7PsfDj58z7eIvJjyWWP1lK5/q52IOPKbKLY2OfGZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeZVXeQvKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zKq7zK+zPFG9nuS972RMayHW0paz8kuc9zLDz5mYuOsYj86Lf8yVI6n+9FHnxMkV0cG/vMqLz+eLOUXkM8HupefiHXE/N0CePpFsbTLoynTRhPRhhPjzCeXmE8rcJ4ssJ4moTxtAjj6RTG0yGMp1kYT0oATyaYP87PUHoN6TBm6iDdMiO3k265kdtIt8LIraRbaeQs6UaM3EK6VUbuJN1qI3eRbo2Ru0m31sg9pBs1ci/pxozcRLp1Rm4m3XqS8XeDkUPS5Yy8lHR5Iy8h3biRB0g3YeR+0m008mLS4dzwuaw18iLSpY28jHR1Rl5OunojryBdg5FXkq7RyCOkQ9xWkQ5xW006xG0N6XCu15IOdWKUdKg7Y6RDHVtHOtRFPleosxtIh/qUIx3qU550qE/jpEN9miAd6hPOVRS7s52z6SjP1xTs1JJuo8PehIMLMrcjKBMGybYjbCukfdhrIY68EJ5mYTwdwng6hfG0CONpEsaTFcbTKoynVxhPjzCejDCeNmE87cJ4uoXxdAnjqbF4eJy3kXTo53ishrJ8L4MxGPI3GR8zHnzk8XFAvvIWksxzeSwXkuHJZYO59zk4fjZ538d5zL8Q33keqi15ngm+31gID8/ztibPk/fkZ/E2pz2YH9c22uf7ePjY7sHHFNnFsbHPjMrrjzfiabFY+Z66RQgjdK1+ecYzFk+0lWsH+PlTZ/I8EzyXsRAenv/tSJ4n78nPXHRcjC2uB8m2d93B/PMFH7KUzs9auz3ELkV2cWzsM6Py+uPltoTbYeRrE8IIXYdfnvGMxRNt5doXfv7fmzzPBM+1LoSHn9/2JM+T9+TnvDVI3ZY/vEaGxwm+1sj0BnPji/1Sa3qUN1levub52RXydQphhI7XcUBXSI4nx8+YcPzoedUrptGOeNE21hu7yJ+mv8jzhY7ZY7zaPsvuawwJu9gWOob0cK8dewzJ99q+7m09+JnzNS8SHaMrmH++svSXn0HDfpeH2KWCufMUIe0zo/L64432OyxWnj/qEMIIXatfnvG4c2d8H+BhzDbBz/AXwsN9mY8xvyc/i+1SryOusMX9NV83HsazxTrZE8yNL/aZUXn98fI1z+0l80pghI7vJaErBMmOIfH8HsePxn8/pjEk2m+MIZEfa57SlGeCxpA1RuZnhnh20mLJ0cbrnnhO1Vf/AFs4Nva7iIHX4UEHNl6312XpfM6NdFnc2O8mRpcvYOP1gd2WztccQSqYO2cR0n4PMbp8sed5+HrlccRbdb22lPAFbPzMoNfSvZX3qi0OX3ic0u7g5mefOA5fI310bOh4LSb+Ys0mX0NY28ntMt594jo7ZGSeA8BaUa4jWFPKa1rxPJvPCZ5ncwxwf8zzH1gLyutIsRaUfUS7yOtScd/N61fRjg6SDvEdIh3ixuthEV/4iGfwvp4/wU8cG/t8X+7hPng87n05GPgZYh3FrdXB7WPdQops4dh2X5IlXb3fOOaTiGMDlXuzMQHHNRX4iWudxQJ7acqzxTQIbVZsC8kxTTBDjRUPvq/0MB64lfunenNssHRTPJDnEYpHEMzt23CdoDz3x677v0Lgr58tOPzw1FcWY9hnxRAsiyiGyPOkFcM+Rwx5HNBr5eP3WApBcm1luRj2VSGGixcQQ+TZY8Vw8ZvEsN3KFx0LdXM/3XN8ju457DEij9N53OijvS03Tm8lv1zPfT30R8U2CucB54ff4UFMkee41W56qDMTvvre6Bh95FO3w0+kn6a6c6ZjNp/d7kXpb3ekYyvXlyJ2kb/9yfubi2xjXIlz2++wPUisCdnOs+2U+Qc70KdJfpEe+gzOim/EGdzRtbHYkY/lLqtMltIXO/wOE/a71DdIYC+qM+epfqH++Gpz2G+OTxPFB+l8H9ph5ef7Pc9rK8rep/JaD+i47eQxqs2dFcDN4yfPazAmXGMYe16P270PW+27j2/l+JpLio7BbXmXw0+kv0TX38ep/bbrU5T+siMdW7n23fM3fnLc1uDcLnbY5nY4Idtz2jm077ADfZrkT1P7PjArvhFncEfXxiJHPpZ7rTJZSl/k8DtM2G9uS0Pah72oznyC6tfL1L77aHPYb44Pt+9I5+fDWSt/Jpj//NjnPHu7FUfs83NY+16Px/Ke7tvnsRWC+fftPE/H80k/pvUxPtYQR2y1wdy4YZ/7ZElrc3gsUUPxa3dw+7rnKlXXXPNZtX7jmE8ijmkq92ZruTiuSfcBXPeZpZUYkOcVa2wBfSE5po3MUGPFw/Pc7kG+t0d/zHMMiAfyvGbNdfC9o/1+Hb+/7JoTKAT+5igKDj88jeEO8vgZMXSN45DndSuGvY4Y8rNOey2rpzWY4+ViyLY9zJ8cdI35weKat/xPZeYtXTHssfJ5mrecKBdDz/OWB13zlq4YIs9/KTNv6Yphh5UvOhau7/9GY8fJztkyXD7a+LkVr4vwsD607HOrLDHY/SrfjzdTPOz1dYXA33sRrjlOe+zLc5z/s0pznD7WJUTH4DnOdoefSP/fVM/+D93j4pygvkXpTZ3z07HpHOfC5jgb6WWhcvOVC5njbLXKSJzj/L9Uv1B/fM7tL3bEh9dBI53nD1us/HxfUo21ZnHugXmtGeQ2B3ebAG5u9zme9nq/GirD9wO+3ucoNzaCPW4jBztnY+pzPtRHnx0dg9v9VoefSB82fkbX6nJq6+26F6WPO9Kx6XzowuZD89QX8Nwm4hxnPtR+Bi5xPnSE6tc49QXVmA91talI5/Xdrnebcc1wmyphXRg/S7LX6jJ3pwDuOPcFGStfIfDWj0245hrs9dHcRt5v9QU+7lV89dnRMbjdb3f4ifStdK0+4hj381z87grvCzzPgeRc9++LHLa5zU7I9pw2EX2B/TskPHewi/oCHlcjzrwuu8+Rj+VWq0w2mP8bEp7uxfJ8n41jL7IYozrzGNWv3dQX+Hom3OeID7epSOd1+Z2O/Cjj+zsxKbKFY2ccjNDxejjI/K1uD+/1zmv3+fzBXg3pkPe6Fbfkvldz5AjflzSYY9tr/bjtO0ntOX+/jZ/9T1L99PC8Is/PK3Bs+3kFvyfQQWyv0LNGD9fzOL+jga1cm+76zSd+buD6LSZfY9JS8xMDxAgdX8++2sU6i6fOiplP2w2W7YYq2m6ybDdV0XapNrQatku9Y14N26Xep+PrE1tNFXgCiycow9MljKdbGE+bMJ5mYTwZYTxpYTx1wngWC+Opxj1SHJ4OYTzVGCvF4WkVxtMojKdJGE+tMB7Pz6dj8/QI4+kVxtMujKdFGE9WGE+9MJ4GYTwpATyZwP0bdkjnNduYP+Hf28KajzTp8J0K/sYCvlNRTzp8p6KBdGEwGxPoho3M76YuMzJ/e4R/jw1/8XtsvG6u3G/n8Zwvfo+N11msNjLPz+H32PhdOfweG79nilhy7BFL/gYIYsnfAEEs+RsgiCV/AwSx5N/OQyxD0iGWw6RDLJeRDrHk2CKW/Ft3iCX/1h1iyb91h1jyb90hlqtJh7Ev/9Ydxp+IbeTraM9sOspznYUdrrNrHfbWOLgg83WKMmGQ7HXKtkLahz3+jbhVQngahPHUC+PJCuNpEcbTLoynVxhPjzCeRcJ4aoXxNAnjaRTG0yqMp1MYT4cwnj5hPIuF8dQJ40kL48kI42kWxtMmjKdbGE+XMJ6aKvLgfhTHXmPxRLZxX11IznbxtyBWJu7ToeK72ZgvwJpM8MNemvI8bE4+rhHoow337yN0blZb+diPn2ad2RFrS1k2rpNt2Ktx8BQspkKQXH2Jjov5mTBI9pxhLgjnDPywl6Y8T1nnDPpoW2vFqIVis4ziuSxxP8r/dhjPdeH+BvWquEa1a5bNw/V2gNsefMPB5khTnuNds2z7umZjaa+v47lZfs4+5Cm+g1Z8sQ97ESPmOHleE2z9Dm6eE61x+FdrHS+6/yoXT1yTHM9TFM//3j0bJw/nehOz1QTucx3pcY0gL9bNLqf9Splc7RmugQZz7HLX+Hm6xj21Z8XvJ8A2jm3HpIbk5VaclnmK07AVJ9hfRnFCnqtWnJA3DJJtn2EP7fNyK07M9KLVPkMfbWutWLaQX8jHfhSCZNsPZik4/KgJZp9fIC/O91LaL1TI5DrfeK6C8w37Sym2yPML1vlG3jBI9nzzc7SQYhE6mN5vnW/oo22tFcsW8gv5GklO8Ldl55xvjKFs2zWkQ96U+VeqrvD4a7lV9nqC/rjqSmiOhbqy3PInTXk+ZtUV5AmDZGNc6h6Cz2/y48aZdwe4rkVbytoPSV5OPB7GJxP8bHghPEPEEybPk/fkZ/HeDWOhpH8LesBxvuADv3M8SLHz9X7HUDD3vGG/1DvSypssb8SzxGLldR9LhDDyNQYe6ArJ8RR/Lwtz5bz25Yt+7x0nXPc64HDdO/6v7lm2L9O9I9J5HclKS+epryieS9jCse37j5Zg/lyRz35zxOIZccTirbTt4Z4r5+n8TrjuUVz3l8jz9TL3KKinPIe0xMrHfhSCZPvs0FN8hqz48HlAfJDn21Z8hhzx4etm2MrHfhSC5MZ8PPYIE46P/Y0v8PPaQ+T5vhWfAUd8QoqP3W/4uVef+e4rX9vRVm4Mys8YfPShvL5tITwcHx/fFeP1pQvh4XGQj7WzPA+5EB5+t3PUE09/DJ5R4hnzxDMag2eMeNZ54hmLwQOGaJxo97GRDtfGMOlQP3lcjjqygnQ4T8tIh1jVkA68mOdoIR3Pc7venX+rvu3XQr70O3gKyfHcwjz2fLnrPigVJNvfJ19PNxW/TbPeHMv+ZiXspSnPj625ovUemHxdk9ExNpBPow4/30ine5N6I3MfhesiSu9xpGMrd80jdpG/+eT9LZ7bcXMsnNu8w/YEsSZkO8+2MU8KO9CnSe6mDwVMzIpvxBnc0fWec+RjeZVVJkvpOYffYcJ+54klpH3YK36DlOpXj+M5X5JM7DfHh98BQjq3XdyfFig/z49uSJx3pk3CNYl6Cxa+fpFnyMQPbZKPdtKPrzPnZj35NOLwE+nLqM6soDYH5wXnNUqfcKRjW8g45K1ok9i2hDZpvESbZLcvC2mT+q0yEtukVVS/JqhN8jFeZ785PqMUH6RjHJwK5j7HKVB+bpOSv192j5PAws+2ked2q03yNU7yMTcQHYPbnzGHn0gvUJ3ZTG2OPSaP0rc70rEtdJyUS97fHF8fOLc5h21uOxKyPefaRJsEO9CnSX6c2qTxWfGNOIM7apPWOfKxPGqVyVL6OoffYcJ+8/Uf0j7sRXXmfqpf26swTlrniA/fhyMd9+E8nxwYFvtZlJ85oZk2Cdehvf6Cv/OMPM9abZKPsZuv+a/oGNz+jDj8RPpzVGf2U5uD84LzGqVPOdKxlWuTEDtP96o5vj5wbtc5bHPbkZDtOdcm2iTYgT5N8mlqk3icYd9fR23Sekc+lpdYZbKB+57Vw9g0z/cdOPY6izGqMwepfk1VYZy03hEfngdEOuYB7ed2Bcrvd23LTJvEz4BDYoE9vlYvWW2Sj7GbH19nzg23P2MOP5H+AtWZF6nNwXnBeY3SP+hIx1auTeJnNMmPN3PO+/L1DtvcdiRke861iTYJdnj+DvIHqE3icQbiDO6oTdrgyMfysFWG7002OPwOE/abr/+Q9mEvqjPvpPr1QWqTfDz7Yb85PiMUH6TjOUTkBz8PKVD+aoyT7GfaYOHrF3lestokH+1ktcZJow4/kf4JqjOfpDYH5wXnNUr/rCMdW7k2iZ/zV7tNYtsS2qTPlGiT7PZlIW3SiFVGYpv0Kapfn6U2ycdaJfab4zNG8UE6noO65riRn9uk5N8Bc4+TRi0+vla/UKVxUvK+zh8nLXH4ifQvUZ35CrU5OC/8LtyrjnRsCx0neZjTd84VbnDY5rYjIdtzrk20SbDDzxkgf4PaJL73sZ9D8NokzsfymFWG50uGHH6HCfvN139I+7AX1ZmvUv16ldqkYQ9M7DfHh+e4kY51GAud4/Y1TsI1ac9x8/WLPN+12iQf7WS1xkmueTOk/4DqzI8cc9i8FuA/KpzjRuzeijaJbUtok/5riTbJbl8W0ibZz40ltkn/TvXrP6owxz3kiA/PcSN9KekWW/l5vpTXgfloR+02MQzc82DQ8RjB8zvUc77VgWPb71Dzu/z8jH73Df7Og12uEMy+74HzUhPMfx8S7z6GtF+o0BfXu4+ov/a7j7DH9/o/tvowX9+tsOcfXO8cIE9tzyxTEMy9Xl3frQitfD7fnRi0/Ohz+PHG9w965sbWx3p8X9dEdAz+3ewRh59IbzV+Rtd0O33/1f5GQJS+1JGOrdz4gNeXepjTy/H8nH0/yrZ9jQ/G6Lg8PoCe59eX4EOUwdy+HnEGN3+HpNT4YKVVhscH/Q6/w4T95jFiGMx/ZhbVmS6qX6g/1XimwfHpo/jweBwsvr7DYD/Hsr8ByP0+f+s5NHI13v0MiTGkfX73Ezr+Xrb9bqT9jqav30sv9e0h/r0rX7brLNt1VbTdYNluqKLtUr89Vw3bGct2poq2s5btbBVtvzX1/NDG6Li9Ho4bnTf+Pb1oKzdm4N9L8fF7ts3B7Dd9jx6e3jY1ffh8irjA+rrFmgrmciO9hXQ1JNdSubRDV+/QNTp0zQ5di6WLNv4t2TaS20nuomN0lPEDedjf2irpgzfhAG9Ur1BX+Pch7N+l5++e9ZIO9pC/KZhfLxO9sNlxe2ugtBqTN6o0xRd5TPqYo/wPTM26w+w/MT117sDRw+H5U1PTYS48/ZP/D5w6NXXp8KH1IaedDycvnJ8Oz08fODcdHjk3NRnm1/Nx95lah0mSe86dO3AlPH760OHL4dSF6XDqSPj81IXTh85zoSOVFJqspNB0JYWuVVLoXZUUem8lhT5cSaGHOyoo9EQlhXZXUuhYJYU+VEmhb1ZS6HuVFPr3Sgr950oK/Y9KCg10VlDovkoKnTCFcKN9YHr68OSZ6XB6Kjxw6FB46fj0sXDq4uFzR37S/nC5rV0VGHuykkLnTKHh+YSTF05NHz9z6kppzCtdlbn3tkpI31OhsfdVYuylCo29Uomxb1VS6PVKCl2vpNBgdwWFbquk0DOVFLpYSaGPVlLo85UU+k4lha6bQnGrX01PBcYaF1oo+H/u5FNIVJ0DAA==","debug_symbols":"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bhTqRqFuFOpGoW406kajbjTqRqNuNOpGo2406kajbjTqRqNuDOrGoG4M6sagbgzqxqBuDOrGoG4M6sagbizqxqJuLOrGom4s6saibizqxqJuLOrGom4c6sahbhzqxqFuHOrGoW4c6sahbhzqxpFuxOOBUoZSjlKBUolShVKNUoNSi1KoG4a6YagbhrphqBuGumGoG4a6YagbhrphqBuOuuGoG4664agbjrrhqBuOuuGoG4664agbgboRqBuBuhGoG4G6EagbgboRqBuBuoFcNJCLBnLRQC4ayEUDuWggFw3kooFcNJCLBnLRQC4ayEUDuWggFw3kooFcNJCLBnLRQC4ayEUDuWggFw3kooFcNJCLBnLRQC4ayEUDuWggFw3kooFcNJCLBnLRQC4ayEUDuWggFw3kooFcNJCLBnLRQC4ayEUDuWggFw3kooFcNJCLBnLRQC4ayEUDuWggFw3kooFcNJCLBnLRQC4ayEUTuWgiF03koolcNJGLJnLRRC6ayEUTuWgiF03koolcNJGLJnLRRC6ayEUTuWgiF03koolcNJGLJnLRRC6ayEUTuWgiF03koolcNJGLJnLRRC6ayEUTuWgiF03koolcNJGLJnLRRC6ayEUTuWgiF03koolcNJGLJnLRRC6ayEUTuWgiF03koolcNJGLJnLRRC6ayEUTuWgiF03koolcNJGLJnLRRC6ayEUTuWgiF03koolcNJGLJnLRRC6ayEUTuWgiF03koolcNJGLJnLRRC6ayEUTuWgiF03koolcNJGLJnLRRC6ayEUTuWgiF03koolcNJGLJnLRRC6ayEUTuWgiF03koolctJCLFnLRQi5ayEULuWghFy3kooVctJCLFnLRQi5ayEULuWghFy3kooVctJCLFnLRQi5ayEULuWghFy3kooVctJCLFnLRQi5ayEULuWghFy3kooVctJCLFnLRQi5ayEULuWghFy3kooVctJCLFnLRQi5ayEULuWghFy3kooVctJCLFnLRQi5ayEULuWghFy3kooVctJCLFnLRQi5ayEULuWghFy3kooVctJCLFnLRQi5ayEULuWghFy3kooVctJCLFnLRQi5ayEULuWghFy3kooVctJCLFnLRQi5ayEULuWghFy3kooVctJCLFnLRQi5ayEULuWghFy3kooVctJCLFnLRQi5ayEUbuWgjF23koo1ctJGLNnLRRi7ayEUbuWgjF23koo1ctJGLNnLRRi7ayEUbuWgjF23koo1ctJGLNnLRRi7ayEUbuWgjF23koo1ctJGLNnLRRi7ayEUbuWgjF23koo1ctJGLNnLRRi7ayEUbuWgjF23koo1ctJGLNnLRRi7ayEUbuWgjF23koo1ctJGLNnLRRi7ayEUbuWgjF23koo1ctJGLNnLRRi7ayEUbuWgjF23koo1ctJGLNnLRRi7ayEUbuWgjF23koo1ctJGLNnLRRi7ayEUbuWgjF23koo1ctJGLNnLRRi7ayEUbuWgjF23koo1ctJGLNnLRRi7ayEUbuWgjF23koo1cdJCLDnLRQS46yEUHueggFx3kooNcdJCLDnLRQS46yEUHueggFx3kooNcdJCLDnLRQS46yEUHueggFx3kooNcdJCLDnLRQS46yEUHueggFx3kooNcdJCLDnLRQS46yEUHueggFx3kooNcdJCLDnLRQS46yEUHueggFx3kooNcdJCLDnLRQS46yEUHueggFx3kooNcdJCLDnLRQS46yEUHueggFx3kooNcdJCLDnLRQS46yEUHueggFx3kooNcdJCLDnLRQS46yEUHueggFx3kooNcdJCLDnLRQS46yEUHueggFx3kooNcdJCLDnLRQS46yEUHueggFx3kooNcdJCLDnLRQS46yEUXuegiF13kootcdJGLLnLRRS66yEUXuegiF13kootcdJGLLnLRRS66yEUXuegiF13kootcdJGLLnLRRS66yEUXuegiF13kootcdJGLLnLRRS66yEUXuegiF13kootcdJGLLnLRRS66yEUXuegiF13kootcdJGLLnLRRS66yEUXuegiF13kootcdJGLLnLRRS66yEUXuegiF13kootcdJGLLnLRRS66yEUXuegiF13kootcdJGLLnLRRS66yEUXuegiF13kootcdJGLLnLRRS66yEUXuegiF13kootcdJGLLnLRRS66yEUXuegiF13kootcdJGLLnLRRS66yEUXuegiF13kootc9JCLHnLRQy56yEUPueghFz3koodc9JCLHnLRQy56yEUPueghFz3koodc9JCLHnLRQy56yEUPueghFz3koodc9JCLHnLRQy56yEUPueghFz3koodc9JCLHnLRQy56yEUPueghFz3koodc9JCLHnLRQy56yEUPueghFz3koodc9JCLHnLRQy56yEUPueghFz3koodc9JCLHnLRQy56yEUPueghFz3koodc9JCLHnLRQy56yEXvtfZk9P0Sy3zM95w96nswabBosGlwaHBp8GDwNQH9TNBo0GmQNudoc44252hzjjbnaHOONccfjwcNGg06DQYNJg0WDTYNDg0uDdLmGG2O0eYYbY7R5hhtjtHmGG2O0eYYbY7R5jhtjtPmOG2O0+Y4bY7T5jhtjtPmOG2O0+YEbU7Q5gRtTtDmBG1O0OYEbU7Q5gRtTtDmJG1O0uYkbU7S5iRtTtLmJG1O0uYkbU7S5hRtTtHmFG1O0eYUbU7R5hRtTtHmFG1O0eY0bU7T5jRtTtPmNG1O0+Y0bU7T5jRtTtPmDG3O0OYMbc7Q5gxtztDmDG3O0OYMbc7Q5ixtztLmLG3O0uYsbc7S5ixtztLmLG3O0uYcbc7R5hxtztHmHG3O0eYcbc7R5hxtDjVko4Zs1JCNGrJRQzZqyEYN2aghGzVko4Zs1JCNGrJRQzZqyEYN2aghGzVko4Zs1JCNGrJRQzZqyEYN2aghGzVko4Zs1JCNGrJRQzZqyEYN2aghGzVko4Zs1JCNGrJRQzZqyEYN2aghGzVko4Zs1JCNGrJRQzZqyEYN2aghGzVko4Zs1JCNGrJRQzZqyEYN2aghGzVko4Zs1JCNGrJRQzZqyEYN2aghGzVko4Zs1JCNGrJRQzZqyEYN2aghGzVko4Zs1JCNGrJRQzZqyEYN2aghGzVko4Zs1JCNGrJRQzZqyEYN2aghGzVko4Zs1JCNGrJRQzZqyEYN2aghGzVko4Zs1JCNGrJRQ3ZqyE4N2akhOzVkp4bs1JCdGrJTQ3ZqyE4N2akhOzVkp4bs1JCdGrJTQ3ZqyE4N2akhOzVkp4bs1JCdGrJTQ3ZqyE4N2akhOzVkp4bs1JCdGrJTQ3ZqyE4N2akhOzVkp4bs1JCdGrJTQ3ZqyE4N2akhOzVkp4bs1JCdGrJTQ3ZqyE4N2akhOzVkp4bs1JCdGrJTQ3ZqyE4N2akhOzVkp4bs1JCdGrJTQ3ZqyE4N2akhOzVkp4bs1JCdGrJTQ3ZqyE4N2akhOzVkp4bs1JCdGrJTQ3ZqyE4N2akhOzVkp4bs1JCdGrJTQ3ZqyE4N2akhOzVkp4bs1JCdGrJTQ3ZqyE4N2akhOzXkoIYc1JCDGnJQQw5qyEENOaghBzXkoIYc1JCDGnJQQw5qyEENOaghBzXkoIYc1JCDGnJQQw5qyEENOaghBzXkoIYc1JCDGnJQQw5qyEENOaghBzXkoIYc1JCDGnJQQw5qyEENOaghBzXkoIYc1JCDGnJQQw5qyEENOaghBzXkoIYc1JCDGnJQQw5qyEENOaghBzXkoIYc1JCDGnJQQw5qyEENOaghBzXkoIYc1JCDGnJQQw5qyEENOaghBzXkoIYc1JCDGnJQQw5qyEENOaghBzXkoIYc1JCDGnJQQw5qyEENOaghBzXkoIYc1JCDGnJQQw5qyEENOaghBzXkoIYc1JCDGnJQQ05qyEkNOakhJzXkpIac1JCTGnJSQ05qyEkNOakhJzXkpIac1JCTGnJSQ05qyEkNOakhJzXkpIac1JCTGnJSQ05qyEkNOakhJzXkpIac1JCTGnJSQ05qyEkNOakhJzXkpIac1JCTGnJSQ05qyEkNOakhJzXkpIac1JCTGnJSQ05qyEkNOakhJzXkpIac1JCTGnJSQ05qyEkNOakhJzXkpIac1JCTGnJSQ05qyEkNOakhJzXkpIac1JCTGnJSQ05qyEkNOakhJzXkpIac1JCTGnJSQ05qyEkNOakhJzXkpIac1JCTGnJSQ05qyEkNOakhJzXkpIac1JCTGnJSQ05qyEkNOakhJzXkooZc1JCLGnJRQy5qyEUNuaghFzXkooZc1JCLGnJRQy5qyEUNuaghFzXkooZc1JCLGnJRQy5qyEUNuaghFzXkooZc1JCLGnJRQy5qyEUNuaghFzXkooZc1JCLGnJRQy5qyEUNuaghFzXkooZc1JCLGnJRQy5qyEUNuaghFzXkooZc1JCLGnJRQy5qyEUNuaghFzXkooZc1JCLGnJRQy5qyEUNuaghFzXkooZc1JCLGnJRQy5qyEUNuaghFzXkooZc1JCLGnJRQy5qyEUNuaghFzXkooZc1JCLGnJRQy5qyEUNuaghFzXkooZc1JCLGnJRQy5qyEUNuaghFzXkooZc1JCLGnJRQ25qyE0NuakhNzXkpobc1JCbGnJTQ25qyE0NuakhNzXkpobc1JCbGnJTQ25qyE0NuakhNzXkpobc1JCbGnJTQ25qyE0NuakhNzXkpobc1JCbGnJTQ25qyE0NuakhNzXkpobc1JCbGnJTQ25qyE0NuakhNzXkpobc1JCbGnJTQ25qyE0N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dwP6bkDfDei7AX03oO8G9N2AvhvQdwP6bkDfDei7AX03oO8G9N2AvhvQdwP6bkDfDei7AX03oO8G9N2AvhvQdwP6bkDfDei7AX03oO8G9N2AvhvQdwP6bkDfDei7AX03oO8G9N2AvhvQdwP6bkDfDei7AX03oO8G9N2AvhvQdxP6bkLfTei7CX03oe8m9N2EvpvQdxP6bkLfTei7CX03oe8m9N2EvpvQdxP6bkLfTei7CX03oe8m9N2EvpvQdxP6bkLfTei7CX03oe8m9N2EvpvQdxP6bkLfTei7CX03oe8m9N2EvpvQdxP6bkLfTei7CX03oe8m9N2EvpvQdxP6bkLfTei7CX03oe8m9N2EvpvQdxP6bkLfTei7CX03oe8m9N2EvpvQdxP6bkLfTei7CX03oe8m9N2EvpvQdxP6bkLfTei7CX03oe8m9N2EvpvQdxP6bkLfTei7CX03oe8m9N2EvpvQdxP6bkLfTei7CX03oe8m9N2EvpvQdxP6bkLfTei7CX23oO8W9N2CvlvQdwv6bkHfLei7BX23oO8W9N2CvlvQdwv6bkHfLei7BX23oO8W9N2CvlvQdwv6bkHfLei7BX23oO8W9N2CvlvQdwv6bkHfLei7BX23oO8W9N2CvlvQdwv6bkHfLei7BX23oO8W9N2CvlvQdwv6bkHfLei7BX23oO8W9N2CvlvQdwv6bkHfLei7BX23oO8W9N2CvlvQdwv6bkHfLei7BX23oO8W9N2CvlvQdwv6bkHfLei7BX23oO8W9N2CvlvQdwv6bkHfLei7BX23oO8W9N2CvlvQdwv6bkHfLei7BX23oO8W9N2CvlvQdwv6bkHfLei7BX23oO8W9N2CvlvQdxv6bkPfbei7DX23oe829N2GvtvQdxv6bkPfbei7DX23oe829N2GvtvQdxv6bkPfbei7DX23oe829N2GvtvQdxv6bkPfbei7DX23oe829N2GvtvQdxv6bkPfbei7DX23oe829N2GvtvQdxv6bkPfbei7DX23oe829N2GvtvQdxv6bkPfbei7DX23oe829N2GvtvQdxv6bkPfbei7DX23oe829N2GvtvQdxv6bkPfbei7DX23oe829N2GvtvQdxv6bkPfbei7DX23oe829N2GvtvQdxv6bkPfbei7DX23oe829N2GvtvQdxv6bkPfbei7DX23oe829N2GvtvQdxv6bkPfbei7DX13oO8O9N2BvjvQdwf67kDfHei7A313oO8O9N2BvjvQdwf67kDfHei7A313oO8O9N2BvjvQdwf67kDfHei7A313oO8O9N2BvjvQdwf67kDfHei7A313oO8O9N2BvjvQdwf67kDfHei7A313oO8O9N2BvjvQdwf67kDfHei7A313oO8O9N2BvjvQdwf67kDfHei7A313oO8O9N2BvjvQdwf67kDfHei7A313oO8O9N2BvjvQdwf67kDfHei7A313oO8O9N2BvjvQdwf67kDfHei7A313oO8O9N2BvjvQdwf67kDfHei7A313oO8O9N2BvjvQdwf67kDfHei7A313oO8O9N2BvjvQdxf67kLfXei7C313oe8u9N2FvrvQdxf67kLfXei7C313oe8u9N2FvrvQdxf67kLfXei7C313oe8u9N2FvrvQdxf67kLfXei7C313oe8u9N2FvrvQdxf67kLfXei7C313oe8u9N2FvrvQdxf67kLfXei7C313oe8u9N2FvrvQdxf67kLfXei7C313oe8u9N2FvrvQdxf67kLfXei7C313oe8u9N2FvrvQdxf67kLfXei7C313oe8u9N2FvrvQdxf67kLfXei7C313oe8u9N2FvrvQdxf67kLfXei7C313oe8u9N2FvrvQdxf67kLfXei7C313oe8u9N2FvrvQdxf67kLfXei7C333oO8e9N2DvnvQdw/67kHfPei7B333oO8e9N2DvnvQdw/67kHfPei7B333oO8e9N2DvnvQdw/67kHfPei7B333oO8e9N2DvnvQdw/67kHfPei7B333oO8e9N2DvnvQdw/67kHfPei7B333oO8e9N2DvnvQdw/67kHfPei7B333oO8e9N2DvnvQdw/67kHfPei7B333oO8e9N2DvnvQdw/67kHfPei7B333oO8e9N2DvnvQdw/67kHfPei7B333oO8e9N2DvnvQdw/67kHfPei7B333oO8e9N2DvnvQdw/67kHfPei7B333oO8e9N2DvnvQdw/67kHfPei7B333oO8e9N2DvnvMd/PBfPeZM5hzmAuYS5grmGuYG5hbmIN9MdgXg30x2BeDfTHYF4N9MdgXg30x2BeDfXHYF4d9cdgXh31x2BeHfXHYF4d9cdgXh30J2JeAfQnYl4B9CdiXgH0J2JeAfQnYl4B9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"},{"name":"compute_note_hash_and_nullifier","function_type":"Unconstrained","is_internal":false,"abi":{"parameters":[{"name":"contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":20,"type":{"kind":"field"}},"visibility":"private"}],"param_witnesses":{"contract_address":[{"start":0,"end":1}],"nonce":[{"start":1,"end":2}],"note_type_id":[{"start":3,"end":4}],"serialized_note":[{"start":4,"end":24}],"storage_slot":[{"start":2,"end":3}]},"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"},"return_witnesses":[24,25,26,27]},"bytecode":"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","debug_symbols":"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"},{"name":"constructor","function_type":"Secret","is_internal":false,"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":"storage_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress","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_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"is_contract_deployment","type":{"kind":"boolean"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"historical_header","type":{"kind":"struct","path":"aztec::protocol_types::header::Header","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":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"in_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"out_hash","type":{"kind":"array","length":2,"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":"contract_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":"timestamp","type":{"kind":"field"}},{"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":"contract_deployment_data","type":{"kind":"struct","path":"aztec::protocol_types::contrakt::contract_deployment_data::ContractDeploymentData","fields":[{"name":"public_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}]}},{"name":"initialization_hash","type":{"kind":"field"}},{"name":"contract_class_id","type":{"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"contract_address_salt","type":{"kind":"field"}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}}]}},{"name":"private_global_variables","type":{"kind":"struct","path":"aztec::context::globals::private_global_variables::PrivateGlobalVariables","fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}}]}}]},"visibility":"private"},{"name":"number","type":{"kind":"field"},"visibility":"private"},{"name":"owner","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]},"visibility":"private"}],"param_witnesses":{"inputs":[{"start":0,"end":41}],"number":[{"start":41,"end":42}],"owner":[{"start":42,"end":43}]},"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":"storage_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress","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_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"is_contract_deployment","type":{"kind":"boolean"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"args_hash","type":{"kind":"field"}},{"name":"return_values","type":{"kind":"array","length":4,"type":{"kind":"field"}}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"kind":"struct","path":"aztec::protocol_types::abis::side_effect::SideEffect","fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":2,"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_key_validation_requests","type":{"kind":"array","length":1,"type":{"kind":"struct","path":"aztec::protocol_types::abis::nullifier_key_validation_request::NullifierKeyValidationRequest","fields":[{"name":"public_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}]}},{"name":"secret_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_private_key::GrumpkinPrivateKey","fields":[{"name":"high","type":{"kind":"field"}},{"name":"low","type":{"kind":"field"}}]}}]}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"kind":"struct","path":"aztec::protocol_types::abis::side_effect::SideEffect","fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"kind":"struct","path":"aztec::protocol_types::abis::side_effect::SideEffectLinkedToNoteHash","fields":[{"name":"value","type":{"kind":"field"}},{"name":"note_hash","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}}},{"name":"private_call_stack_hashes","type":{"kind":"array","length":4,"type":{"kind":"field"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":4,"type":{"kind":"field"}}},{"name":"new_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":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"encrypted_logs_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"unencrypted_logs_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"encrypted_log_preimages_length","type":{"kind":"field"}},{"name":"unencrypted_log_preimages_length","type":{"kind":"field"}},{"name":"historical_header","type":{"kind":"struct","path":"aztec::protocol_types::header::Header","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":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"in_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"out_hash","type":{"kind":"array","length":2,"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":"contract_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":"timestamp","type":{"kind":"field"}},{"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":"contract_deployment_data","type":{"kind":"struct","path":"aztec::protocol_types::contrakt::contract_deployment_data::ContractDeploymentData","fields":[{"name":"public_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}]}},{"name":"initialization_hash","type":{"kind":"field"}},{"name":"contract_class_id","type":{"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"contract_address_salt","type":{"kind":"field"}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}}]}},{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}}]},"visibility":"public"},"return_witnesses":[67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284]},"bytecode":"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","debug_symbols":"3ZjdiloxEIDf5VyLzG8m8VVKL2xrQRB3WaVQxHdv/ElOtMG0R3A9Xu0emBm/TOYvs+tWb9/n2+XbetPNdh1iN/uy6zbv8/Xhc7Odf2y7GUy6xfpH/LufdD+Xq0U3E7ef/CWGGs6C6DGLIkpFlljsLEwCkqUJtGYZ0RIEYtS9kP866ZBGys2P4haPiVsF7+aWO7gVnDtLKoLLwq6KAkCJBKg4ZuCKtIQkrGQFNByhdYzQbozQVoMWTPEq4m+DUzBN4RqK4CY62fdV++qTfdPb9gMm88H1KAg2KBnCM9EQ3EmDIJx/AKDB84+R6CmVH8/lEU/IOD5kGh8yjw9ZbiMrhGYdSWWKAfHCfq25+765B9+Qbmei3knPkJ3D4Fr0YibpKj1QWewPMO6ZYOxumP5ekVo35SWxeN+jKNVCAEJqUlQa1loP9JbyIYDeFkXC5D0kpYuGNiS0/Es4MOTxBAFdw4NNn4SH+iTOUz7jhFB6JcIwfBpMdPs1DD4WhkgzTDHQVONFhFyeClWuCgXTaMn5weQhBwALN3JUCHKfE9coRuJTlVPuq5zJ8ZTyKqc0TCXOClmrvaVDXgHEMagsQzikbLG+igtdfhKak9suxJDfmtENdPF+HOJD9zJhaCm2PNh1stkzn1JTMSRn2DglW8jLg2ITYKfdwbSaEXmswKK/WTh1/ilW+y15zsOId3y9Rjjo4UC9amPSXERcMfNGdxwbwrS+KGBJbubizXG+cp7W3/MtJRyiREOU+L+VbFp/GSkn76nRVVQclNwQpWrOOIacZX2sWlSKH7/mH8v5t9XisBCPn9vf76d/938A"},{"name":"setNumber","function_type":"Secret","is_internal":false,"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":"storage_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress","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_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"is_contract_deployment","type":{"kind":"boolean"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"historical_header","type":{"kind":"struct","path":"aztec::protocol_types::header::Header","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":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"in_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"out_hash","type":{"kind":"array","length":2,"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":"contract_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":"timestamp","type":{"kind":"field"}},{"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":"contract_deployment_data","type":{"kind":"struct","path":"aztec::protocol_types::contrakt::contract_deployment_data::ContractDeploymentData","fields":[{"name":"public_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}]}},{"name":"initialization_hash","type":{"kind":"field"}},{"name":"contract_class_id","type":{"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"contract_address_salt","type":{"kind":"field"}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}}]}},{"name":"private_global_variables","type":{"kind":"struct","path":"aztec::context::globals::private_global_variables::PrivateGlobalVariables","fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}}]}}]},"visibility":"private"},{"name":"number","type":{"kind":"field"},"visibility":"private"},{"name":"owner","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]},"visibility":"private"}],"param_witnesses":{"inputs":[{"start":0,"end":41}],"number":[{"start":41,"end":42}],"owner":[{"start":42,"end":43}]},"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":"storage_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress","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_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"is_contract_deployment","type":{"kind":"boolean"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}},{"name":"args_hash","type":{"kind":"field"}},{"name":"return_values","type":{"kind":"array","length":4,"type":{"kind":"field"}}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"kind":"struct","path":"aztec::protocol_types::abis::side_effect::SideEffect","fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":2,"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_key_validation_requests","type":{"kind":"array","length":1,"type":{"kind":"struct","path":"aztec::protocol_types::abis::nullifier_key_validation_request::NullifierKeyValidationRequest","fields":[{"name":"public_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}]}},{"name":"secret_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_private_key::GrumpkinPrivateKey","fields":[{"name":"high","type":{"kind":"field"}},{"name":"low","type":{"kind":"field"}}]}}]}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"kind":"struct","path":"aztec::protocol_types::abis::side_effect::SideEffect","fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"kind":"struct","path":"aztec::protocol_types::abis::side_effect::SideEffectLinkedToNoteHash","fields":[{"name":"value","type":{"kind":"field"}},{"name":"note_hash","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}]}}},{"name":"private_call_stack_hashes","type":{"kind":"array","length":4,"type":{"kind":"field"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":4,"type":{"kind":"field"}}},{"name":"new_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":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"encrypted_logs_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"unencrypted_logs_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"encrypted_log_preimages_length","type":{"kind":"field"}},{"name":"unencrypted_log_preimages_length","type":{"kind":"field"}},{"name":"historical_header","type":{"kind":"struct","path":"aztec::protocol_types::header::Header","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":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"in_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"out_hash","type":{"kind":"array","length":2,"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":"contract_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":"timestamp","type":{"kind":"field"}},{"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":"contract_deployment_data","type":{"kind":"struct","path":"aztec::protocol_types::contrakt::contract_deployment_data::ContractDeploymentData","fields":[{"name":"public_key","type":{"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint","fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}]}},{"name":"initialization_hash","type":{"kind":"field"}},{"name":"contract_class_id","type":{"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId","fields":[{"name":"inner","type":{"kind":"field"}}]}},{"name":"contract_address_salt","type":{"kind":"field"}},{"name":"portal_contract_address","type":{"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress","fields":[{"name":"inner","type":{"kind":"field"}}]}}]}},{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}}]},"visibility":"public"},"return_witnesses":[110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327]},"bytecode":"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","debug_symbols":"7Z3RbtxGEkX/Rc9B0FVd1VWVX1nkwbubBQIESZAECywC//uObZFD2y2PfCS1R7KfbAG8U82e02TzsMn5++aX3/716q+ff/v1z5sf/r4RufnhH3/f/Pn7q1/f/PnnX6/++Ovmh/bdzU+//vv07+vvbv7z8y8/3fxg4/V3H20mXrcbSsq+qYhNttVucbuxWrN9a20++2SR2Bohcsq+t/2P392IPtN291XttpSt3W7y4HbbA9rtbYzbLV3a2Dce06a0pltLmh52s/pka6ttY9c4NLq9bbQ/x0aP59jomDV6jH4bGaWfbrhW+IZrHeBWfff5Ofv82NsfUp/+/JLt42vkeU9boMFQ19QabQ9sjTTre4HWLrTnniSmboef7MddfNdkeX5N1ufX5P78mmwXmuwXPr133w6AvR8OOjI97emI7YyqIeePdnnbGL+mxoy1jQnZpz0x7NiYjzc+gbS1YvQP2x1X3O7Ytk3RD9uda9udzbZ2p/VPt1uj63knzydLn523M7YxXG8qf2pTUdnGpqjreydhcmKqF9KFtU+qpMm40IeXeqW3a+6VOI+esuOevmm5PNuW67NtuV1xy7P2jUvt0riofRBpj2s9ZnX/Gvv7cQ9w46V0odq2sfRLHFrmdnls9tAevOK5R++m+0dHXdhTq/0Cwru/jCPEFc9qruTLedTDiV3xfOkJ+/tLHXvsiid5n9fdvm988ub90xuPsV/Bqj+0B696svmlLnusf+uVSa/Yt16Z9MrqSbi3fVIoF3ql2nnmcdrVfePxruXj2bb8wZ7O+nYd223UpZaf7lpuLRc7HHJ1Bkyv7aPF+rgwg3smdszyq+zwxz1Q1IvpwxfoUrx9+3aWXiq5fJ0d/qWulVxfSn9/9VbH+7ev8nodkNu3b+dqjZH71/nlfCm/5OPbhcODDyhf59Xu4/bhtwvYh/fhNV/A2nm5ube40Ifl+zKGGi2PdunjjWOf5+XBWuXbFQ/jmq8afV+iJ6PkoZPOcc3Xa4+8q9d8qfTIu3rNlxKPvKu2dlcj9xWyqfnpXX0mGnj4C+nCRz0vjsVz3Dw/5JVVx15505j4Yo2pwxNnt41ZPOsq2RGoUZ/mxSK2Q5Fl0+Mc4E3L67m2PB48JXHZji/do19oee4X8pl6YYS22oezHIfzdR3kQl5EBz7qIS50aZ9IG7k356NDXPQv1hgV/bAxtrYxqr43Zlw4JZrpxoCZ24cHCn+2LR+LW147AP24EGU6Rk33VQ5mly7mLbd2HJVp2Nu9jJeyl7FP+uOwbcyeBK99OiHy3gPsgg5b+VK6cOwPNB8fFJt2odS+f6duOJwOGzsd1ovB8PwE3cEQvRts2a55L/dlVjri0nVw3y+a/TBFsHj35Pv304P+Pq2Qw/ntdE/hxzcPuX4/f33F6bC8H6JT33t48TbWWcxYzFlssFiwWLJYodj8WfvLMWExRokySpRRoowSZZQoo0QZJcoo6YySzijpjJLOKOmMks4o6YySzijpjJLOKDFGiTFKjFFijBJjlBijxBglxigxRokxSpxR4owSZ5Q4o8QZJc4ocUaJM0qcUeKMksEoGYySwSgZjJLBKBmMksEoGYySwSgZjJJglASjJBglwSgJRkkwSoJREoySYJQEoyQZJckoSUZJMkqSUZKMkmSUJKMkGSXJKClGSTFKilFSjJJilBSjpBglxSgpRkkxSqQ1mBOYg2KtQbPWoFpr0K01KNcatGsN6rUGeRHIi0BeqIilJpaqWOpiqYylNpbqWOhjBQpZgUZWoJIV6GQFSlmBVlaglhXoZQWKWYFmVqCaFehmpdMbPZAXqGcF+lmBglagoRWoaAU6WoGSVqClFahpxeidQcgLNLUCVa1AVytQ1gq0tQJ1rUBfK1DYCjS2ApWtQGcrUNoKtLYCta1AbytQ3Ao0twLVrUB3K1DeyqBrDyAv0N8KFLgCDa5AhSvQ4QqUuAItrkCNK9DjStDFKpAXqHIFulyBMlegzRWocwX6XIFCV6DRFah0JenqJsgLtLoCta5ArytQ7Ao0uwLVrkC3K1DuCrS7UnQ5HF0PBxfEQb+r0O8q9LsK/a5Cv6vQ7yr0uwr9rkK/q0IXUEJeoN9V6HcV+l2Ffleh31XodxX6XaXrbemCW7ziFvJC19zSRbd01S1ddkvX3dKFt9DvKvS7Cv2udrpEG/IC/a5Cv6vQ7yr0uwr9rkK/q9DvKvS7Cv2uGl3TD3mBfleh31XodxX6XYV+V6HfVeh3FfpdhX5Xod/V+/jdmOUGzAXMJcwVy93H705zAnMKcx3mDOYgLwPyMiAvA/IyIC8BeQnIS0BeAvISkJeAvATkJSAvAXkJyEtCXhLykpCXhLwk5CUhLwl5SchLQl4S8lKQl4K8FOSlIC8FeSnIS0FeCvJSkJdivPT7+N1pTmBOYa7DnMGcw9yAuYC5hDnIi0Be7uF3D69xdZm+Y3l7s8SI84tfuu0l9OlL9KcvYU9e4h4O7f0SW05gTmGuw5zBnMPcgLmAuYS5YjmDvBjkxSAvBnkxyItBXgzyYpAXg7wY5GXu0E7qYnvbz2k2fX7NTpxzAnMKcx3mDOYc5gbMBcwlzBXLDcjLgLwMyMuAvAzIy4C8DMjLgLwMyMuAvATkJSAvAXkJyEtAXgLyEpCXgLwE5CUgLwl5SchLQl4S8pKQl4S8JOQlIS8JeUnIS0FeCvJSkJeCvBTkpSAvBXkpyEtBXorxYq3BnMCcwlyHOYM5h7kBcwFzCXOQF4G8CORFIC8CeRHIi0BeBPIikBeBvAjkRSEvCnlRyItCXhTyopAXhbwo5EUhLwp56ZCXDnnpkJcOeemQlw556ZCXDnnpkJcOeTHIi0FeDPJikBeDvBjkxSAvBnkxyItBXqDfNeh3Dfpdg37XoN816HcN+l2Dfteg3zXodw36XYN+16DfNeh3Dfpdg37XoN816HcN+l2Dfteg3zXodw36XYN+16DfNeh3Dfpdg37XoN816HcN+l2Dfteg3zXodw36XYN+16DfNeh3Dfpdg37XoN816HcN+l2Dfteg3zXodw36XYN+16DfNeh3Hfpdh37Xod916Hcd+l2Hfteh33Xodx36XYd+16Hfdeh3Hfpdh37Xod916Hcd+l2Hfteh33Xodx36XYd+16Hfdeh3Hfpdh37Xod916Hcd+l2Hfteh33Xodx36XYd+16Hfdeh3Hfpdh37Xod916Hcd+l2Hfteh3/U7/G61/Qcrq9UsZzDnMDdgLmAuYa5Y7g6/e8wdfh37kBOYU5i7g5c452K6fwZzDnMD5gLmEuaK5e7wu7X/Xmtv6rOcwJzBnMPctD97te3HuU//nfE595+Xc3P/eY+cwJzC3LxfWq+9Pw+/pXzOzb1b7/tPXvdus+9h7t3ukeswZzDnMDdgLmBu/v2djrYXcsVyc+92j5zAnMJchzmDuTt4iXOu2iw3YC5gLmGuUG7Mvds9cnNerG/nsW6z72HMvds9ch3mDOYc5gbMBczNebH9OqAff4D+kCuWm3u3e+QE5hTmOszZxZzbLOcwN2Buzss4n4+G1iyXMFcsN/du98gJzCnMdZgzmJvzcppH7bn+3nH340fQRWybPJ7+e4ZZW9urjCVVYkmVXFKlVlSZ28VHryJLquiSKn1JFVtSZcnY70vGfl8y9vuSsd+XjH1bMvZtydi3JWPflox9WzL2bcnYtyVj35aMfVsy9m3J2PclY98fTrK3zS+e7tTvm0rVXsMX1Hj4N3+6P7rV6DatUU9fY7QFNWRBDV1Q43OP9VvOYM5hbsDcHdftvvv8aPLpPqy2XVuWntW/6j7+77iX8rg16ulr3HGP5nFryIIauqBGX1DDHl5jbPcBK8e0hi+oMRbUiAU1ckGNevoa2RbUePg4lybbwV1al2kVXVKlL6liS6r4kipjSZVYUuVzR/2WK5arBnMCcwpzHeYM5hzmBswFzEFeivESrcGcwJzCXIc5gzmHuQFzAXMJc3Nesu93wnLUhaOfyL4OTkQPV4jafKtzxx3ox68ji+roojp9UR1bVMcX1RmfWWfLBcwlzBXLaYM5thIyVGGuw5zBnMPcgLmAuYQ5tnI2eoM5yEuHvHTIS4e8dMhLh7x0yEuHvHTIi0FeDPJikBeDvBjkxSAvBnkxyItBXgzy4pAXh7w45MUhLw55cciLQ14c8uKQF4e8DMjLgLwMyMuAvAzIy4C8DMjLgLzAJ38CPvkT8MmfgE/+BHzyJwLyEpCXgLwE5CUgLwF5CchLQl4S8pKQl4S8JOQlIS8JeUnIS0JeEvJSkJeCvBTkpSAvBXkpyEtBXgryUpCXYrxkazAnMKcw12HOYM5hbsBcwFzCHORFIC8CeRHIi0BeBPIikBeBvAjkRSAvAnlRyAv0uwn9bkK/m9DvJvS7Cf1uQr+b0O8m9LsJ/W5Cv5vQ7yb0uwn9bkK/m9DvJvS7Cf1uQr+b0O8m9LsJ/W5Cv5vQ7yb0uwn9bkK/m9DvJvS7Cf1uQr+b0O8m9LsJ/W5Cv5vQ7yb0uwn9bkK/m9DvJvS7Cf1uQr+b0O8m9LsJ/W5Cv5vQ7yb0uwn9bkK/m9DvJvS7Cf1uQr+b0O8m9LsJ/W5Cv5vQ7yb0uwn9bkK/m9DvJvS7Cf1uQr+b0O8m9LsJ/W5Cv5vQ7yb0uwn9bkK/m9DvJvS7Cf1uQr9b0O8W9LsF/W5Bv1vQ7xb0uwX9bkG/W9DvFvS7Bf1uQb9b0O8W9LsF/W5Bv1vQ7xb0uwX9bkG/W9DvFvS7Bf1uQb9b0O8W9LsF/W5Bv1vQ7xb0uwX9bkG/W9DvFvS7Bf1uQb9b0O8W9LsF/W5Bv1vQ7xb0uwX9bkG/W9DvFvS7Bf1uQb9b0O8W9LsF/W5Bv1vQ7xb0uwX9bkG/W9DvFvS7Bf1uQb9b0O8W9LsF/W5Bv1vQ7xb0uwX9bkG/W9DTFvS0FQ9/G9ylN0/VHY71cWv4ghpjQY1YUOMR3gRmutU4/GDCsUY9fY1sC2rIghq6oEZfUOMRxnnPvUaf1vAFNcaCGrGgRi6oUU9fo57+jX9VsqCGLqjRF9SwBTV8QY2xoEYsqJELajz9mz2ltbaiiKwooiuK9BVFbEURX1FkrCgSK4rkiiIrRrysGPGyYsTLihEvK0a8rBjxsmLEy4oRLytGvKwY8bJixOuKEa8rRryuGPG6YsTrihGvK0b8/PbvPXLFcvPbvzJk3AZlWLz+SLu+eRspDSoNdho0GnQaHDQYNJg0WDBolByj5Ngd5Pj+jtxSmQY7DRoNOg0OGozPD3p9P5+/2tje9uftbEqzbyEhISWhTkJGQk5Cg4Sm39T5NOI1CyUJFQjN5zeXQkJCSkKdhKZEeMVtaBxuLZ5DTkKDhIKEkoQKhOZzhEuhKRHD99CYhZSEOgkZCTkJDRIKEpoSMWIbGiMnQ2N+/r8Qmp/7L4WEhJSEOgnZ54bG+H76NWXf7jNm5gen3NA7TrmafbvrrTnOt5FuX/X/JicwNz/M7j9JOw4nqdtGjjtOHd22O129Dntmt6E7Lo0vhISElIT654ay3XUW2F+H7HHuvdO09TY0SGg+5vef/M7je9ZPodMf/331x8+v/vnLT3+eAqc///rf7+/++/r/"}],"events":[],"file_map":{"3":{"source":"struct BoundedVec {\n storage: [T; MaxLen],\n len: u64,\n}\n\nimpl BoundedVec {\n pub fn new() -> Self {\n let zeroed = crate::unsafe::zeroed();\n BoundedVec { storage: [zeroed; MaxLen], len: 0 }\n }\n\n pub fn get(mut self: Self, index: u64) -> T {\n assert(index as u64 < self.len);\n self.storage[index]\n }\n\n pub fn get_unchecked(mut self: Self, index: u64) -> T {\n self.storage[index]\n }\n\n pub fn push(&mut self, elem: T) {\n assert(self.len < MaxLen as u64, \"push out of bounds\");\n\n self.storage[self.len] = elem;\n self.len += 1;\n }\n\n pub fn len(self) -> u64 {\n self.len\n }\n\n pub fn max_len(_self: BoundedVec) -> u64 {\n MaxLen\n }\n\n // This is a intermediate method, while we don't have an\n // .extend method\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n pub fn extend_from_array(&mut self, array: [T; Len]) {\n let new_len = self.len + array.len();\n assert(new_len as u64 <= MaxLen as u64, \"extend_from_array out of bounds\");\n for i in 0..array.len() {\n self.storage[self.len + i] = array[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) {\n let append_len = vec.len();\n let new_len = self.len + append_len;\n assert(new_len as u64 <= MaxLen as u64, \"extend_from_bounded_vec out of bounds\");\n\n let mut exceeded_len = false;\n for i in 0..Len {\n exceeded_len |= i == append_len;\n if !exceeded_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n }\n self.len = new_len;\n }\n\n pub fn pop(&mut self) -> T {\n assert(self.len as u64 > 0);\n self.len -= 1;\n\n let elem = self.storage[self.len];\n self.storage[self.len] = crate::unsafe::zeroed();\n elem\n }\n\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n let mut exceeded_len = false;\n for i in 0..MaxLen {\n exceeded_len |= i == self.len;\n if !exceeded_len {\n ret |= predicate(self.storage[i]);\n }\n }\n ret\n }\n}\n","path":"std/collections/bounded_vec.nr"},"34":{"source":"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::unsafe::zeroed() }\n }\n\n /// Constructs a Some wrapper around the given value\n pub fn some(_value: T) -> Self {\n Self { _is_some: true, _value }\n }\n\n /// True if this Option is None\n pub fn is_none(self) -> bool {\n !self._is_some\n }\n\n /// True if this Option is Some\n pub fn is_some(self) -> bool {\n self._is_some\n }\n\n /// Asserts `self.is_some()` and returns the wrapped value.\n pub fn unwrap(self) -> T {\n assert(self._is_some);\n self._value\n }\n\n /// Returns the inner value without asserting `self.is_some()`\n /// Note that if `self` is `None`, there is no guarantee what value will be returned,\n /// only that it will be of type `T`.\n pub fn unwrap_unchecked(self) -> T {\n self._value\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value.\n pub fn unwrap_or(self, default: T) -> T {\n if self._is_some { self._value } else { default }\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return\n /// a default value.\n pub fn unwrap_or_else(self, default: fn[Env]() -> T) -> T {\n if self._is_some {\n self._value\n } else {\n default()\n }\n }\n\n /// Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value\n fn expect(self, message: fmtstr) -> T {\n assert(self.is_some(), message);\n self._value\n }\n\n /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`.\n pub fn map(self, f: fn[Env](T) -> U) -> Option {\n if self._is_some {\n Option::some(f(self._value))\n } else {\n Option::none()\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value.\n pub fn map_or(self, default: U, f: fn[Env](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`.\n pub fn map_or_else(self, default: fn[Env1]() -> U, f: fn[Env2](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default()\n }\n }\n\n /// Returns None if self is None. Otherwise, this returns `other`.\n pub fn and(self, other: Self) -> Self {\n if self.is_none() {\n Option::none()\n } else {\n other\n }\n }\n\n /// If self is None, this returns None. Otherwise, this calls the given function\n /// with the Some value contained within self, and returns the result of that call.\n ///\n /// In some languages this function is called `flat_map` or `bind`.\n pub fn and_then(self, f: fn[Env](T) -> Option) -> Option {\n if self._is_some {\n f(self._value)\n } else {\n Option::none()\n }\n }\n\n /// If self is Some, return self. Otherwise, return `other`.\n pub fn or(self, other: Self) -> Self {\n if self._is_some { self } else { other }\n }\n\n /// If self is Some, return self. Otherwise, return `default()`.\n pub fn or_else(self, default: fn[Env]() -> Self) -> Self {\n if self._is_some { self } else { default() }\n }\n\n // If only one of the two Options is Some, return that option.\n // Otherwise, if both options are Some or both are None, None is returned.\n pub fn xor(self, other: Self) -> Self {\n if self._is_some {\n if other._is_some { Option::none() } else { self }\n } else if other._is_some {\n other\n } else {\n Option::none()\n }\n }\n\n /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true.\n /// Otherwise, this returns `None`\n pub fn filter(self, predicate: fn[Env](T) -> bool) -> Self {\n if self._is_some {\n if predicate(self._value) {\n self\n } else {\n Option::none()\n }\n } else {\n Option::none()\n }\n }\n\n /// Flattens an Option> into a Option.\n /// This returns None if the outer Option is None. Otherwise, this returns the inner Option.\n pub fn flatten(option: Option>) -> Option {\n if option._is_some {\n option._value\n } else {\n Option::none()\n }\n }\n}\n","path":"std/option.nr"},"46":{"source":"contract BoxReact {\n use dep::aztec::prelude::{AztecAddress, PrivateMutable, Map, NoteInterface, NoteHeader};\n\n use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN};\n\n struct Storage {\n numbers: Map>,\n }\n\n #[aztec(private)]\n fn constructor(number: Field, owner: AztecAddress) {\n let numbers = storage.numbers;\n let mut new_number = ValueNote::new(number, owner);\n numbers.at(owner).initialize(&mut new_number, true);\n }\n\n #[aztec(private)]\n fn setNumber(number: Field, owner: AztecAddress) {\n let numbers = storage.numbers;\n let mut new_number = ValueNote::new(number, owner);\n numbers.at(owner).replace(&mut new_number, true);\n }\n\n unconstrained fn getNumber(owner: AztecAddress) -> pub ValueNote {\n let numbers = storage.numbers;\n numbers.at(owner).view_note()\n }\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/boxes/boxes/react/src/contracts/src/main.nr"},"47":{"source":"use crate::context::{PrivateContext, PublicContext};\nuse crate::oracle;\nuse dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint};\n\npub fn emit_encrypted_log(\n context: &mut PrivateContext,\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n encryption_pub_key: GrumpkinPoint,\n log: [Field; N]\n) {\n let _ = oracle::logs::emit_encrypted_log(\n contract_address,\n storage_slot,\n note_type_id,\n encryption_pub_key,\n log\n );\n context.accumulate_encrypted_logs(log);\n}\n\npub fn emit_unencrypted_log(context: &mut PublicContext, log: T) {\n let contract_address = context.this_address();\n let event_selector = 5; // TODO: compute actual event selector.\n let _ = oracle::logs::emit_unencrypted_log(contract_address, event_selector, log);\n // context.accumulate_unencrypted_logs(log);\n}\n\n// TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n// --> might be a better approach to force devs to make a public function call that emits the log if needed then\n// it would be less easy to accidentally leak information.\n// If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\npub fn emit_unencrypted_log_from_private(context: &mut PrivateContext, log: T) {\n let contract_address = context.this_address();\n let event_selector = 5; // TODO: compute actual event selector.\n let _ = oracle::logs::emit_unencrypted_log(contract_address, event_selector, log);\n // context.accumulate_unencrypted_logs(log);\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/aztec-nr/aztec/src/log.nr"},"51":{"source":"use dep::protocol_types::{\n constants::{\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, GET_NOTE_ORACLE_RETURN_LENGTH, GET_NOTES_ORACLE_RETURN_LENGTH,\n MAX_NOTES_PER_PAGE, VIEW_NOTE_ORACLE_RETURN_LENGTH\n}\n};\nuse crate::context::PrivateContext;\nuse crate::note::{\n note_getter_options::{NoteGetterOptions, Select, Sort, SortOrder, Comparator, NoteStatus},\n note_interface::NoteInterface, note_viewer_options::NoteViewerOptions,\n utils::compute_note_hash_for_consumption\n};\nuse crate::oracle;\n\nfn check_note_header(context: PrivateContext, storage_slot: Field, note: Note) where Note: NoteInterface {\n let header = note.get_header();\n let contract_address = context.this_address();\n assert(header.contract_address.eq(contract_address));\n assert(header.storage_slot == storage_slot);\n}\n\nfn check_note_fields(fields: [Field; N], selects: BoundedVec, N>) {\n for i in 0..selects.len {\n let select = selects.get_unchecked(i).unwrap_unchecked();\n\n // Values are computed ahead of time because circuits evaluate all branches\n let isEqual = fields[select.field_index] == select.value;\n let isLt = fields[select.field_index].lt(select.value);\n\n if (select.comparator == Comparator.EQ) {\n assert(isEqual, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.NEQ) {\n assert(!isEqual, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.LT) {\n assert(isLt, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.LTE) {\n assert(isLt | isEqual, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.GT) {\n assert(!isLt & !isEqual, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.GTE) {\n assert(!isLt, \"Mismatch return note field.\");\n }\n }\n}\n\nfn check_notes_order(\n fields_0: [Field; N],\n fields_1: [Field; N],\n sorts: BoundedVec, N>\n) {\n for i in 0..sorts.len {\n let sort = sorts.get_unchecked(i).unwrap_unchecked();\n let eq = fields_0[sort.field_index] == fields_1[sort.field_index];\n let lt = fields_0[sort.field_index].lt(fields_1[sort.field_index]);\n if sort.order == SortOrder.ASC {\n assert(eq | lt, \"Return notes not sorted in ascending order.\");\n } else if !eq {\n assert(!lt, \"Return notes not sorted in descending order.\");\n }\n }\n}\n\npub fn get_note(\n context: &mut PrivateContext,\n storage_slot: Field\n) -> Note where Note: NoteInterface {\n let note = get_note_internal(storage_slot);\n\n check_note_header(*context, storage_slot, note);\n\n let note_hash_for_read_request = compute_note_hash_for_consumption(note);\n\n context.push_note_hash_read_request(note_hash_for_read_request);\n note\n}\n\npub fn get_notes(\n context: &mut PrivateContext,\n storage_slot: Field,\n options: NoteGetterOptions\n) -> [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] where Note: NoteInterface {\n let opt_notes = get_notes_internal(storage_slot, options);\n let mut num_notes = 0;\n let mut prev_fields = [0; N];\n for i in 0..opt_notes.len() {\n let opt_note = opt_notes[i];\n if opt_note.is_some() {\n let note = opt_note.unwrap_unchecked();\n let fields = note.serialize_content();\n check_note_header(*context, storage_slot, note);\n check_note_fields(fields, options.selects);\n if i != 0 {\n check_notes_order(prev_fields, fields, options.sorts);\n }\n prev_fields = fields;\n\n let note_hash_for_read_request = compute_note_hash_for_consumption(note);\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1410): test to ensure\n // failure if malicious oracle injects 0 nonce here for a \"pre-existing\" note.\n context.push_note_hash_read_request(note_hash_for_read_request);\n\n num_notes += 1;\n };\n }\n if options.limit != 0 {\n assert(num_notes <= options.limit, \"Invalid number of return notes.\");\n }\n opt_notes\n}\n\nunconstrained fn get_note_internal(storage_slot: Field) -> Note where Note: NoteInterface {\n let placeholder_note = [Option::none()];\n let placeholder_fields = [0; GET_NOTE_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n oracle::notes::get_notes(\n storage_slot,\n 0,\n [],\n [],\n [],\n [],\n [],\n 1, // limit\n 0, // offset\n NoteStatus.ACTIVE,\n placeholder_note,\n placeholder_fields,\n placeholder_note_length\n )[0].unwrap() // Notice: we don't allow dummies to be returned from get_note (singular).\n}\n\nunconstrained fn get_notes_internal(\n storage_slot: Field,\n options: NoteGetterOptions\n) -> [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] where Note: NoteInterface {\n let (num_selects, select_by, select_values, select_comparators, sort_by, sort_order) = flatten_options(options.selects, options.sorts);\n let placeholder_opt_notes = [Option::none(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL];\n let placeholder_fields = [0; GET_NOTES_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n let opt_notes = oracle::notes::get_notes(\n storage_slot,\n num_selects,\n select_by,\n select_values,\n select_comparators,\n sort_by,\n sort_order,\n options.limit,\n options.offset,\n options.status,\n placeholder_opt_notes,\n placeholder_fields,\n placeholder_note_length\n );\n\n let filter = options.filter;\n let filter_args = options.filter_args;\n filter(opt_notes, filter_args)\n}\n\nunconstrained pub fn view_notes(\n storage_slot: Field,\n options: NoteViewerOptions\n) -> [Option; MAX_NOTES_PER_PAGE] where Note: NoteInterface {\n let (num_selects, select_by, select_values, select_comparators, sort_by, sort_order) = flatten_options(options.selects, options.sorts);\n let placeholder_opt_notes = [Option::none(); MAX_NOTES_PER_PAGE];\n let placeholder_fields = [0; VIEW_NOTE_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n oracle::notes::get_notes(\n storage_slot,\n num_selects,\n select_by,\n select_values,\n select_comparators,\n sort_by,\n sort_order,\n options.limit,\n options.offset,\n options.status,\n placeholder_opt_notes,\n placeholder_fields,\n placeholder_note_length\n )\n}\n\nunconstrained fn flatten_options(\n selects: BoundedVec, N>,\n sorts: BoundedVec, N>\n) -> (u8, [u8; N], [Field; N], [u8; N], [u8; N], [u8; N]) {\n let mut num_selects = 0;\n let mut select_by = [0; N];\n let mut select_values = [0; N];\n let mut select_comparators = [0; N];\n\n for i in 0..selects.len {\n let select = selects.get(i);\n if select.is_some() {\n select_by[num_selects] = select.unwrap_unchecked().field_index;\n select_values[num_selects] = select.unwrap_unchecked().value;\n select_comparators[num_selects] = select.unwrap_unchecked().comparator;\n num_selects += 1;\n };\n }\n\n let mut sort_by = [0; N];\n let mut sort_order = [0; N];\n for i in 0..sorts.len {\n let sort = sorts.get(i);\n if sort.is_some() {\n sort_by[i] = sort.unwrap_unchecked().field_index;\n sort_order[i] = sort.unwrap_unchecked().order;\n };\n }\n\n (num_selects, select_by, select_values, select_comparators, sort_by, sort_order)\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/aztec-nr/aztec/src/note/note_getter.nr"},"52":{"source":"use crate::context::{PrivateContext, PublicContext};\nuse crate::note::{\n note_header::NoteHeader, note_interface::NoteInterface,\n utils::{compute_note_hash_for_insertion, compute_note_hash_for_consumption}\n};\nuse crate::oracle::notes::{notify_created_note, notify_nullified_note};\n\npub fn create_note(\n context: &mut PrivateContext,\n storage_slot: Field,\n note: &mut Note,\n broadcast: bool\n) where Note: NoteInterface {\n let contract_address = (*context).this_address();\n\n let header = NoteHeader { contract_address, storage_slot, nonce: 0, is_transient: true };\n // TODO: change this to note.setHeader(header) once https://github.com/noir-lang/noir/issues/4095 is fixed\n Note::set_header(note, header);\n // As `is_transient` is true, this will compute the inner note hsah\n let inner_note_hash = compute_note_hash_for_insertion(*note);\n\n // TODO: Strong typing required because of https://github.com/noir-lang/noir/issues/4088\n let serialized_note: [Field; N] = Note::serialize_content(*note);\n assert(\n notify_created_note(\n storage_slot,\n Note::get_note_type_id(),\n serialized_note,\n inner_note_hash\n )\n == 0\n );\n\n context.push_new_note_hash(inner_note_hash);\n\n if broadcast {\n Note::broadcast(*note, context, storage_slot);\n }\n}\n\npub fn create_note_hash_from_public(\n context: &mut PublicContext,\n storage_slot: Field,\n note: &mut Note\n) where Note: NoteInterface {\n let contract_address = (*context).this_address();\n\n let header = NoteHeader { contract_address, storage_slot, nonce: 0, is_transient: true };\n // TODO: change this to note.setHeader(header) once https://github.com/noir-lang/noir/issues/4095 is fixed\n Note::set_header(note, header);\n let inner_note_hash = compute_note_hash_for_insertion(*note);\n\n context.push_new_note_hash(inner_note_hash);\n}\n\npub fn destroy_note(context: &mut PrivateContext, note: Note) where Note: NoteInterface {\n let mut nullifier = 0;\n let mut consumed_note_hash: Field = 0;\n nullifier = note.compute_nullifier(context);\n\n // We also need the note hash corresponding to the \"nullifier\"\n let header = note.get_header();\n // `consumed_note_hash` is used to inform the kernel which pending note hash\n // the nullifier corresponds to so they can be matched and both squashed/deleted.\n // nonzero nonce implies \"persistable\" nullifier (nullifies a persistent/in-tree\n // note hash) in which case `consumed_note_hash` is not used since the kernel\n // just siloes and forwards the nullifier to its output.\n if (header.is_transient) {\n // TODO(1718): Can we reuse the note hash computed in `compute_nullifier`?\n consumed_note_hash = compute_note_hash_for_consumption(note);\n }\n assert(notify_nullified_note(nullifier, consumed_note_hash) == 0);\n\n context.push_new_nullifier(nullifier, consumed_note_hash)\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr"},"53":{"source":"use crate::{context::PrivateContext, note::{note_header::NoteHeader, note_interface::NoteInterface}};\n\nuse dep::protocol_types::{\n address::AztecAddress,\n constants::{GENERATOR_INDEX__OUTER_NULLIFIER, GENERATOR_INDEX__UNIQUE_NOTE_HASH, GENERATOR_INDEX__SILOED_NOTE_HASH},\n hash::pedersen_hash, utils::arr_copy_slice\n};\n\nfn compute_siloed_hash(contract_address: AztecAddress, inner_note_hash: Field) -> Field {\n let inputs = [contract_address.to_field(), inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__SILOED_NOTE_HASH)\n}\n\nfn compute_unique_hash(nonce: Field, siloed_note_hash: Field) -> Field {\n let inputs = [nonce, siloed_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\nfn compute_inner_note_hash(note: Note) -> Field where Note: NoteInterface {\n let header = note.get_header();\n let note_hash = note.compute_note_content_hash();\n\n // TODO(#1205) Do we need a generator index here?\n pedersen_hash([header.storage_slot, note_hash], 0)\n}\n\nfn compute_siloed_note_hash(note_with_header: Note) -> Field where Note: NoteInterface {\n let header = note_with_header.get_header();\n\n let inner_note_hash = compute_inner_note_hash(note_with_header);\n\n compute_siloed_hash(header.contract_address, inner_note_hash)\n}\n\nfn compute_unique_siloed_note_hash(note_with_header: Note) -> Field where Note: NoteInterface {\n let header = note_with_header.get_header();\n\n let siloed_note_hash = compute_siloed_note_hash(note_with_header);\n\n compute_unique_hash(header.nonce, siloed_note_hash)\n}\n\npub fn compute_siloed_nullifier(\n note_with_header: Note,\n context: &mut PrivateContext\n) -> Field where Note: NoteInterface {\n let header = note_with_header.get_header();\n let inner_nullifier = note_with_header.compute_nullifier(context);\n\n let input = [header.contract_address.to_field(), inner_nullifier];\n pedersen_hash(input, GENERATOR_INDEX__OUTER_NULLIFIER)\n}\n\npub fn compute_note_hash_for_insertion(note: Note) -> Field where Note: NoteInterface {\n compute_inner_note_hash(note)\n}\n\npub fn compute_note_hash_for_consumption(note: Note) -> Field where Note: NoteInterface {\n let header = note.get_header();\n // There are 3 cases for reading a note intended for consumption:\n // 1. The note was inserted in this transaction, and is transient.\n // 2. The note was inserted in a previous transaction, and was inserted in public\n // 3. The note was inserted in a previous transaction, and was inserted in private\n\n if (header.is_transient) {\n // If a note is transient, we just read the inner_note_hash (kernel will silo by contract address).\n compute_inner_note_hash(note)\n } else if (header.nonce == 0) {\n // If not transient and nonce is zero, that means we are reading a public note.\n compute_siloed_note_hash(note)\n } else {\n // When nonce is nonzero, that means we are reading a settled note (from tree) created in a\n // previous TX. So we need the unique_siloed_note_hash which has already been hashed with\n // contract address and then nonce. This hash will match the existing leaf in the private\n // data tree, so the kernel can just perform a membership check directly on this hash/leaf.\n compute_unique_siloed_note_hash(note)\n // IMPORTANT NOTE ON REDUNDANT SILOING BY CONTRACT ADDRESS: The note hash computed above is\n // \"siloed\" by contract address. When a note hash is computed solely for the purpose of\n // nullification, it is not strictly necessary to silo the note hash before computing\n // its nullifier. In other words, it is NOT NECESSARY for protocol security that a nullifier\n // be computed from a siloed note hash. After all, persistable note hashes and nullifiers are\n // siloed by the kernel circuit. That being said, the siloed note hash computed above CAN be\n // used for nullifier computation, and this achieves the (arguably unnecessary) property that\n // nullifiers are computed from a note hash's fully-computed private data tree leaf.\n }\n}\n\npub fn compute_note_hash_and_nullifier(\n // docs:start:compute_note_hash_and_nullifier_args\n deserialize_content: fn([Field; N]) -> T,\n note_header: NoteHeader,\n serialized_note: [Field; S] // docs:end:compute_note_hash_and_nullifier_args\n) -> [Field; 4] where T: NoteInterface {\n let mut note = deserialize_content(arr_copy_slice(serialized_note, [0; N], 0));\n // TODO: change this to note.setHeader(header) once https://github.com/noir-lang/noir/issues/4095 is fixed\n T::set_header((&mut note), note_header);\n\n let inner_note_hash = compute_inner_note_hash(note);\n\n let siloed_note_hash = compute_siloed_hash(note_header.contract_address, inner_note_hash);\n\n let unique_siloed_note_hash = compute_unique_hash(note_header.nonce, siloed_note_hash);\n\n let inner_nullifier = note.compute_nullifier_without_context();\n // docs:start:compute_note_hash_and_nullifier_returns\n [inner_note_hash, siloed_note_hash, unique_siloed_note_hash, inner_nullifier]\n // docs:end:compute_note_hash_and_nullifier_returns\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/aztec-nr/aztec/src/note/utils.nr"},"65":{"source":"use crate::{\n context::{inputs::PrivateContextInputs, interface::ContextInterface},\n key::nullifier_key::validate_nullifier_key_against_address, messaging::process_l1_to_l2_message,\n oracle::{\n arguments, call_private_function::call_private_function_internal,\n enqueue_public_function_call::enqueue_public_function_call_internal, context::get_portal_address,\n header::get_header_at, nullifier_key::{get_nullifier_key_pair, NullifierKeyPair},\n debug_log::debug_log\n}\n};\nuse dep::protocol_types::{\n abis::{\n call_context::CallContext, function_data::FunctionData, function_selector::FunctionSelector,\n nullifier_key_validation_request::NullifierKeyValidationRequest,\n private_call_stack_item::PrivateCallStackItem,\n private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem,\n public_circuit_public_inputs::PublicCircuitPublicInputs, read_request::ReadRequest,\n side_effect::{SideEffect, SideEffectLinkedToNoteHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, NUM_FIELDS_PER_SHA256, RETURN_VALUES_LENGTH\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, hash::hash_args, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::is_empty\n};\n\n// TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165)\n// use dep::std::collections::vec::Vec;\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n\n args_hash : Field,\n return_values : BoundedVec,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n nullifier_key_validation_requests: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_stack_hashes : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165)\n // encrypted_logs_preimages: Vec,\n // unencrypted_logs_preimages: Vec,\n\n nullifier_key: Option,\n}\n\nimpl ContextInterface for PrivateContext {\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn this_portal_address(self) -> EthAddress {\n self.inputs.call_context.portal_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.private_global_variables.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.private_global_variables.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\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_header(self) -> Header {\n self.historical_header\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n let side_effect = SideEffect { value: note_hash, counter: self.side_effect_counter };\n self.new_note_hashes.push(side_effect);\n self.side_effect_counter = self.side_effect_counter + 1;\n }\n\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_commitment: Field) {\n let side_effect = SideEffectLinkedToNoteHash { value: nullifier, note_hash: nullified_commitment, counter: self.side_effect_counter };\n self.new_nullifiers.push(side_effect);\n self.side_effect_counter = self.side_effect_counter + 1;\n }\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n let side_effect_counter = inputs.call_context.start_side_effect_counter;\n let mut min_revertible_side_effect_counter = 0;\n if is_empty(inputs.call_context.msg_sender) {\n min_revertible_side_effect_counter = side_effect_counter;\n }\n PrivateContext {\n inputs,\n side_effect_counter,\n min_revertible_side_effect_counter,\n args_hash,\n return_values: BoundedVec::new(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n nullifier_key_validation_requests: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_stack_hashes: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n new_l2_to_l1_msgs: BoundedVec::new(),\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165)\n // encrypted_logs_preimages: Vec::new(),\n // unencrypted_logs_preimages: Vec::new(),\n nullifier_key: Option::none()\n }\n }\n\n pub fn is_deployment(self) -> bool {\n // TODO(#4738): Implement this\n false\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165)\n let encrypted_logs_hash = [0; NUM_FIELDS_PER_SHA256];\n let unencrypted_logs_hash = [0; NUM_FIELDS_PER_SHA256];\n let encrypted_log_preimages_length = 0;\n let unencrypted_log_preimages_length = 0;\n\n let priv_circuit_pub_inputs = PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n return_values: self.return_values.storage,\n // TODO(fees): start this from 0 and test the following:\n // - in the private circuit init that it gets set correctly\n // - in the private circuit inner that it remains 0\n // I've had to initialize the counter here so that it would work for contract deployments\n // the above checks should be doable after we figure out fee payments for contract deployments\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n nullifier_key_validation_requests: self.nullifier_key_validation_requests.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_stack_hashes: self.private_call_stack_hashes.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n end_side_effect_counter: self.side_effect_counter,\n encrypted_logs_hash,\n unencrypted_logs_hash,\n encrypted_log_preimages_length,\n unencrypted_log_preimages_length,\n historical_header: self.historical_header,\n contract_deployment_data: self.inputs.contract_deployment_data,\n chain_id: self.inputs.private_global_variables.chain_id,\n version: self.inputs.private_global_variables.version\n };\n priv_circuit_pub_inputs\n }\n\n pub fn capture_min_revertible_side_effect_counter(&mut self) {\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = SideEffect { value: note_hash, counter: self.side_effect_counter };\n self.note_hash_read_requests.push(side_effect);\n self.side_effect_counter = self.side_effect_counter + 1;\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.side_effect_counter };\n self.nullifier_read_requests.push(request);\n self.side_effect_counter = self.side_effect_counter + 1;\n }\n\n pub fn request_nullifier_secret_key(&mut self, account: AztecAddress) -> GrumpkinPrivateKey {\n let key_pair = if self.nullifier_key.is_none() {\n let key_pair = get_nullifier_key_pair(account);\n validate_nullifier_key_against_address(account, key_pair.public_key);\n let request = NullifierKeyValidationRequest { public_key: key_pair.public_key, secret_key: key_pair.secret_key };\n self.nullifier_key_validation_requests.push(request);\n self.nullifier_key = Option::some(key_pair);\n key_pair\n } else {\n let key_pair = self.nullifier_key.unwrap_unchecked();\n // If MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL is larger than 1, need to update the way the key pair is cached.\n assert(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL == 1);\n assert(\n key_pair.account == account, \"Cannot query nullifier key for more than one account per call\"\n );\n key_pair\n };\n key_pair.secret_key\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 };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n pub fn accumulate_encrypted_logs(&mut self, log: [Field; N]) {\n let _void1 = self.inputs;\n let _void2 = log;\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165)\n }\n\n pub fn accumulate_unencrypted_logs(&mut self, log: T) {\n let _void1 = self.inputs;\n let _void2 = log;\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165)\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 ) -> [Field; RETURN_VALUES_LENGTH] {\n let args_hash = hash_args(args);\n assert(args_hash == arguments::pack_arguments(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> [Field; RETURN_VALUES_LENGTH] {\n let args_hash = hash_args(args);\n assert(args_hash == arguments::pack_arguments(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> [Field; RETURN_VALUES_LENGTH] {\n let args_hash = hash_args(args);\n assert(args_hash == arguments::pack_arguments(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> [Field; RETURN_VALUES_LENGTH] {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> [Field; RETURN_VALUES_LENGTH] {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> [Field; RETURN_VALUES_LENGTH] {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> [Field; RETURN_VALUES_LENGTH] {\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.start_side_effect_counter, self.side_effect_counter);\n self.side_effect_counter = item.public_inputs.end_side_effect_counter + 1;\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n assert(item.public_inputs.call_context.is_contract_deployment == false);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n self.private_call_stack_hashes.push(item.hash());\n\n item.public_inputs.return_values\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args(args);\n assert(args_hash == arguments::pack_arguments(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args(args);\n assert(args_hash == arguments::pack_arguments(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args(args);\n assert(args_hash == arguments::pack_arguments(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let mut reader = Reader::new(fields);\n\n // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and\n // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields!\n let item = PublicCallStackItem {\n contract_address: AztecAddress::from_field(reader.read()),\n function_data: reader.read_struct(FunctionData::deserialize),\n public_inputs: PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n return_values: [0; RETURN_VALUES_LENGTH],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [SideEffect::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [SideEffectLinkedToNoteHash::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n unencrypted_logs_hash: [0; NUM_FIELDS_PER_SHA256],\n unencrypted_log_preimages_length: 0,\n historical_header: Header::empty(),\n prover_address: AztecAddress::zero()\n },\n is_execution_request: true\n };\n reader.finish();\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.start_side_effect_counter, self.side_effect_counter);\n // We increment the sideffect counter by one, to account for the call itself being a side effect.\n self.side_effect_counter = self.side_effect_counter + 1;\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n assert(item.public_inputs.call_context.is_contract_deployment == false);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n self.public_call_stack_hashes.push(item.hash());\n }\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/aztec-nr/aztec/src/context/private_context.nr"},"71":{"source":"use crate::note::{note_header::NoteHeader, note_interface::NoteInterface};\n\nuse dep::protocol_types::{address::AztecAddress, utils::arr_copy_slice};\n\n#[oracle(notifyCreatedNote)]\nfn notify_created_note_oracle(\n _storage_slot: Field,\n _note_type_id: Field,\n _serialized_note: [Field; N],\n _inner_note_hash: Field\n) -> Field {}\n\nunconstrained pub fn notify_created_note(\n storage_slot: Field,\n note_type_id: Field,\n serialized_note: [Field; N],\n inner_note_hash: Field\n) -> Field {\n notify_created_note_oracle(storage_slot, note_type_id, serialized_note, inner_note_hash)\n}\n\n#[oracle(notifyNullifiedNote)]\nfn notify_nullified_note_oracle(_nullifier: Field, _inner_note_hash: Field) -> Field {}\n\nunconstrained pub fn notify_nullified_note(nullifier: Field, inner_note_hash: Field) -> Field {\n notify_nullified_note_oracle(nullifier, inner_note_hash)\n}\n\n#[oracle(getNotes)]\nfn get_notes_oracle(\n _storage_slot: Field,\n _num_selects: u8,\n _select_by: [u8; N],\n _select_values: [Field; N],\n _select_comparators: [u8; N],\n _sort_by: [u8; N],\n _sort_order: [u8; N],\n _limit: u32,\n _offset: u32,\n _status: u8,\n _return_size: u32,\n _placeholder_fields: [Field; S]\n) -> [Field; S] {}\n\nunconstrained fn get_notes_oracle_wrapper(\n storage_slot: Field,\n num_selects: u8,\n select_by: [u8; N],\n select_values: [Field; N],\n select_comparators: [u8; N],\n sort_by: [u8; N],\n sort_order: [u8; N],\n limit: u32,\n offset: u32,\n status: u8,\n mut placeholder_fields: [Field; S]\n) -> [Field; S] {\n let return_size = placeholder_fields.len() as u32;\n get_notes_oracle(\n storage_slot,\n num_selects,\n select_by,\n select_values,\n select_comparators,\n sort_by,\n sort_order,\n limit,\n offset,\n status,\n return_size,\n placeholder_fields\n )\n}\n\nunconstrained pub fn get_notes(\n storage_slot: Field,\n num_selects: u8,\n select_by: [u8; M],\n select_values: [Field; M],\n select_comparators: [u8; M],\n sort_by: [u8; M],\n sort_order: [u8; M],\n limit: u32,\n offset: u32,\n status: u8,\n mut placeholder_opt_notes: [Option; S], // TODO: Remove it and use `limit` to initialize the note array.\n placeholder_fields: [Field; NS], // TODO: Remove it and use `limit` to initialize the note array.\n _placeholder_note_length: [Field; N] // Turbofish hack? Compiler breaks calculating read_offset unless we add this parameter\n) -> [Option; S] where Note: NoteInterface {\n let fields = get_notes_oracle_wrapper(\n storage_slot,\n num_selects,\n select_by,\n select_values,\n select_comparators,\n sort_by,\n sort_order,\n limit,\n offset,\n status,\n placeholder_fields\n );\n let num_notes = fields[0] as u64;\n let contract_address = AztecAddress::from_field(fields[1]);\n for i in 0..placeholder_opt_notes.len() {\n if i < num_notes {\n // lengths named as per typescript.\n let return_header_length: u64 = 2; // num_notes & contract_address.\n let extra_preimage_length: u64 = 2; // nonce & is_transient.\n let read_offset: u64 = return_header_length + i * (N + extra_preimage_length);\n let nonce = fields[read_offset];\n let is_transient = fields[read_offset + 1] as bool;\n let header = NoteHeader { contract_address, nonce, storage_slot, is_transient };\n let serialized_note = arr_copy_slice(fields, [0; N], read_offset + 2);\n let mut note = Note::deserialize_content(serialized_note);\n // TODO: change this to note.setHeader(header) once https://github.com/noir-lang/noir/issues/4095 is fixed\n Note::set_header(&mut note, header);\n placeholder_opt_notes[i] = Option::some(note);\n };\n }\n placeholder_opt_notes\n}\n\n#[oracle(checkNullifierExists)]\nfn check_nullifier_exists_oracle(_inner_nullifier: Field) -> Field {}\n\nunconstrained pub fn check_nullifier_exists(inner_nullifier: Field) -> bool {\n check_nullifier_exists_oracle(inner_nullifier) == 1\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/notes.nr"},"74":{"source":"use dep::protocol_types::{address::{AztecAddress, PartialAddress, PublicKeysHash}, grumpkin_point::GrumpkinPoint};\n\n#[oracle(getPublicKeyAndPartialAddress)]\nfn get_public_key_and_partial_address_oracle(_address: AztecAddress) -> [Field; 3] {}\n\nunconstrained fn get_public_key_and_partial_address_internal(address: AztecAddress) -> [Field; 3] {\n get_public_key_and_partial_address_oracle(address)\n}\n\npub fn get_public_key(address: AztecAddress) -> GrumpkinPoint {\n let result = get_public_key_and_partial_address_internal(address);\n let pub_key = GrumpkinPoint::new(result[0], result[1]);\n let partial_address = PartialAddress::from_field(result[2]);\n\n let calculated_address = AztecAddress::compute(PublicKeysHash::compute(pub_key), partial_address);\n assert(calculated_address.eq(address));\n\n pub_key\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/get_public_key.nr"},"77":{"source":"use dep::protocol_types::{address::AztecAddress, constants::NUM_FIELDS_PER_SHA256, grumpkin_point::GrumpkinPoint};\n\n// TODO: Should take encrypted data.\n#[oracle(emitEncryptedLog)]\nfn emit_encrypted_log_oracle(\n _contract_address: AztecAddress,\n _storage_slot: Field,\n _note_type_id: Field,\n _encryption_pub_key: GrumpkinPoint,\n _preimage: [Field; N]\n) -> Field {}\n\nunconstrained pub fn emit_encrypted_log(\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n encryption_pub_key: GrumpkinPoint,\n preimage: [Field; N]\n) -> [Field; NUM_FIELDS_PER_SHA256] {\n [\n emit_encrypted_log_oracle(\n contract_address,\n storage_slot,\n note_type_id,\n encryption_pub_key,\n preimage\n ), 0\n ]\n}\n\n#[oracle(emitUnencryptedLog)]\nfn emit_unencrypted_log_oracle(\n _contract_address: AztecAddress,\n _event_selector: Field,\n _message: T\n) -> Field {}\n\nunconstrained pub fn emit_unencrypted_log(\n contract_address: AztecAddress,\n event_selector: Field,\n message: T\n) -> [Field; NUM_FIELDS_PER_SHA256] {\n // https://github.com/AztecProtocol/aztec-packages/issues/885\n [emit_unencrypted_log_oracle(contract_address, event_selector, message), 0]\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/logs.nr"},"79":{"source":"#[oracle(getRandomField)]\nfn rand_oracle() -> Field {}\n\nunconstrained pub fn rand() -> Field {\n rand_oracle()\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/rand.nr"},"83":{"source":"use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey};\n\nstruct NullifierKeyPair {\n account: AztecAddress,\n public_key: GrumpkinPoint,\n secret_key: GrumpkinPrivateKey,\n}\n\n#[oracle(getNullifierKeyPair)]\nfn get_nullifier_key_pair_oracle(_account: AztecAddress) -> [Field; 4] {}\n\nunconstrained fn get_nullifier_key_pair_internal(account: AztecAddress) -> NullifierKeyPair {\n let result = get_nullifier_key_pair_oracle(account);\n NullifierKeyPair {\n account,\n public_key: GrumpkinPoint { x: result[0], y: result[1] },\n secret_key: GrumpkinPrivateKey { high: result[2], low: result[3] }\n }\n}\n\npub fn get_nullifier_key_pair(account: AztecAddress) -> NullifierKeyPair {\n get_nullifier_key_pair_internal(account)\n}\n\npub fn get_nullifier_secret_key(account: AztecAddress) -> GrumpkinPrivateKey {\n get_nullifier_key_pair_internal(account).secret_key\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/aztec-nr/aztec/src/oracle/nullifier_key.nr"},"92":{"source":"mod globals;\nmod inputs;\n\nmod private_context;\nmod public_context;\nmod interface;\nmod avm;\n\nuse private_context::PrivateContext;\nuse interface::ContextInterface;\nuse public_context::PublicContext;\nuse avm::AVMContext;\n\nstruct Context {\n private: Option<&mut PrivateContext>,\n public: Option<&mut PublicContext>,\n}\n\nimpl Context {\n pub fn private(context: &mut PrivateContext) -> Context {\n Context { private: Option::some(context), public: Option::none() }\n }\n\n pub fn public(context: &mut PublicContext) -> Context {\n Context { public: Option::some(context), private: Option::none() }\n }\n\n pub fn none() -> Context {\n Context { public: Option::none(), private: Option::none() }\n }\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/aztec-nr/aztec/src/context.nr"},"105":{"source":"use dep::protocol_types::{address::AztecAddress, constants::{GENERATOR_INDEX__INITIALIZATION_NULLIFIER}, hash::pedersen_hash};\n\nuse crate::context::{PrivateContext, PublicContext, Context};\nuse crate::note::{\n lifecycle::{create_note, destroy_note}, note_getter::{get_note, view_notes},\n note_interface::NoteInterface, note_viewer_options::NoteViewerOptions\n};\nuse crate::oracle::{nullifier_key::get_nullifier_secret_key, notes::check_nullifier_exists};\nuse crate::state_vars::storage::Storage;\n\n// docs:start:struct\nstruct PrivateMutable {\n context: Option<&mut PrivateContext>,\n storage_slot: Field\n}\n// docs:end:struct\n\nimpl Storage for PrivateMutable {}\n\nimpl PrivateMutable {\n // docs:start:new\n pub fn new(context: Context, storage_slot: Field) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Self { context: context.private, storage_slot }\n }\n // docs:end:new\n\n // The following computation is leaky, in that it doesn't hide the storage slot that has been initialized, nor does it hide the contract address of this contract.\n // When this initialization nullifier is emitted, an observer could do a dictionary or rainbow attack to learn the preimage of this nullifier to deduce the storage slot and contract address.\n // For some applications, leaking the details that a particular state variable of a particular contract has been initialized will be unacceptable.\n // Under such circumstances, such application developers might wish to _not_ use this state variable type.\n // This is especially dangerous for initial assignment to elements of a `Map` type (for example), because the storage slot often also identifies an actor. e.g.\n // the initial assignment to `my_map.at(msg.sender)` will leak: `msg.sender`, the fact that an element of `my_map` was assigned-to for the first time, and the contract_address.\n // Note: subsequent nullification of this state variable, via the `replace` method will not be leaky, if the `compute_nullifier()` method of the underlying note is designed to ensure privacy.\n // For example, if the `compute_nullifier()` method injects the secret key of a note owner into the computed nullifier's preimage.\n pub fn compute_initialization_nullifier(self) -> Field {\n pedersen_hash(\n [self.storage_slot],\n GENERATOR_INDEX__INITIALIZATION_NULLIFIER\n )\n }\n\n // docs:start:is_initialized\n unconstrained pub fn is_initialized(self) -> bool {\n let nullifier = self.compute_initialization_nullifier();\n check_nullifier_exists(nullifier)\n }\n // docs:end:is_initialized\n\n // docs:start:initialize\n pub fn initialize(self, note: &mut Note, broadcast: bool) where Note: NoteInterface {\n let context = self.context.unwrap();\n\n // Nullify the storage slot.\n let nullifier = self.compute_initialization_nullifier();\n context.push_new_nullifier(nullifier, 0);\n\n create_note(context, self.storage_slot, note, broadcast);\n }\n // docs:end:initialize\n\n // docs:start:replace\n pub fn replace(self, new_note: &mut Note, broadcast: bool) where Note: NoteInterface {\n let context = self.context.unwrap();\n let prev_note = get_note(context, self.storage_slot);\n\n // Nullify previous note.\n destroy_note(context, prev_note);\n\n // Add replacement note.\n create_note(context, self.storage_slot, new_note, broadcast);\n }\n // docs:end:replace\n\n // docs:start:get_note\n pub fn get_note(self, broadcast: bool) -> Note where Note: NoteInterface {\n let context = self.context.unwrap();\n let mut note = get_note(context, self.storage_slot);\n\n // Nullify current note to make sure it's reading the latest note.\n destroy_note(context, note);\n\n // Add the same note again.\n // Because a nonce is added to every note in the kernel, its nullifier will be different.\n create_note(context, self.storage_slot, &mut note, broadcast);\n\n note\n }\n // docs:end:get_note\n\n // docs:start:view_note\n unconstrained pub fn view_note(self) -> Note where Note: NoteInterface {\n let options = NoteViewerOptions::new().set_limit(1);\n view_notes(self.storage_slot, options)[0].unwrap()\n }\n // docs:end:view_note\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr"},"107":{"source":"use crate::context::{PrivateContext, PublicContext, Context};\nuse dep::protocol_types::{hash::pedersen_hash, traits::{ToField}};\nuse crate::state_vars::storage::Storage;\n\n// docs:start:map\nstruct Map {\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V,\n}\n// docs:end:map\n\nimpl Storage for Map {}\n\nimpl Map {\n // docs:start:new\n pub fn new(\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Map { context, storage_slot, state_var_constructor }\n }\n // docs:end:new\n\n // docs:start:at\n pub fn at(self, key: K) -> V where K: ToField {\n // TODO(#1204): use a generator index for the storage slot\n let derived_storage_slot = pedersen_hash([self.storage_slot, key.to_field()], 0);\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","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/aztec-nr/aztec/src/state_vars/map.nr"},"114":{"source":"use dep::protocol_types::{hash::hash_args, traits::Hash};\n\nstruct Hasher {\n fields: [Field],\n}\n\nimpl Hash for Hasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl Hasher {\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","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/aztec-nr/aztec/src/hasher.nr"},"193":{"source":"use dep::std::cmp::Eq;\n\n// Trait: is_empty\n//\n// The general is_empty trait checks if a data type is is empty,\n// and it defines empty for the basic data types as 0.\n//\n// If a Field is equal to zero, then it is regarded as zero.\n// We will go with this definition for now, however it can be problematic \n// if a value can actually be zero. In a future refactor, we can \n// use the optional type for safety. Doing it now would lead to a worse devex\n// and would make it harder to sync up with the cpp code.\n// Preferred over Default trait to convey intent, as default doesn't necessarily mean empty.\ntrait Empty {\n fn empty() -> Self;\n}\n\nimpl Empty for Field { fn empty() -> Self {0} }\n\nimpl Empty for u1 { fn empty() -> Self {0} }\nimpl Empty for u8 { fn empty() -> Self {0} }\nimpl Empty for u32 { fn empty() -> Self {0} }\nimpl Empty for u64 { fn empty() -> Self {0} }\nimpl Empty for U128 { fn empty() -> Self {U128::from_integer(0)} }\n\npub fn is_empty(item: T) -> bool where T: Empty + Eq {\n item.eq(T::empty())\n}\n\npub fn is_empty_array(array: [T; N]) -> bool where T: Empty + Eq {\n array.all(|elem| is_empty(elem))\n}\n\ntrait Hash {\n fn hash(self) -> Field;\n}\n\ntrait ToField {\n fn to_field(self) -> Field;\n}\n\nimpl ToField for Field {\n fn to_field(self) -> Field {\n self\n }\n}\n\nimpl ToField for U128 {\n fn to_field(self) -> Field {\n self.to_integer()\n }\n}\n\n// docs:start:serialize\ntrait Serialize {\n fn serialize(self) -> [Field; N];\n}\n// docs:end:serialize\n\n// docs:start:deserialize\ntrait Deserialize {\n fn deserialize(fields: [Field; N]) -> Self;\n}\n// docs:end:deserialize\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr"},"199":{"source":"// general util packages/modules are usually bad practice\n// because there is no criteria for what we should not put in here.\n// Reducing the size of this package would be welcome.\n\nmod arrays;\nmod field;\nmod reader;\nmod uint256;\n\n// if predicate == true then return lhs, else return rhs\npub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field {\n if predicate { lhs } else { rhs }\n}\n\npub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u64) -> [T; M] {\n for i in 0..dst.len() {\n dst[i] = src[i + offset];\n }\n dst\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr"},"200":{"source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS},\n contract_class_id::ContractClassId, hash::pedersen_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl 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 AztecAddress::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute_from_public_key(\n pub_key: GrumpkinPoint,\n contract_class_id: ContractClassId,\n salt: Field,\n initialization_hash: Field,\n portal_contract_address: EthAddress\n ) -> AztecAddress {\n AztecAddress::compute(\n PublicKeysHash::compute(pub_key),\n PartialAddress::compute(\n contract_class_id,\n salt,\n initialization_hash,\n portal_contract_address\n )\n )\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n pedersen_hash(\n [pub_keys_hash.to_field(), partial_address.to_field()],\n GENERATOR_INDEX__CONTRACT_ADDRESS\n )\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address() {\n let point = GrumpkinPoint { x: 1, y: 2 };\n let contract_address_salt = 3;\n let contract_class_id = ContractClassId::from_field(4);\n let initialization_hash = 5;\n let portal_contract_address = EthAddress::from_field(6);\n\n let address = AztecAddress::compute_from_public_key(\n point,\n contract_class_id,\n contract_address_salt,\n initialization_hash,\n portal_contract_address\n );\n\n assert(address.to_field() == 0x2fd71a4f0742364f194dd16d0ae32d2f47845ddc7f5d328f37d4148b565c4123);\n}\n\n#[test]\nfn compute_address_from_partial_and_pubkey() {\n let point = GrumpkinPoint { x: 1, y: 2 };\n let partial_address = PartialAddress::from_field(3);\n\n let address = AztecAddress::compute(PublicKeysHash::compute(point), partial_address);\n assert(address.to_field() == 0x0447f893197175723deb223696e2e96dbba1e707ee8507766373558877e74197);\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr"},"201":{"source":"use crate::{\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, hash::pedersen_hash, grumpkin_point::GrumpkinPoint,\n traits::{ToField, Serialize, Deserialize}\n};\n\n// Public keys hash. Used in the computation of an address.\nstruct PublicKeysHash {\n inner: Field\n}\n\nimpl ToField for PublicKeysHash {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize<1> for PublicKeysHash {\n fn serialize(self: Self) -> [Field; 1] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize<1> for PublicKeysHash {\n fn deserialize(fields: [Field; 1]) -> Self {\n PublicKeysHash::from_field(fields[0])\n }\n}\n\nimpl Eq for PublicKeysHash {\n fn eq(self, other: Self) -> bool {\n self.inner == other.inner\n }\n}\n\nimpl PublicKeysHash {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(public_key: GrumpkinPoint) -> Self {\n PublicKeysHash::from_field(\n pedersen_hash(\n [\n public_key.x,\n public_key.y\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn to_field(self) -> Field {\n self.inner\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n\n#[test]\nfn compute_public_keys_hash() {\n let point = GrumpkinPoint { x: 1, y: 2 };\n let actual = PublicKeysHash::compute(point);\n assert(actual.to_field() == 0x1923a6246e305720b6aaf751fde0342613e93c82e455c3831e28375c16dd40d8);\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/address/public_keys_hash.nr"},"205":{"source":"use crate::address::{AztecAddress, EthAddress};\nuse crate::mocked::VerificationKey;\nuse crate::abis::function_selector::FunctionSelector;\nuse crate::abis::function_leaf_preimage::FunctionLeafPreimage;\nuse crate::abis::contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage;\nuse crate::contract_class_id::ContractClassId;\nuse crate::abis::new_contract_data::NewContractData as ContractLeafPreimage;\nuse crate::abis::function_data::FunctionData;\nuse crate::abis::side_effect::{SideEffect};\nuse crate::utils::uint256::U256;\nuse crate::constants::{\n ARGS_HASH_CHUNK_COUNT, ARGS_HASH_CHUNK_LENGTH, CONTRACT_TREE_HEIGHT, FUNCTION_TREE_HEIGHT,\n NUM_FIELDS_PER_SHA256, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__CONSTRUCTOR, GENERATOR_INDEX__PARTIAL_ADDRESS,\n GENERATOR_INDEX__CONTRACT_ADDRESS, GENERATOR_INDEX__NOTE_HASH_NONCE,\n GENERATOR_INDEX__UNIQUE_NOTE_HASH, GENERATOR_INDEX__FUNCTION_ARGS\n};\nuse crate::messaging::l2_to_l1_message::L2ToL1Message;\n\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n\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 + (sha256_hashed[15 - i] as Field) * v;\n low = low + (sha256_hashed[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n let hash_in_a_field = low + high * v;\n\n hash_in_a_field\n}\n\npub fn hash_args(args: [Field; N]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n for i in 0..ARGS_HASH_CHUNK_COUNT {\n let mut chunk_hash = 0;\n let start_chunk_index = i * ARGS_HASH_CHUNK_LENGTH;\n if start_chunk_index < args.len() {\n let mut chunk_args = [0; ARGS_HASH_CHUNK_LENGTH];\n for j in 0..ARGS_HASH_CHUNK_LENGTH {\n let item_index = i * ARGS_HASH_CHUNK_LENGTH + j;\n if item_index < args.len() {\n chunk_args[j] = args[item_index];\n }\n }\n chunk_hash = pedersen_hash(chunk_args, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n chunks_hashes[i] = chunk_hash;\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n// Checks that `value` is a member of a merkle tree with root `root` at position `index`\n// The witness being the `sibling_path`\npub fn assert_check_membership(value: Field, index: Field, sibling_path: [Field; N], root: Field) {\n let calculated_root = root_from_sibling_path(value, index, sibling_path);\n assert(calculated_root == root, \"membership check failed\");\n}\n\n// Calculate the Merkle tree root from the sibling path and leaf.\n//\n// The leaf is hashed with its sibling, and then the result is hashed\n// with the next sibling etc in the path. The last hash is the root.\n//\n// TODO(David/Someone): The cpp code is using a uint256, whereas its\n// TODO a bit simpler in Noir to just have a bit array.\n// TODO: I'd generally like to avoid u256 for algorithms like \n// this because it means we never even need to consider cases where \n// the index is greater than p.\npub fn root_from_sibling_path(leaf: Field, leaf_index: Field, sibling_path: [Field; N]) -> Field {\n let mut node = leaf;\n let indices = leaf_index.to_le_bits(N);\n\n for i in 0..N {\n let (hash_left, hash_right) = if indices[i] == 1 {\n (sibling_path[i], node)\n } else {\n (node, sibling_path[i])\n };\n node = merkle_hash(hash_left, hash_right);\n }\n node\n}\n\n// Calculate the function tree root from the sibling path and leaf preimage.\n//\n// TODO: The cpp code passes in components of the FunctionLeafPreimage and then \n// builds it up. We should build it up and then pass the leaf preimage as a parameter.\n// We can then choose to have a general method that takes in anything hashable\n// and deduplicate the logic in `contract_tree_root_from_siblings`\npub fn function_tree_root_from_siblings(\n selector: FunctionSelector,\n is_internal: bool,\n is_private: bool,\n vk_hash: Field,\n acir_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = FunctionLeafPreimage { selector, is_internal, is_private, vk_hash, acir_hash };\n\n let function_leaf = function_leaf_preimage.hash();\n\n let function_tree_root = root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path);\n\n function_tree_root\n}\n\n// Calculate the contract tree root from the sibling path and leaf preimage.\npub fn contract_tree_root_from_siblings(\n contract_class_id: ContractClassId,\n storage_contract_address: AztecAddress,\n portal_contract_address: EthAddress,\n contract_leaf_index: Field,\n contract_leaf_sibling_path: [Field; CONTRACT_TREE_HEIGHT]\n) -> Field {\n //TODO(Kev): if we use shorthand syntax here, we get an error as expected,\n // since variable name is `storage_contract_address` but the span is incorrect.\n let contract_leaf_preimage = ContractLeafPreimage { contract_address: storage_contract_address, portal_contract_address, contract_class_id };\n\n let contract_leaf = contract_leaf_preimage.hash();\n\n let computed_contract_tree_root = root_from_sibling_path(contract_leaf, contract_leaf_index, contract_leaf_sibling_path);\n\n computed_contract_tree_root\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn silo_note_hash(address: AztecAddress, inner_commitment: Field) -> Field {\n pedersen_hash(\n [\n address.to_field(),\n inner_commitment\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_nullifier(address: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n address.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\nfn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\n// TODO CPP uses blake2s for this\npub fn compute_new_contract_address_hash(new_contract_address: AztecAddress) -> Field {\n dep::std::hash::pedersen_hash([new_contract_address.to_field()])\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n rollup_version_id: Field,\n chain_id: Field,\n message: L2ToL1Message\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [\n contract_address.to_field(), rollup_version_id, message.recipient.to_field(), chain_id, message.content\n ];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn compute_constructor_hash(\n function_data: FunctionData,\n args_hash: Field,\n constructor_vk_hash: Field\n) -> Field {\n let function_data_hash = function_data.hash();\n\n pedersen_hash(\n [\n function_data_hash,\n args_hash,\n constructor_vk_hash\n ],\n GENERATOR_INDEX__CONSTRUCTOR\n )\n}\n\n// Computes sha256 hash of 2 input hashes stored in 4 fields.\n// \n// This method is bn254 specific. Two fields is needed in order to \n// encode the sha256 output. It can be abstracted away with any 4-2 hash function.\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//\n// Returning a Field would be desirable because then this can be replaced with \n// poseidon without changing the rest of the code\n//\npub fn accumulate_sha256(input: [U128; 4]) -> [Field; NUM_FIELDS_PER_SHA256] {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n //\n // Concatenate 4 u128 bit integers into a byte array.\n let mut hash_input_flattened = [0; 64];\n for offset in 0..4 {\n let input_as_bytes = input[offset].to_be_bytes();\n for byte_index in 0..16 {\n hash_input_flattened[offset * 16 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n let sha_digest = dep::std::hash::sha256(hash_input_flattened);\n\n U256::from_bytes32(sha_digest).to_u128_limbs()\n}\n\npub fn compute_logs_hash(\n previous_log_hash: [Field; 2],\n current_log_hash: [Field; 2]\n) -> [Field; NUM_FIELDS_PER_SHA256] {\n accumulate_sha256(\n [\n U128::from_integer(previous_log_hash[0]),\n U128::from_integer(previous_log_hash[1]),\n U128::from_integer(current_log_hash[0]),\n U128::from_integer(current_log_hash[1])\n ]\n )\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, commitment_index: u64) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n commitment_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_siloed_note_hash(nonce: Field, siloed_note_hash: Field) -> Field {\n pedersen_hash(\n [\n nonce,\n siloed_note_hash\n ],\n GENERATOR_INDEX__UNIQUE_NOTE_HASH\n )\n}\n\npub fn compute_unique_siloed_note_hashes(\n first_nullifier: Field,\n siloed_note_hashes: [SideEffect; N]\n) -> [SideEffect; N] {\n let mut unique_siloed_note_hashes = [SideEffect::empty(); N];\n for i in 0..N {\n let siloed_note_hash = siloed_note_hashes[i];\n if siloed_note_hash.value != 0 {\n let nonce = compute_note_hash_nonce(first_nullifier, i);\n unique_siloed_note_hashes[i] = SideEffect {\n value: compute_unique_siloed_note_hash(nonce, siloed_note_hash.value),\n counter: siloed_note_hash.counter\n };\n }\n }\n unique_siloed_note_hashes\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n assert(result == 0x142a6d57007171f6eaa33d55976d9dbe739c889c8e920f115f7808dea184c718);\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = [0; 800];\n for i in 0..800 {\n input[i] = i as Field;\n }\n let hash = hash_args(input);\n assert(hash == 0x371960dd84ed3445ab099ac4c1af5ba90e0c713b593e0ca52ee532087c7f097);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), 0, 0, L2ToL1Message::empty());\n assert(hash_result == 0x2266ac2f9f0c19c015239ef5ea85862fc6fac00db73779b220a4d49c4856c2e1);\n\n // Non-zero case\n let message = L2ToL1Message { recipient: EthAddress::from_field(3), content: 5 };\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), 2, 4, message);\n assert(hash_result == 0x0f24729168d4450a5681beafa5e3a899ac28bd17bf5a4877dab37bcd834e1634);\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr"},"220":{"source":"use dep::aztec::{\n protocol_types::{address::AztecAddress, traits::{Deserialize, Serialize}},\n note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption},\n oracle::{rand::rand, nullifier_key::get_nullifier_secret_key, get_public_key::get_public_key},\n log::emit_encrypted_log, hash::pedersen_hash, context::PrivateContext\n};\n\nglobal VALUE_NOTE_LEN: Field = 3; // 3 plus a header.\n\n// docs:start:value-note-def\nstruct ValueNote {\n value: Field,\n owner: AztecAddress,\n randomness: Field,\n header: NoteHeader,\n}\n// docs:end:value-note-def\n\nimpl NoteInterface for ValueNote {\n fn serialize_content(self) -> [Field; VALUE_NOTE_LEN] {\n [self.value, self.owner.to_field(), self.randomness]\n }\n\n fn deserialize_content(serialized_note: [Field; VALUE_NOTE_LEN]) -> Self {\n ValueNote {\n value: serialized_note[0],\n owner: AztecAddress::from_field(serialized_note[1]),\n randomness: serialized_note[2],\n header: NoteHeader::empty(),\n }\n }\n\n fn compute_note_content_hash(self) -> Field {\n // TODO(#1205) Should use a non-zero generator index.\n pedersen_hash(self.serialize_content(),0)\n }\n\n // docs:start:nullifier\n\n fn compute_nullifier(self, context: &mut PrivateContext) -> Field {\n let note_hash_for_nullify = compute_note_hash_for_consumption(self);\n let secret = context.request_nullifier_secret_key(self.owner);\n // TODO(#1205) Should use a non-zero generator index.\n pedersen_hash([\n note_hash_for_nullify,\n secret.low,\n secret.high,\n ],0)\n }\n\n // docs:end:nullifier\n\n fn compute_nullifier_without_context(self) -> Field {\n let note_hash_for_nullify = compute_note_hash_for_consumption(self);\n let secret = get_nullifier_secret_key(self.owner);\n // TODO(#1205) Should use a non-zero generator index.\n pedersen_hash([\n note_hash_for_nullify,\n secret.low,\n secret.high,\n ],0)\n }\n\n fn set_header(&mut self, header: NoteHeader) {\n self.header = header;\n }\n\n fn get_header(self) -> NoteHeader {\n self.header\n }\n\n // Broadcasts the note as an encrypted log on L1.\n fn broadcast(self, context: &mut PrivateContext, slot: Field) {\n let encryption_pub_key = get_public_key(self.owner);\n emit_encrypted_log(\n context,\n (*context).this_address(),\n slot,\n Self::get_note_type_id(),\n encryption_pub_key,\n self.serialize_content(),\n );\n }\n\n fn get_note_type_id() -> Field {\n // TODO(#4519): autogenerate\n // python -c \"print(int(''.join(str(ord(c)) for c in 'ValueNote')))\"\n 869710811710178111116101\n }\n}\n\nimpl ValueNote {\n pub fn new(value: Field, owner: AztecAddress) -> Self {\n let randomness = rand();\n let header = NoteHeader::empty();\n ValueNote { value, owner, randomness, header }\n }\n}\n","path":"/Users/zpedro/Documents/GitHub/aztec-packages/noir-projects/aztec-nr/value-note/src/value_note.nr"}}} \ No newline at end of file diff --git a/boxes/boxes/react/src/hooks/useContract.tsx b/boxes/boxes/react/src/hooks/useContract.tsx index 8082005867c..0b43494be65 100644 --- a/boxes/boxes/react/src/hooks/useContract.tsx +++ b/boxes/boxes/react/src/hooks/useContract.tsx @@ -1,12 +1,11 @@ import { useState } from 'react'; import { deployerEnv } from '../config'; -import { Contract, ContractDeployer, Fr } from '@aztec/aztec.js'; +import { Contract, Fr } from '@aztec/aztec.js'; import { BoxReactContract } from '../../artifacts/BoxReact'; import { toast } from 'react-toastify'; export function useContract() { - const { artifact, at } = BoxReactContract; const [wait, setWait] = useState(false); const [contract, setContract] = useState(); @@ -15,13 +14,11 @@ export function useContract() { setWait(true); const wallet = await deployerEnv.getWallet(); - const contractDeployer = new ContractDeployer(artifact, wallet); - const salt = Fr.random(); - const tx = contractDeployer - .deploy(Fr.random(), wallet.getCompleteAddress().address) - .send({ contractAddressSalt: salt }); - const { address: contractAddress } = await toast.promise(tx.deployed(), { + const tx = await BoxReactContract.deploy(wallet, Fr.random(), wallet.getCompleteAddress().address).send({ + contractAddressSalt: salt, + }); + const contract = await toast.promise(tx.deployed(), { pending: 'Deploying contract...', success: { render: ({ data }) => `Address: ${data.address}`, @@ -29,8 +26,6 @@ export function useContract() { error: 'Error deploying contract', }); - const deployerWallet = await deployerEnv.getWallet(); - const contract = await at(contractAddress!, deployerWallet); setContract(contract); setWait(false); }; diff --git a/boxes/boxes/react/tests/node.test.ts b/boxes/boxes/react/tests/node.test.ts index 40c43ef8acc..f7c9bd0d255 100644 --- a/boxes/boxes/react/tests/node.test.ts +++ b/boxes/boxes/react/tests/node.test.ts @@ -7,18 +7,16 @@ const logger = createDebugLogger('aztec:http-pxe-client'); describe('BoxReact Contract Tests', () => { let wallet: AccountWallet; let contract: Contract; - const { artifact } = BoxReactContract; const numberToSet = Fr.random(); beforeAll(async () => { wallet = await deployerEnv.getWallet(); - const pxe = deployerEnv.pxe; - const deployer = new ContractDeployer(artifact, wallet); const salt = Fr.random(); - const { address: contractAddress } = await deployer.deploy(Fr.random(), wallet.getCompleteAddress().address).send({ contractAddressSalt: salt }).deployed(); - contract = await BoxReactContract.at(contractAddress!, wallet); + contract = await BoxReactContract.deploy(wallet, Fr.random(), wallet.getCompleteAddress().address) + .send({ contractAddressSalt: salt }) + .deployed(); - logger(`L2 contract deployed at ${contractAddress}`); + logger(`L2 contract deployed at ${contract.address}`); }, 60000); test('Can set a number', async () => { diff --git a/boxes/boxes/vanilla/src/index.ts b/boxes/boxes/vanilla/src/index.ts index c3cd0e55712..e5add71062b 100644 --- a/boxes/boxes/vanilla/src/index.ts +++ b/boxes/boxes/vanilla/src/index.ts @@ -1,4 +1,4 @@ -import { GrumpkinScalar, createPXEClient, AccountManager, ContractDeployer, Fr, Wallet } from '@aztec/aztec.js'; +import { GrumpkinScalar, createPXEClient, AccountManager, Fr, Wallet } from '@aztec/aztec.js'; import { SingleKeyAccountContract } from '@aztec/accounts/single_key'; import { VanillaContract } from '../artifacts/Vanilla'; @@ -19,15 +19,10 @@ const setWait = (state: boolean): void => document.querySelector('#deploy').addEventListener('click', async ({ target }: any) => { setWait(true); wallet = await account.register(); - - const { artifact, at } = VanillaContract; - const contractDeployer = new ContractDeployer(artifact, wallet); - const { address: contractAddress } = await contractDeployer - .deploy(Fr.random(), wallet.getCompleteAddress().address) + contract = await VanillaContract.deploy(wallet, Fr.random(), wallet.getCompleteAddress().address) .send({ contractAddressSalt: Fr.random() }) .deployed(); - contract = await at(contractAddress, wallet); - alert(`Contract deployed at ${contractAddress}`); + alert(`Contract deployed at ${contract.address}`); target.hidden = true; document.querySelectorAll('#get, #set').forEach((e: HTMLButtonElement & HTMLFormElement) => (e.hidden = false)); diff --git a/boxes/contract-only/.gitignore b/boxes/contract-only/.gitignore new file mode 100644 index 00000000000..5af41cfb33e --- /dev/null +++ b/boxes/contract-only/.gitignore @@ -0,0 +1,12 @@ +.yarn/* +!.yarn/releases + +node_modules +dist +artifacts +src/contracts/target +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ +codegenCache.json diff --git a/boxes/contract-only/.prettierignore b/boxes/contract-only/.prettierignore new file mode 100644 index 00000000000..a72dfe54860 --- /dev/null +++ b/boxes/contract-only/.prettierignore @@ -0,0 +1,2 @@ +src/artifacts/**/*.json +src/artifacts/**/*.ts \ No newline at end of file diff --git a/boxes/contract-only/.prettierrc.json b/boxes/contract-only/.prettierrc.json new file mode 100644 index 00000000000..7c3bbec6848 --- /dev/null +++ b/boxes/contract-only/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "printWidth": 120, + "arrowParens": "avoid" +} diff --git a/boxes/contract-only/README.md b/boxes/contract-only/README.md new file mode 100644 index 00000000000..9ab9f68660d --- /dev/null +++ b/boxes/contract-only/README.md @@ -0,0 +1,24 @@ +# Contract-Only Box + +This box is a one-stop-shop for Aztec with the %%contract_name%% example contract. You can use it as a boilerplate to start developing your own Aztec app in seconds! + +## How to start + +The script copied one of the example contracts and put it into a one-size-fits-all "box". With it, you can run commands such as: + +- `yarn test` -> Runs the built-in tests +- `yarn compile` -> Compiles your contract so it can be deployed +- `yarn codegen` -> Generates a handy TS interface file with all your contract's methods so they're easy to interact with +- `yarn clean` -> Removes artifacts and other things you may not want to have lying around +- `yarn formatting` -> Formats your code with prettier +- + +## Testing + +Contract-only boxes give you basic test functionality through `jest`, and check for existence and correct working of the sandbox. + +If you want some ideas to test the contract you just bootstrapped, check out [our own e2e test suite!](%%e2e_test_url%%) + +## More information + +Visit the [Aztec Docs](https://docs.aztec.network) for more information on how Aztec works, and the [Awesome Aztec Repository](https://github.com/AztecProtocol/awesome-aztec) for more cool projects, boilerplates and tooling. diff --git a/boxes/contract-only/package.json b/boxes/contract-only/package.json new file mode 100644 index 00000000000..361571253f8 --- /dev/null +++ b/boxes/contract-only/package.json @@ -0,0 +1,53 @@ +{ + "name": "@aztec/contract_box", + "description": "My Aztec contract", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "compile": "cd src && ${AZTEC_NARGO:-aztec-nargo} compile", + "codegen": "${AZTEC_CLI:-aztec-cli} codegen target -o artifacts --ts", + "clean": "rm -rf ./dest .tsbuildinfo ./artifacts ./target", + "prep": "yarn clean && yarn compile && yarn codegen && tsc -b", + "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --runInBand", + "formatting": "prettier --check ./src && eslint ./src", + "formatting:fix": "prettier -w ./src" + }, + "dependencies": { + "@aztec/accounts": "latest", + "@aztec/aztec.js": "latest" + }, + "jest": { + "preset": "ts-jest/presets/default-esm", + "transform": { + "^.+\\.(ts|tsx)$": [ + "ts-jest", + { + "useESM": true + } + ] + }, + "moduleNameMapper": { + "^(\\.{1,2}/.*)\\.js$": "$1" + }, + "testRegex": "tests/.*\\.test\\.ts$", + "rootDir": "./" + }, + "devDependencies": { + "@playwright/test": "1.42.0", + "@types/jest": "^29.5.0", + "@types/node": "^20.11.17", + "copy-webpack-plugin": "^11.0.0", + "html-webpack-plugin": "^5.6.0", + "jest": "^29.6.4", + "stream-browserify": "^3.0.0", + "ts-loader": "^9.5.1", + "tty-browserify": "^0.0.1", + "typescript": "^5.0.4", + "util": "^0.12.5", + "webpack": "^5.90.1", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^4.15.1" + }, + "packageManager": "yarn@4.0.2" +} diff --git a/boxes/contract-only/tests/node.test.ts b/boxes/contract-only/tests/node.test.ts new file mode 100644 index 00000000000..158476f897c --- /dev/null +++ b/boxes/contract-only/tests/node.test.ts @@ -0,0 +1,35 @@ +import { createPXEClient, PXE, GrumpkinScalar, AccountManager, Wallet } from '@aztec/aztec.js'; +import { SingleKeyAccountContract } from '@aztec/accounts/single_key'; +import { derivePublicKey } from '@aztec/circuits.js'; + +describe('Account Tests', () => { + const pxeURL = process.env.PXE_URL || 'http://localhost:8080'; + let pxe: PXE; + let account: AccountManager; + let wallet: Wallet; + + const privateKey = GrumpkinScalar.fromString('0x1234'); + const expectedPublicKey = derivePublicKey(privateKey).toString(); + + test('Can start the PXE server', async () => { + pxe = createPXEClient(pxeURL); + const { chainId } = await pxe.getNodeInfo(); + expect(chainId).toBe(31337); + }); + + beforeEach(() => { + const accountContract = new SingleKeyAccountContract(privateKey); + account = new AccountManager(pxe, privateKey, accountContract); + }); + + test('Can create an account contract with a known address', async () => { + const publicKey = account.getCompleteAddress().publicKey.toString(); + expect(publicKey).toEqual(expectedPublicKey); + }); + + test('Can deploy a contract with a known address', async () => { + ({ wallet } = await (await account.deploy()).wait()); + const publicKey = wallet.getCompleteAddress().publicKey.toString(); + expect(publicKey).toEqual(expectedPublicKey); + }); +}); diff --git a/boxes/contract-only/tsconfig.json b/boxes/contract-only/tsconfig.json new file mode 100644 index 00000000000..c1bff675717 --- /dev/null +++ b/boxes/contract-only/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "es2020", + "outDir": "artifacts/build", + "module": "ESNext", + "moduleResolution": "Bundler", + "skipLibCheck": true + }, + "include": ["**/*.ts"] +} diff --git a/boxes/package.json b/boxes/package.json index ec60d38c550..b782ec6ec55 100644 --- a/boxes/package.json +++ b/boxes/package.json @@ -1,7 +1,7 @@ { "name": "create-aztec-app", "packageManager": "yarn@4.1.0", - "version": "0.2.13", + "version": "0.2.15", "type": "module", "scripts": { "compile": "yarn workspaces foreach -A -v run compile", @@ -30,10 +30,11 @@ "@inquirer/input": "^2.0.0", "@inquirer/select": "^2.0.0", "axios": "^1.6.7", - "chalk": "^5.3.0", "commander": "^12.0.0", "node-pty": "^1.0.0", "ora": "^8.0.1", + "pino": "^8.19.0", + "pino-pretty": "^10.3.1", "tiged": "^2.12.6" } } diff --git a/boxes/scripts/config.js b/boxes/scripts/config.js new file mode 100644 index 00000000000..21940d4404f --- /dev/null +++ b/boxes/scripts/config.js @@ -0,0 +1,14 @@ +export const AZTEC_REPO = "AztecProtocol/aztec-packages"; +export const CONTRACTS_TO_SHOW = ["token_contract"]; +export const getPlaceholders = (contract) => { + return [ + { + key: "%%contract_name%%", + value: contract, + }, + { + key: "%%e2e_test_url%%", + value: `https://github.com/${AZTEC_REPO}/tree/master/yarn-project/end-to-end/src/e2e_${contract}.test.ts`, + }, + ]; +}; diff --git a/boxes/scripts/steps/chooseBox.js b/boxes/scripts/steps/chooseBox.js index 0f25e81a166..644a15a201b 100644 --- a/boxes/scripts/steps/chooseBox.js +++ b/boxes/scripts/steps/chooseBox.js @@ -1,13 +1,15 @@ import select from "@inquirer/select"; -import input from "@inquirer/input"; -import tiged from "tiged"; -import { getAvailableBoxes, replacePaths } from "../utils.js"; -import chalk from "chalk"; -import ora from "ora"; -const { log } = console; - -export async function chooseAndCloneBox(tag, version) { - const availableBoxes = await getAvailableBoxes(tag, version); +import { + getAvailableBoxes, + getAvailableContracts, + processProject, + replacePaths, + clone, +} from "../utils.js"; +import { getPlaceholders } from "../config.js"; + +async function chooseAndCloneBox() { + const availableBoxes = await getAvailableBoxes(); const appType = await select({ message: `Please choose your Aztec boilerplate:`, choices: [ @@ -18,45 +20,75 @@ export async function chooseAndCloneBox(tag, version) { ], }); - if (appType === "skip") return; + const rootDir = await clone({ + path: "boxes/boxes", + choice: appType, + type: "box", + tag, + version, + }); + + await replacePaths({ + rootDir, + tag, + version, + prefix: "", + }); + success("Your code is ready!"); +} - log(chalk.yellow(`You chose: ${appType}`)); +async function chooseAndCloneContract() { + const availableContracts = await getAvailableContracts(); + // let user choose one of the contracts in noir-projects + const contract = await select({ + message: `Please choose your Aztec boilerplate:`, + choices: [ + ...availableContracts.map((contract) => { + return { value: contract.name, name: contract.name }; + }), + { value: "skip", name: "Skip this step" }, + ], + }); - const spinner = ora({ - text: "Cloning the boilerplate code...", - color: "blue", + const rootDir = await clone({ + path: "noir-projects/noir-contracts/contracts", + choice: contract, + type: "contract", + tag, + version, }); - try { - // STEP 1: Clone the box - const appName = await input({ - message: "Your app name:", - default: "my-aztec-app", - }); + await replacePaths({ + rootDir, + tag, + version, + prefix: "noir-projects/", + }); - spinner.start(); + await processProject({ + rootDir, + placeholders: getPlaceholders(contract), + }); + success("Your code is ready!"); - const emitter = tiged( - // same as the nargo dependencies above: - // but if the user has set a semver version, we want that tag (i.e. aztec-packages-v0.23.0) - `AztecProtocol/aztec-packages/boxes/${appType}${tag && `#${tag}`}`, - { - verbose: true, - }, - ); + // get the e2e test for that contract from yarn-project/end-to-end +} - emitter.on("info", (info) => { - log(info.message); - }); +export async function chooseProject() { + const projectType = await select({ + message: `Please choose your type of project:`, + choices: [ + { value: "fs_app", name: "Boilerplate project with frontend" }, + { value: "contract_only", name: "Just a contract example" }, + { value: "skip", name: "Skip this step" }, + ], + }); - await emitter.clone(`./${appName}`).then(() => { - replacePaths(`./${appName}`, tag, version); - log(chalk.bgGreen("Your code is ready!")); - }); - } catch (error) { - log(chalk.bgRed(error.message)); - process.exit(1); - } finally { - spinner.stop(); + if (projectType === "skip") { + return; + } else if (projectType === "contract_only") { + await chooseAndCloneContract(); + } else if (projectType === "fs_app") { + await chooseAndCloneBox(); } } diff --git a/boxes/scripts/steps/sandbox/install.js b/boxes/scripts/steps/sandbox/install.js index 40501fe36c7..34926b6045b 100644 --- a/boxes/scripts/steps/sandbox/install.js +++ b/boxes/scripts/steps/sandbox/install.js @@ -2,10 +2,8 @@ import confirm from "@inquirer/confirm"; import { execSync } from "child_process"; import pty from "node-pty"; import { updatePathEnvVar } from "../../utils.js"; -import chalk from "chalk"; -const { log } = console; -const runPty = async (command, { success, error }) => { +const runPty = async (command, { success: exitSuccess, error }) => { try { const ptySession = new Promise((resolve, reject) => { const ptyProcess = pty.spawn("bash", [], { @@ -22,20 +20,20 @@ const runPty = async (command, { success, error }) => { ptyProcess.write(command); - ptyProcess.on("exit", function (exitCode, signal) { - updatePathEnvVar(); + ptyProcess.on("exit", async function (exitCode, signal) { + await updatePathEnvVar(); resolve(); if (exitCode === 0) { - log(chalk.bgGreen(success)); + success(exitSuccess); } else { - reject(chalk.bgRed(error)); + error(e); } }); }); await ptySession; - } catch (error) { - log(chalk.bgRed(error)); + } catch (e) { + error(e); } }; @@ -78,15 +76,13 @@ function findOutUserVersion() { return sandboxVersion; } -export async function sandboxInstallOrUpdate(latestStable, versionToInstall) { +export async function sandboxInstallOrUpdate() { // Checking for docker try { execSync("docker info >/dev/null 2>&1"); - } catch (error) { - log( - chalk.bgRed( - "Doesn't seem like Docker is installed or running. Please start it or visit https://docs.aztec.network for more information", - ), + } catch (e) { + error( + "Doesn't seem like Docker is installed or running. Please start it or visit https://docs.aztec.network for more information", ); process.exit(1); } @@ -116,10 +112,10 @@ export async function sandboxInstallOrUpdate(latestStable, versionToInstall) { // Another situation is where the sandbox matches the stable version (i.e. 0.24.0) or master (sandboxVersion === latestStable || sandboxVersion === "master") && // but the user has chosen a different version (i.e. "master", 0.23.0, etc) - sandboxVersion !== versionToInstall + sandboxVersion !== version ) { const answer = await confirm({ - message: `The sandbox is version ${sandboxVersion} but your chosen version is ${versionToInstall}. Do you want to install version ${versionToInstall}?`, + message: `The sandbox is version ${sandboxVersion} but your chosen version is ${version}. Do you want to install version ${version}?`, default: true, }); @@ -130,13 +126,13 @@ export async function sandboxInstallOrUpdate(latestStable, versionToInstall) { } else if ( // Finally, there's a situation where // the user didn't want any specific version - sandboxVersion !== versionToInstall && + sandboxVersion !== version && // and the sandbox is not up to date // so we need to update to that since the cloned repo is also the latest sandboxVersion !== latestStable && // we're also aware that the user might be on master // so his version is actually not outdated! - versionToInstall !== "master" + version !== "master" ) { const answer = await confirm({ message: `The Sandbox is not up to date. Do you want to update it to ${latestStable}?`, diff --git a/boxes/scripts/steps/sandbox/run.js b/boxes/scripts/steps/sandbox/run.js index a54f438f276..2a6eed9ab0c 100644 --- a/boxes/scripts/steps/sandbox/run.js +++ b/boxes/scripts/steps/sandbox/run.js @@ -1,15 +1,9 @@ import confirm from "@inquirer/confirm"; import { execSync } from "child_process"; -import chalk from "chalk"; import axios from "axios"; -import ora from "ora"; -const { log } = console; -export async function sandboxRun(version) { - const spinner = ora({ - text: "Trying to reach the sandbox...", - color: "blue", - }); +export async function sandboxRun() { + spinner.text = "Trying to reach the sandbox..."; try { spinner.start(); @@ -25,10 +19,11 @@ export async function sandboxRun(version) { id: "null", }), }); - spinner.stop(); - log(chalk.green("The Sandbox already running!")); + spinner.succeed(); + success("The Sandbox is already running!"); + process.exit(0); } catch (error) { - spinner.stop(); + spinner.fail(); const answer = await confirm({ message: "Sandbox can't be reached on localhost:8080. Do you want to start it?", @@ -36,13 +31,9 @@ export async function sandboxRun(version) { }); if (answer) { - log( - chalk.green("Starting the sandbox... This might take a few minutes."), - ); - log(chalk.bgGreen(`Go and explore the boilerplate code while you wait!`)); + info("Starting the sandbox... This might take a few minutes."); + info(`Go and explore the boilerplate code while you wait!`); execSync(`$HOME/.aztec/bin/aztec sandbox`, { stdio: "inherit" }); } - } finally { - spinner.stop(); } } diff --git a/boxes/scripts/utils.js b/boxes/scripts/utils.js index 97959ff8b01..a5fc790d313 100644 --- a/boxes/scripts/utils.js +++ b/boxes/scripts/utils.js @@ -1,60 +1,136 @@ import path from "path"; import os from "os"; -import fs from "fs"; +import fs from "fs/promises"; import { parse, stringify } from "@iarna/toml"; -import { default as axiosBase } from "axios"; +import { CONTRACTS_TO_SHOW, AZTEC_REPO } from "./config.js"; + +import input from "@inquirer/input"; +import tiged from "tiged"; -const { log, warn, info } = console; const targetDir = path.join(os.homedir(), ".aztec/bin"); // Use os.homedir() to get $HOME -const { GITHUB_TOKEN } = process.env; -const axiosOpts = {}; -if (GITHUB_TOKEN) { - axiosOpts.headers = { Authorization: `token ${GITHUB_TOKEN}` }; -} +export async function getAvailableBoxes() { + try { + const data = await github({ + path: `boxes/boxes${tag == "master" ? "" : `?ref=${tag}`}`, + }); -export const axios = axiosBase.create(axiosOpts); + let availableBoxes = data + .filter( + (content) => content.type === "dir" && !content.name.startsWith("."), + ) + .map(async ({ path, name }) => { + const { description } = await github({ + path: `${tag == "master" ? "master" : tag}/${path}/package.json`, + raw: true, + }); + + return { + name, + description: description || name, + }; + }); -export async function getAvailableBoxes(tag, version) { - const { GITHUB_TOKEN } = process.env; - const axiosOpts = {}; - if (GITHUB_TOKEN) { - axiosOpts.headers = { Authorization: `token ${GITHUB_TOKEN}` }; + return await Promise.all(availableBoxes); + } catch (e) { + error(e); } +} - // TODO: Remove this try catch. Boxes are currently in "boxes" but from this PR on, they will be in "boxes/boxes" - let data; +export async function getAvailableContracts() { try { - ({ data } = await axios.get( - `https://api.github.com/repos/AztecProtocol/aztec-packages/contents/boxes/boxes${tag == "master" ? "" : `?ref=${tag}`}`, - axiosOpts, - )); + const data = await github({ + path: `noir-projects/noir-contracts/contracts${tag == "master" ? "" : `?ref=${tag}`}`, + }); + let availableContracts = data.filter((content) => + CONTRACTS_TO_SHOW.includes(content.name), + ); + + return await Promise.all(availableContracts); } catch (e) { - if (e.response.statusText === "Not Found") { - ({ data } = await axios.get( - `https://api.github.com/repos/AztecProtocol/aztec-packages/contents/boxes${tag == "master" ? "" : `?ref=${tag}`}`, - axiosOpts, - )); + error(e); + } +} + +export async function clone({ path, choice, type }) { + const appName = await input({ + message: `Your ${type} name:`, + default: `my-aztec-${type}`, + }); + + spinner.text = `Cloning the ${type} code...`; + try { + spinner.start(); + + const emitter = tiged( + `${AZTEC_REPO}/${path}/${choice}${tag && `#${tag}`}`, + { verbose: true }, + ); + emitter.on("info", ({ message }) => debug(message)); + emitter.on("warn", ({ message }) => error(message)); + await emitter.clone(`./${appName}`); + + if (type === "contract") { + spinner.text = `Cloning default contract project...`; + const baseEmitter = tiged( + `${AZTEC_REPO}/boxes/contract-only${tag && `#${tag}`}`, + { verbose: true }, + ); + baseEmitter.on("info", debug); + baseEmitter.on("warn", error); + await baseEmitter.clone(`./${appName}/base`); + await fs.cp(`./${appName}/base`, `./${appName}`, { + recursive: true, + force: true, + }); + await fs.rm(`./${appName}/base`, { recursive: true, force: true }); } + spinner.succeed(); + return `./${appName}`; + } catch (e) { + spinner.fail(); + error(e); + process.exit(1); } +} - let availableBoxes = data - .filter( - (content) => content.type === "dir" && !content.name.startsWith("."), - ) - .map(async ({ path, name }) => { - ({ data } = await axios.get( - `https://raw.githubusercontent.com/AztecProtocol/aztec-packages/${tag == "master" ? "master" : tag}/${path}/package.json`, - axiosOpts, - )); - - return { - name, - description: data.description || name, - }; - }); +export async function processProject({ rootDir, placeholders }) { + spinner.text = `Processing the code...`; + try { + spinner.start(); + const processes = []; + const findAndReplace = async (dir, placeholders) => { + const files = await fs.readdir(dir, { + withFileTypes: true, + }); + files.forEach(async (file) => { + const filePath = path.join(dir, file.name); + if (file.isDirectory()) { + findAndReplace(filePath, placeholders); + } else { + processes.push( + new Promise(async (resolve, reject) => { + let content = await fs.readFile(filePath, "utf8"); + placeholders.forEach(({ key, value }) => { + content = content.replace(new RegExp(key, "g"), value); + }); + await fs.writeFile(filePath, content, "utf8"); + + resolve(); + }), + ); + } + }); + }; - return await Promise.all(availableBoxes); + await findAndReplace(path.resolve(rootDir), placeholders); + await Promise.all(processes); + spinner.succeed(); + } catch (e) { + spinner.fail(); + error(e); + process.exit(1); + } } export function prettyPrintNargoToml(config) { @@ -75,7 +151,7 @@ export function prettyPrintNargoToml(config) { ); } -export function updatePathEnvVar() { +export async function updatePathEnvVar() { // Detect the user's shell profile file based on common shells and environment variables const homeDir = os.homedir(); let shellProfile; @@ -90,63 +166,85 @@ export function updatePathEnvVar() { } // Read the current content of the shell profile to check if the path is already included - const profileContent = fs.readFileSync(shellProfile, "utf8"); + const profileContent = await fs.readFile(shellProfile, "utf8"); if (profileContent.includes(targetDir)) { - log(`${targetDir} is already in PATH.`); + info(`${targetDir} is already in PATH.`); return; } // Append the export command to the shell profile file const exportCmd = `\nexport PATH="$PATH:${targetDir}" # Added by Node.js script\n`; - fs.appendFileSync(shellProfile, exportCmd); + await fs.appendFile(shellProfile, exportCmd); info(`Added ${targetDir} to PATH in ${shellProfile}.`); } -export async function replacePaths(rootDir, tag, version) { - const files = fs.readdirSync(path.resolve(".", rootDir), { - withFileTypes: true, - }); +export async function replacePaths({ rootDir, prefix = "" }) { + spinner.text = `Replacing paths...`; - files.forEach((file) => { - const filePath = path.join(rootDir, file.name); - if (file.isDirectory()) { - replacePaths(filePath, tag, version); // Recursively search subdirectories - } else if (file.name === "Nargo.toml") { - let content = parse(fs.readFileSync(filePath, "utf8")); - - try { - Object.keys(content.dependencies).forEach((dep) => { - const directory = content.dependencies[dep].path.replace( - /^(..\/)+/, - "", + try { + spinner.start(); + const replaces = []; + const findAndReplace = async (dir, prefix) => { + const files = await fs.readdir(dir, { + withFileTypes: true, + }); + files.forEach(async (file) => { + const filePath = path.join(dir, file.name); + if (file.isDirectory()) { + findAndReplace(filePath, prefix); // Recursively search subdirectories + } else if (file.name === "Nargo.toml") { + replaces.push( + new Promise(async (resolve, reject) => { + let content = parse(await fs.readFile(filePath, "utf8")); + + Object.keys(content.dependencies).forEach((dep) => { + const directory = content.dependencies[dep].path.replace( + /^(..\/)+/, + "", + ); + content.dependencies[dep] = { + git: `https://github.com/${AZTEC_REPO}/`, + tag, + directory: `${prefix}${directory}`, + }; + }); + + await fs.writeFile( + filePath, + prettyPrintNargoToml(content), + "utf8", + ); + resolve(); + }), ); - content.dependencies[dep] = { - git: "https://github.com/AztecProtocol/aztec-packages/", - tag, - directory, - }; - }); - } catch (e) { - log(e); - } - - fs.writeFileSync(filePath, prettyPrintNargoToml(content), "utf8"); - } else if (file.name === "package.json") { - try { - let content = JSON.parse(fs.readFileSync(filePath, "utf8")); - Object.keys(content.dependencies) - .filter((deps) => deps.match("@aztec")) - // "master" actually means "latest" for the npm release - .map( - (dep) => - (content.dependencies[dep] = - `${version === "master" ? "latest" : `^${version}`}`), + } else if (file.name === "package.json") { + replaces.push( + new Promise(async (resolve, reject) => { + let content = JSON.parse(await fs.readFile(filePath, "utf8")); + Object.keys(content.dependencies) + .filter((deps) => deps.match("@aztec")) + // "master" actually means "latest" for the npm release + .map( + (dep) => + (content.dependencies[dep] = + `${version === "master" ? "latest" : `^${version}`}`), + ); + await fs.writeFile(filePath, JSON.stringify(content), "utf8"); + resolve(); + }), ); - fs.writeFileSync(filePath, JSON.stringify(content), "utf8"); - } catch (e) { - log("No package.json to update"); - } - } - }); + } + }); + }; + + await findAndReplace(path.resolve(rootDir), prefix); + await Promise.all(replaces); + spinner.succeed(); + return; + } catch (e) { + spinner.fail(); + error(e); + process.exit(1); + } } diff --git a/boxes/yarn.lock b/boxes/yarn.lock index 20a71a90baa..dfcaf49a4d5 100644 --- a/boxes/yarn.lock +++ b/boxes/yarn.lock @@ -2159,6 +2159,15 @@ __metadata: languageName: node linkType: hard +"abort-controller@npm:^3.0.0": + version: 3.0.0 + resolution: "abort-controller@npm:3.0.0" + dependencies: + event-target-shim: "npm:^5.0.0" + checksum: 10c0/90ccc50f010250152509a344eb2e71977fbf8db0ab8f1061197e3275ddf6c61a41a6edfd7b9409c664513131dd96e962065415325ef23efa5db931b382d24ca5 + languageName: node + linkType: hard + "abstract-leveldown@npm:^7.2.0": version: 7.2.0 resolution: "abstract-leveldown@npm:7.2.0" @@ -2592,6 +2601,13 @@ __metadata: languageName: node linkType: hard +"atomic-sleep@npm:^1.0.0": + version: 1.0.0 + resolution: "atomic-sleep@npm:1.0.0" + checksum: 10c0/e329a6665512736a9bbb073e1761b4ec102f7926cce35037753146a9db9c8104f5044c1662e4a863576ce544fb8be27cd2be6bc8c1a40147d03f31eb1cfb6e8a + languageName: node + linkType: hard + "autoprefixer@npm:^10.4.15": version: 10.4.18 resolution: "autoprefixer@npm:10.4.18" @@ -3376,7 +3392,7 @@ __metadata: languageName: node linkType: hard -"colorette@npm:^2.0.10, colorette@npm:^2.0.14": +"colorette@npm:^2.0.10, colorette@npm:^2.0.14, colorette@npm:^2.0.7": version: 2.0.20 resolution: "colorette@npm:2.0.20" checksum: 10c0/e94116ff33b0ff56f3b83b9ace895e5bf87c2a7a47b3401b8c3f3226e050d5ef76cf4072fb3325f9dc24d1698f9b730baf4e05eeaf861d74a1883073f4c98a40 @@ -3582,10 +3598,11 @@ __metadata: "@inquirer/input": "npm:^2.0.0" "@inquirer/select": "npm:^2.0.0" axios: "npm:^1.6.7" - chalk: "npm:^5.3.0" commander: "npm:^12.0.0" node-pty: "npm:^1.0.0" ora: "npm:^8.0.1" + pino: "npm:^8.19.0" + pino-pretty: "npm:^10.3.1" tiged: "npm:^2.12.6" bin: create-aztec-app: bin.js @@ -3700,6 +3717,13 @@ __metadata: languageName: node linkType: hard +"dateformat@npm:^4.6.3": + version: 4.6.3 + resolution: "dateformat@npm:4.6.3" + checksum: 10c0/e2023b905e8cfe2eb8444fb558562b524807a51cdfe712570f360f873271600b5c94aebffaf11efb285e2c072264a7cf243eadb68f3eba0f8cc85fb86cd25df6 + languageName: node + linkType: hard + "debug@npm:2.6.9": version: 2.6.9 resolution: "debug@npm:2.6.9" @@ -4095,6 +4119,15 @@ __metadata: languageName: node linkType: hard +"end-of-stream@npm:^1.1.0": + version: 1.4.4 + resolution: "end-of-stream@npm:1.4.4" + dependencies: + once: "npm:^1.4.0" + checksum: 10c0/870b423afb2d54bb8d243c63e07c170409d41e20b47eeef0727547aea5740bd6717aca45597a9f2745525667a6b804c1e7bede41f856818faee5806dd9ff3975 + languageName: node + linkType: hard + "enhanced-resolve@npm:^5.0.0, enhanced-resolve@npm:^5.12.0, enhanced-resolve@npm:^5.15.0": version: 5.15.1 resolution: "enhanced-resolve@npm:5.15.1" @@ -4557,6 +4590,13 @@ __metadata: languageName: node linkType: hard +"event-target-shim@npm:^5.0.0": + version: 5.0.1 + resolution: "event-target-shim@npm:5.0.1" + checksum: 10c0/0255d9f936215fd206156fd4caa9e8d35e62075d720dc7d847e89b417e5e62cf1ce6c9b4e0a1633a9256de0efefaf9f8d26924b1f3c8620cffb9db78e7d3076b + languageName: node + linkType: hard + "eventemitter3@npm:^4.0.0": version: 4.0.7 resolution: "eventemitter3@npm:4.0.7" @@ -4564,7 +4604,7 @@ __metadata: languageName: node linkType: hard -"events@npm:^3.2.0": +"events@npm:^3.2.0, events@npm:^3.3.0": version: 3.3.0 resolution: "events@npm:3.3.0" checksum: 10c0/d6b6f2adbccbcda74ddbab52ed07db727ef52e31a61ed26db9feb7dc62af7fc8e060defa65e5f8af9449b86b52cc1a1f6a79f2eafcf4e62add2b7a1fa4a432f6 @@ -4665,6 +4705,13 @@ __metadata: languageName: node linkType: hard +"fast-copy@npm:^3.0.0": + version: 3.0.1 + resolution: "fast-copy@npm:3.0.1" + checksum: 10c0/a8310dbcc4c94ed001dc3e0bbc3c3f0491bb04e6c17163abe441a54997ba06cdf1eb532c2f05e54777c6f072c84548c23ef0ecd54665cd611be1d42f37eca258 + languageName: node + linkType: hard + "fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -4706,6 +4753,20 @@ __metadata: languageName: node linkType: hard +"fast-redact@npm:^3.1.1": + version: 3.4.0 + resolution: "fast-redact@npm:3.4.0" + checksum: 10c0/4e2ba1de87a11a24d35a2a9b2f5736107df1d1740e97a6b3103a8db5134de2a32a19d41210e66470322b08352bff8743527d18b4003b0ee04ead51b4c2fcfb97 + languageName: node + linkType: hard + +"fast-safe-stringify@npm:^2.1.1": + version: 2.1.1 + resolution: "fast-safe-stringify@npm:2.1.1" + checksum: 10c0/d90ec1c963394919828872f21edaa3ad6f1dddd288d2bd4e977027afff09f5db40f94e39536d4646f7e01761d704d72d51dce5af1b93717f3489ef808f5f4e4d + languageName: node + linkType: hard + "fast-url-parser@npm:1.1.3": version: 1.1.3 resolution: "fast-url-parser@npm:1.1.3" @@ -5432,6 +5493,13 @@ __metadata: languageName: node linkType: hard +"help-me@npm:^5.0.0": + version: 5.0.0 + resolution: "help-me@npm:5.0.0" + checksum: 10c0/054c0e2e9ae2231c85ab5e04f75109b9d068ffcc54e58fb22079822a5ace8ff3d02c66fd45379c902ad5ab825e5d2e1451fcc2f7eab1eb49e7d488133ba4cacb + languageName: node + linkType: hard + "hmac-drbg@npm:^1.0.1": version: 1.0.1 resolution: "hmac-drbg@npm:1.0.1" @@ -6759,6 +6827,13 @@ __metadata: languageName: node linkType: hard +"joycon@npm:^3.1.1": + version: 3.1.1 + resolution: "joycon@npm:3.1.1" + checksum: 10c0/131fb1e98c9065d067fd49b6e685487ac4ad4d254191d7aa2c9e3b90f4e9ca70430c43cad001602bdbdabcf58717d3b5c5b7461c1bd8e39478c8de706b3fe6ae + languageName: node + linkType: hard + "js-base64@npm:^2.4.9": version: 2.6.4 resolution: "js-base64@npm:2.6.4" @@ -8086,6 +8161,13 @@ __metadata: languageName: node linkType: hard +"on-exit-leak-free@npm:^2.1.0": + version: 2.1.2 + resolution: "on-exit-leak-free@npm:2.1.2" + checksum: 10c0/faea2e1c9d696ecee919026c32be8d6a633a7ac1240b3b87e944a380e8a11dc9c95c4a1f8fb0568de7ab8db3823e790f12bda45296b1d111e341aad3922a0570 + languageName: node + linkType: hard + "on-finished@npm:2.4.1, on-finished@npm:^2.3.0": version: 2.4.1 resolution: "on-finished@npm:2.4.1" @@ -8102,7 +8184,7 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0": +"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -8373,6 +8455,68 @@ __metadata: languageName: node linkType: hard +"pino-abstract-transport@npm:^1.0.0, pino-abstract-transport@npm:v1.1.0": + version: 1.1.0 + resolution: "pino-abstract-transport@npm:1.1.0" + dependencies: + readable-stream: "npm:^4.0.0" + split2: "npm:^4.0.0" + checksum: 10c0/6e9b9d5a2c0a37f91ecaf224d335daae1ae682b1c79a05b06ef9e0f0a5d289f8e597992217efc857796dae6f1067e9b4882f95c6228ff433ddc153532cae8aca + languageName: node + linkType: hard + +"pino-pretty@npm:^10.3.1": + version: 10.3.1 + resolution: "pino-pretty@npm:10.3.1" + dependencies: + colorette: "npm:^2.0.7" + dateformat: "npm:^4.6.3" + fast-copy: "npm:^3.0.0" + fast-safe-stringify: "npm:^2.1.1" + help-me: "npm:^5.0.0" + joycon: "npm:^3.1.1" + minimist: "npm:^1.2.6" + on-exit-leak-free: "npm:^2.1.0" + pino-abstract-transport: "npm:^1.0.0" + pump: "npm:^3.0.0" + readable-stream: "npm:^4.0.0" + secure-json-parse: "npm:^2.4.0" + sonic-boom: "npm:^3.0.0" + strip-json-comments: "npm:^3.1.1" + bin: + pino-pretty: bin.js + checksum: 10c0/6964fba5acc7a9f112e4c6738d602e123daf16cb5f6ddc56ab4b6bb05059f28876d51da8f72358cf1172e95fa12496b70465431a0836df693c462986d050686b + languageName: node + linkType: hard + +"pino-std-serializers@npm:^6.0.0": + version: 6.2.2 + resolution: "pino-std-serializers@npm:6.2.2" + checksum: 10c0/8f1c7f0f0d8f91e6c6b5b2a6bfb48f06441abeb85f1c2288319f736f9c6d814fbeebe928d2314efc2ba6018fa7db9357a105eca9fc99fc1f28945a8a8b28d3d5 + languageName: node + linkType: hard + +"pino@npm:^8.19.0": + version: 8.19.0 + resolution: "pino@npm:8.19.0" + dependencies: + atomic-sleep: "npm:^1.0.0" + fast-redact: "npm:^3.1.1" + on-exit-leak-free: "npm:^2.1.0" + pino-abstract-transport: "npm:v1.1.0" + pino-std-serializers: "npm:^6.0.0" + process-warning: "npm:^3.0.0" + quick-format-unescaped: "npm:^4.0.3" + real-require: "npm:^0.2.0" + safe-stable-stringify: "npm:^2.3.1" + sonic-boom: "npm:^3.7.0" + thread-stream: "npm:^2.0.0" + bin: + pino: bin.js + checksum: 10c0/53e6e9db91e451163e93294b0a7c5c8135742d58909dfc4a6fa1afc155b2b0dc44448ec3d057e08351951f9a3ea67e6ea8e72e952b64a1d889f4d5376cbd1a5d + languageName: node + linkType: hard + "pirates@npm:^4.0.4": version: 4.0.6 resolution: "pirates@npm:4.0.6" @@ -8566,6 +8710,20 @@ __metadata: languageName: node linkType: hard +"process-warning@npm:^3.0.0": + version: 3.0.0 + resolution: "process-warning@npm:3.0.0" + checksum: 10c0/60f3c8ddee586f0706c1e6cb5aa9c86df05774b9330d792d7c8851cf0031afd759d665404d07037e0b4901b55c44a423f07bdc465c63de07d8d23196bb403622 + languageName: node + linkType: hard + +"process@npm:^0.11.10": + version: 0.11.10 + resolution: "process@npm:0.11.10" + checksum: 10c0/40c3ce4b7e6d4b8c3355479df77aeed46f81b279818ccdc500124e6a5ab882c0cc81ff7ea16384873a95a74c4570b01b120f287abbdd4c877931460eca6084b3 + languageName: node + linkType: hard + "promise-inflight@npm:^1.0.1": version: 1.0.1 resolution: "promise-inflight@npm:1.0.1" @@ -8617,6 +8775,16 @@ __metadata: languageName: node linkType: hard +"pump@npm:^3.0.0": + version: 3.0.0 + resolution: "pump@npm:3.0.0" + dependencies: + end-of-stream: "npm:^1.1.0" + once: "npm:^1.3.1" + checksum: 10c0/bbdeda4f747cdf47db97428f3a135728669e56a0ae5f354a9ac5b74556556f5446a46f720a8f14ca2ece5be9b4d5d23c346db02b555f46739934cc6c093a5478 + languageName: node + linkType: hard + "punycode@npm:^1.3.2": version: 1.4.1 resolution: "punycode@npm:1.4.1" @@ -8663,6 +8831,13 @@ __metadata: languageName: node linkType: hard +"quick-format-unescaped@npm:^4.0.3": + version: 4.0.4 + resolution: "quick-format-unescaped@npm:4.0.4" + checksum: 10c0/fe5acc6f775b172ca5b4373df26f7e4fd347975578199e7d74b2ae4077f0af05baa27d231de1e80e8f72d88275ccc6028568a7a8c9ee5e7368ace0e18eff93a4 + languageName: node + linkType: hard + "quick-lru@npm:^4.0.1": version: 4.0.1 resolution: "quick-lru@npm:4.0.1" @@ -8822,6 +8997,19 @@ __metadata: languageName: node linkType: hard +"readable-stream@npm:^4.0.0": + version: 4.5.2 + resolution: "readable-stream@npm:4.5.2" + dependencies: + abort-controller: "npm:^3.0.0" + buffer: "npm:^6.0.3" + events: "npm:^3.3.0" + process: "npm:^0.11.10" + string_decoder: "npm:^1.3.0" + checksum: 10c0/a2c80e0e53aabd91d7df0330929e32d0a73219f9477dbbb18472f6fdd6a11a699fc5d172a1beff98d50eae4f1496c950ffa85b7cc2c4c196963f289a5f39275d + languageName: node + linkType: hard + "readdirp@npm:~3.6.0": version: 3.6.0 resolution: "readdirp@npm:3.6.0" @@ -8831,6 +9019,13 @@ __metadata: languageName: node linkType: hard +"real-require@npm:^0.2.0": + version: 0.2.0 + resolution: "real-require@npm:0.2.0" + checksum: 10c0/23eea5623642f0477412ef8b91acd3969015a1501ed34992ada0e3af521d3c865bb2fe4cdbfec5fe4b505f6d1ef6a03e5c3652520837a8c3b53decff7e74b6a0 + languageName: node + linkType: hard + "rechoir@npm:^0.8.0": version: 0.8.0 resolution: "rechoir@npm:0.8.0" @@ -9101,6 +9296,13 @@ __metadata: languageName: node linkType: hard +"safe-stable-stringify@npm:^2.3.1": + version: 2.4.3 + resolution: "safe-stable-stringify@npm:2.4.3" + checksum: 10c0/81dede06b8f2ae794efd868b1e281e3c9000e57b39801c6c162267eb9efda17bd7a9eafa7379e1f1cacd528d4ced7c80d7460ad26f62ada7c9e01dec61b2e768 + languageName: node + linkType: hard + "safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0": version: 2.1.2 resolution: "safer-buffer@npm:2.1.2" @@ -9188,6 +9390,13 @@ __metadata: languageName: node linkType: hard +"secure-json-parse@npm:^2.4.0": + version: 2.7.0 + resolution: "secure-json-parse@npm:2.7.0" + checksum: 10c0/f57eb6a44a38a3eeaf3548228585d769d788f59007454214fab9ed7f01fbf2e0f1929111da6db28cf0bcc1a2e89db5219a59e83eeaec3a54e413a0197ce879e4 + languageName: node + linkType: hard + "select-hose@npm:^2.0.0": version: 2.0.0 resolution: "select-hose@npm:2.0.0" @@ -9536,6 +9745,15 @@ __metadata: languageName: node linkType: hard +"sonic-boom@npm:^3.0.0, sonic-boom@npm:^3.7.0": + version: 3.8.0 + resolution: "sonic-boom@npm:3.8.0" + dependencies: + atomic-sleep: "npm:^1.0.0" + checksum: 10c0/f3f61cb3fd5d4aad862dd957f22318ef85bf47d4f12ba27b915112908449f752dbdfc95a4739d2b4a9b2770e1e08d349adae9d1030fdab2a3d86128c6773a7f4 + languageName: node + linkType: hard + "source-map-js@npm:^1.0.2": version: 1.0.2 resolution: "source-map-js@npm:1.0.2" @@ -9638,6 +9856,13 @@ __metadata: languageName: node linkType: hard +"split2@npm:^4.0.0": + version: 4.2.0 + resolution: "split2@npm:4.2.0" + checksum: 10c0/b292beb8ce9215f8c642bb68be6249c5a4c7f332fc8ecadae7be5cbdf1ea95addc95f0459ef2e7ad9d45fd1064698a097e4eb211c83e772b49bc0ee423e91534 + languageName: node + linkType: hard + "sprintf-js@npm:^1.1.3": version: 1.1.3 resolution: "sprintf-js@npm:1.1.3" @@ -9804,7 +10029,7 @@ __metadata: languageName: node linkType: hard -"string_decoder@npm:^1.1.1": +"string_decoder@npm:^1.1.1, string_decoder@npm:^1.3.0": version: 1.3.0 resolution: "string_decoder@npm:1.3.0" dependencies: @@ -10012,6 +10237,15 @@ __metadata: languageName: node linkType: hard +"thread-stream@npm:^2.0.0": + version: 2.4.1 + resolution: "thread-stream@npm:2.4.1" + dependencies: + real-require: "npm:^0.2.0" + checksum: 10c0/ce29265810b9550ce896726301ff006ebfe96b90292728f07cfa4c379740585583046e2a8018afc53aca66b18fed12b33a84f3883e7ebc317185f6682898b8f8 + languageName: node + linkType: hard + "thunky@npm:^1.0.2": version: 1.1.0 resolution: "thunky@npm:1.1.0" diff --git a/docs/docs/developers/contracts/writing_contracts/functions/context.md b/docs/docs/developers/contracts/writing_contracts/functions/context.md index 8f4455fc3cd..f878aae70fc 100644 --- a/docs/docs/developers/contracts/writing_contracts/functions/context.md +++ b/docs/docs/developers/contracts/writing_contracts/functions/context.md @@ -14,7 +14,7 @@ On this page, you'll learn - The details and functionalities of the private context in Aztec.nr - Difference between the private and public contexts and their unified APIs -- Components of the private context, such as inputs, block header, and contract deployment data +- Components of the private context, such as inputs and block header. - Elements like return values, read requests, new note hashes, and nullifiers in transaction processing - Differences between the private and public contexts, especially the unique features and variables in the public context @@ -42,7 +42,7 @@ The context inputs includes all of the information that is passed from the kerne #include_code private-context-inputs /noir-projects/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr rust -As shown in the snippet, the application context is made up of 4 main structures. The call context, the block header, the contract deployment data and the private global variables. +As shown in the snippet, the application context is made up of 4 main structures. The call context, the block header, and the private global variables. First of all, the call context. @@ -67,7 +67,6 @@ The call context contains information about the current call being made: - Furthermore there are a series of flags that are stored within the application context: - is_delegate_call: Denotes whether the current call is a delegate call. If true, then the storage contract address will be the address of the sender. - is_static_call: This will be set if and only if the current call is a static call. In a static call, state changing altering operations are not allowed. - - is_contract_deployment: This will be set if and only if the current call is the contract's constructor. ### Header @@ -77,12 +76,6 @@ In the public context this header is set by sequencer (sequencer executes public #include_code header /noir-projects/noir-protocol-circuits/crates/types/src/header.nr rust -### Contract Deployment Data - -Just like with the `is_contract_deployment` flag mentioned earlier. This data will only be set to true when the current transaction is one in which a contract is being deployed. - -#include_code contract-deployment-data /noir-projects/noir-protocol-circuits/crates/types/src/contrakt/contract_deployment_data.nr rust - ### Private Global Variables In the private execution context, we only have access to a subset of the total global variables, we are restricted to those which can be reliably proven by the kernel circuits. @@ -137,7 +130,7 @@ The Public Context includes all of the information passed from the `Public VM` i ### Public Context Inputs -In the current version of the system, the public context is almost a clone of the private execution context. It contains the same call context data, access to the same historical tree roots, however it does NOT have access to contract deployment data, this is due to traditional contract deployments only currently being possible from private transactions. +In the current version of the system, the public context is almost a clone of the private execution context. #include_code public-context-inputs /noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr rust diff --git a/docs/docs/developers/getting_started/aztecjs-getting-started.md b/docs/docs/developers/getting_started/aztecjs-getting-started.md index 9fa784129dc..330f9a787a3 100644 --- a/docs/docs/developers/getting_started/aztecjs-getting-started.md +++ b/docs/docs/developers/getting_started/aztecjs-getting-started.md @@ -137,9 +137,6 @@ A successful run should show something like this: token outboxAddress: EthAddress { token buffer: token }, - token contractDeploymentEmitterAddress: EthAddress { - token buffer: - token } token } token } +0ms ``` @@ -182,9 +179,6 @@ Now that we have our accounts loaded, let's move on to deploy our pre-compiled t token outboxAddress: EthAddress { token buffer: token }, - token contractDeploymentEmitterAddress: EthAddress { - token buffer: - token } token } token } +0ms token Loaded alice's account at 0x25048e8c...70d0 +4s @@ -233,9 +227,6 @@ Running now should yield output: token outboxAddress: EthAddress { token buffer: token }, - token contractDeploymentEmitterAddress: EthAddress { - token buffer: - token } token } token } +0ms token Loaded alice's account at 0x25048e8c...70d0 +4s @@ -294,9 +285,6 @@ Our output should now look like this: token outboxAddress: EthAddress { token buffer: token }, - token contractDeploymentEmitterAddress: EthAddress { - token buffer: - token } token } token } +0ms token Loaded alice's account at 0x25048e8c...70d0 +4s @@ -350,9 +338,6 @@ Our complete output should now be something like: token outboxAddress: EthAddress { token buffer: token }, - token contractDeploymentEmitterAddress: EthAddress { - token buffer: - token } token } token } +0ms token Loaded alice's account at 0x25048e8c...70d0 +4s diff --git a/docs/docs/developers/getting_started/quickstart.md b/docs/docs/developers/getting_started/quickstart.md index 6f22059ce4f..13caa41e093 100644 --- a/docs/docs/developers/getting_started/quickstart.md +++ b/docs/docs/developers/getting_started/quickstart.md @@ -98,3 +98,5 @@ Congratulations! You are all set up with the Aztec sandbox! To deploy and interact with a contract using Aztec.js, go to the [next page](aztecnr-getting-started.md). You can also dig more into the sandbox and CLI [here](../sandbox/main.md). + +To learn more about writing contracts, consider jumping to the [tutorials section](../tutorials/main.md). diff --git a/docs/docs/developers/sandbox/references/sandbox-reference.md b/docs/docs/developers/sandbox/references/sandbox-reference.md index 04048676ccc..408572796eb 100644 --- a/docs/docs/developers/sandbox/references/sandbox-reference.md +++ b/docs/docs/developers/sandbox/references/sandbox-reference.md @@ -133,7 +133,6 @@ REGISTRY_CONTRACT_ADDRESS=0x01234567890abcde01234567890abcde INBOX_CONTRACT_ADDRESS=0x01234567890abcde01234567890abcde OUTBOX_CONTRACT_ADDRESS=0x01234567890abcde01234567890abcde ROLLUP_CONTRACT_ADDRESS=0x01234567890abcde01234567890abcde -CONTRACT_DEPLOYMENT_EMITTER_ADDRESS=0x01234567890abcde01234567890abcde ## Sequencer variables ## SEQ_PUBLISHER_PRIVATE_KEY=0x01234567890abcde01234567890abcde # Private key of an ethereum account that will be used by the sequencer to publish blocks. diff --git a/iac/mainnet-fork/scripts/install_foundry.sh b/iac/mainnet-fork/scripts/install_foundry.sh index 3842f6a4318..e5f878288bd 100755 --- a/iac/mainnet-fork/scripts/install_foundry.sh +++ b/iac/mainnet-fork/scripts/install_foundry.sh @@ -6,6 +6,7 @@ FOUNDRY_BIN_DIR="$FOUNDRY_DIR/bin" BIN_URL="https://raw.githubusercontent.com/foundry-rs/foundry/master/foundryup/foundryup" BIN_PATH="$FOUNDRY_BIN_DIR/foundryup" FOUNDRY_MAN_DIR="$FOUNDRY_DIR/share/man/man1" +FOUNDRY_VERSION="nightly-de33b6af53005037b463318d2628b5cfcaf39916" # Clean rm -rf $FOUNDRY_DIR @@ -18,4 +19,4 @@ chmod +x $BIN_PATH export PATH=$FOUNDRY_BIN_DIR:$PATH # Use version. -foundryup \ No newline at end of file +foundryup --version $FOUNDRY_VERSION diff --git a/l1-contracts/README.md b/l1-contracts/README.md index 183ddf0404d..ddae20c94ed 100644 --- a/l1-contracts/README.md +++ b/l1-contracts/README.md @@ -54,12 +54,6 @@ It is the job of the rollup contract to store the state of the rollup and progre Currently not running any proofs _nor_ access control so blocks can be submitted by anyone and can be complete garbage. -### ContractDeploymentEmitter - -Job: Share Contract Deployment public data on chain. - -For now, this include bytecode for contract deployment, but over time this will be verified for public functions. - --- # Linter diff --git a/l1-contracts/scripts/ci_deploy_contracts.sh b/l1-contracts/scripts/ci_deploy_contracts.sh index ee8d3a987a4..8bf5d65b3b1 100755 --- a/l1-contracts/scripts/ci_deploy_contracts.sh +++ b/l1-contracts/scripts/ci_deploy_contracts.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +set -euo pipefail + export ETHEREUM_HOST=https://$DEPLOY_TAG-mainnet-fork.aztec.network:8545/$FORK_API_KEY REPOSITORY="l1-contracts" @@ -29,7 +31,7 @@ retry docker pull $CLI_IMAGE PRIVATE_KEY=${CONTRACT_PUBLISHER_PRIVATE_KEY#0x} docker run \ $CLI_IMAGE \ - deploy-l1-contracts -u $ETHEREUM_HOST -p $PRIVATE_KEY >./serve/contract_addresses.json + deploy-l1-contracts -u $ETHEREUM_HOST -p $PRIVATE_KEY | tee ./serve/contract_addresses.json ## Result format is: # Rollup Address: 0xe33d37702bb94e83ca09e7dc804c9f4c4ab8ee4a @@ -57,9 +59,6 @@ while IFS= read -r line; do elif [[ $line == *"Outbox"* ]]; then export TF_VAR_OUTBOX_CONTRACT_ADDRESS=$address echo "TF_VAR_OUTBOX_CONTRACT_ADDRESS=$TF_VAR_OUTBOX_CONTRACT_ADDRESS" - elif [[ $line == *"Emitter"* ]]; then - export TF_VAR_CONTRACT_DEPLOYMENT_EMITTER_ADDRESS=$address - echo "TF_VAR_CONTRACT_DEPLOYMENT_EMITTER_ADDRESS=$TF_VAR_CONTRACT_DEPLOYMENT_EMITTER_ADDRESS" elif [[ $line == *"Oracle"* ]]; then export TF_VAR_AVAILABILITY_ORACLE_CONTRACT_ADDRESS=$address echo "TF_VAR_AVAILABILITY_ORACLE_CONTRACT_ADDRESS=$TF_VAR_AVAILABILITY_ORACLE_CONTRACT_ADDRESS" diff --git a/l1-contracts/scripts/install_foundry.sh b/l1-contracts/scripts/install_foundry.sh index e085beb76d5..e5f878288bd 100755 --- a/l1-contracts/scripts/install_foundry.sh +++ b/l1-contracts/scripts/install_foundry.sh @@ -6,6 +6,7 @@ FOUNDRY_BIN_DIR="$FOUNDRY_DIR/bin" BIN_URL="https://raw.githubusercontent.com/foundry-rs/foundry/master/foundryup/foundryup" BIN_PATH="$FOUNDRY_BIN_DIR/foundryup" FOUNDRY_MAN_DIR="$FOUNDRY_DIR/share/man/man1" +FOUNDRY_VERSION="nightly-de33b6af53005037b463318d2628b5cfcaf39916" # Clean rm -rf $FOUNDRY_DIR @@ -18,4 +19,4 @@ chmod +x $BIN_PATH export PATH=$FOUNDRY_BIN_DIR:$PATH # Use version. -foundryup +foundryup --version $FOUNDRY_VERSION diff --git a/l1-contracts/slither_output.md b/l1-contracts/slither_output.md index 7f202ef2ce5..1d5dc10c830 100644 --- a/l1-contracts/slither_output.md +++ b/l1-contracts/slither_output.md @@ -27,15 +27,15 @@ src/core/Rollup.sol#L58-L103 Impact: Medium Confidence: Medium - [ ] ID-1 -[HeaderLib.decode(bytes).header](src/core/libraries/HeaderLib.sol#L150) is a local variable never initialized +[HeaderLib.decode(bytes).header](src/core/libraries/HeaderLib.sol#L148) is a local variable never initialized -src/core/libraries/HeaderLib.sol#L150 +src/core/libraries/HeaderLib.sol#L148 - [ ] ID-2 -[TxsDecoder.decode(bytes).vars](src/core/libraries/decoders/TxsDecoder.sol#L86) is a local variable never initialized +[TxsDecoder.decode(bytes).vars](src/core/libraries/decoders/TxsDecoder.sol#L79) is a local variable never initialized -src/core/libraries/decoders/TxsDecoder.sol#L86 +src/core/libraries/decoders/TxsDecoder.sol#L79 ## unused-return @@ -57,27 +57,20 @@ src/core/Rollup.sol#L58-L103 Impact: Medium Confidence: High - [ ] ID-5 -Dubious typecast in [TxsDecoder.read4(bytes,uint256)](src/core/libraries/decoders/TxsDecoder.sol#L359-L361): - bytes => bytes4 casting occurs in [uint256(uint32(bytes4(slice(_data,_offset,4))))](src/core/libraries/decoders/TxsDecoder.sol#L360) +Dubious typecast in [TxsDecoder.read1(bytes,uint256)](src/core/libraries/decoders/TxsDecoder.sol#L314-L316): + bytes => bytes1 casting occurs in [uint256(uint8(bytes1(slice(_data,_offset,1))))](src/core/libraries/decoders/TxsDecoder.sol#L315) -src/core/libraries/decoders/TxsDecoder.sol#L359-L361 +src/core/libraries/decoders/TxsDecoder.sol#L314-L316 - [ ] ID-6 -Dubious typecast in [MessagesDecoder.read1(bytes,uint256)](src/core/libraries/decoders/MessagesDecoder.sol#L158-L160): - bytes => bytes1 casting occurs in [uint256(uint8(bytes1(_data)))](src/core/libraries/decoders/MessagesDecoder.sol#L159) - -src/core/libraries/decoders/MessagesDecoder.sol#L158-L160 - - - - [ ] ID-7 Dubious typecast in [Outbox.sendL1Messages(bytes32[])](src/core/messagebridge/Outbox.sol#L38-L46): uint256 => uint32 casting occurs in [version = uint32(REGISTRY.getVersionFor(msg.sender))](src/core/messagebridge/Outbox.sol#L40) src/core/messagebridge/Outbox.sol#L38-L46 - - [ ] ID-8 + - [ ] ID-7 Dubious typecast in [Inbox.sendL2Message(DataStructures.L2Actor,uint32,bytes32,bytes32)](src/core/messagebridge/Inbox.sol#L45-L91): uint256 => uint64 casting occurs in [fee = uint64(msg.value)](src/core/messagebridge/Inbox.sol#L64) uint256 => uint32 casting occurs in [entries.insert(key,fee,uint32(_recipient.version),_deadline,_errIncompatibleEntryArguments)](src/core/messagebridge/Inbox.sol#L76) @@ -85,53 +78,58 @@ Dubious typecast in [Inbox.sendL2Message(DataStructures.L2Actor,uint32,bytes32,b src/core/messagebridge/Inbox.sol#L45-L91 - - [ ] ID-9 -Dubious typecast in [TxsDecoder.read1(bytes,uint256)](src/core/libraries/decoders/TxsDecoder.sol#L349-L351): - bytes => bytes1 casting occurs in [uint256(uint8(bytes1(slice(_data,_offset,1))))](src/core/libraries/decoders/TxsDecoder.sol#L350) + - [ ] ID-8 +Dubious typecast in [TxsDecoder.read4(bytes,uint256)](src/core/libraries/decoders/TxsDecoder.sol#L324-L326): + bytes => bytes4 casting occurs in [uint256(uint32(bytes4(slice(_data,_offset,4))))](src/core/libraries/decoders/TxsDecoder.sol#L325) -src/core/libraries/decoders/TxsDecoder.sol#L349-L351 +src/core/libraries/decoders/TxsDecoder.sol#L324-L326 - - [ ] ID-10 -Dubious typecast in [MessagesDecoder.read4(bytes,uint256)](src/core/libraries/decoders/MessagesDecoder.sol#L168-L170): - bytes => bytes4 casting occurs in [uint256(uint32(bytes4(_data)))](src/core/libraries/decoders/MessagesDecoder.sol#L169) + - [ ] ID-9 +Dubious typecast in [MessagesDecoder.read4(bytes,uint256)](src/core/libraries/decoders/MessagesDecoder.sol#L160-L162): + bytes => bytes4 casting occurs in [uint256(uint32(bytes4(_data)))](src/core/libraries/decoders/MessagesDecoder.sol#L161) -src/core/libraries/decoders/MessagesDecoder.sol#L168-L170 +src/core/libraries/decoders/MessagesDecoder.sol#L160-L162 - - [ ] ID-11 + - [ ] ID-10 Dubious typecast in [Inbox.batchConsume(bytes32[],address)](src/core/messagebridge/Inbox.sol#L122-L143): uint256 => uint32 casting occurs in [expectedVersion = uint32(REGISTRY.getVersionFor(msg.sender))](src/core/messagebridge/Inbox.sol#L128) src/core/messagebridge/Inbox.sol#L122-L143 + - [ ] ID-11 +Dubious typecast in [HeaderLib.decode(bytes)](src/core/libraries/HeaderLib.sol#L143-L184): + bytes => bytes32 casting occurs in [header.lastArchive = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L151-L153) + bytes => bytes4 casting occurs in [header.lastArchive = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L151-L153) + bytes => bytes32 casting occurs in [header.contentCommitment.txTreeHeight = uint256(bytes32(_header))](src/core/libraries/HeaderLib.sol#L156) + bytes => bytes32 casting occurs in [header.contentCommitment.txsEffectsHash = bytes32(_header)](src/core/libraries/HeaderLib.sol#L157) + bytes => bytes32 casting occurs in [header.contentCommitment.inHash = bytes32(_header)](src/core/libraries/HeaderLib.sol#L158) + bytes => bytes32 casting occurs in [header.contentCommitment.outHash = bytes32(_header)](src/core/libraries/HeaderLib.sol#L159) + bytes => bytes32 casting occurs in [header.stateReference.l1ToL2MessageTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L162-L164) + bytes => bytes4 casting occurs in [header.stateReference.l1ToL2MessageTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L162-L164) + bytes => bytes32 casting occurs in [header.stateReference.partialStateReference.noteHashTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L165-L167) + bytes => bytes4 casting occurs in [header.stateReference.partialStateReference.noteHashTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L165-L167) + bytes => bytes32 casting occurs in [header.stateReference.partialStateReference.nullifierTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L168-L170) + bytes => bytes4 casting occurs in [header.stateReference.partialStateReference.nullifierTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L168-L170) + bytes => bytes32 casting occurs in [header.stateReference.partialStateReference.publicDataTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L171-L173) + bytes => bytes4 casting occurs in [header.stateReference.partialStateReference.publicDataTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L171-L173) + bytes => bytes32 casting occurs in [header.globalVariables.chainId = uint256(bytes32(_header))](src/core/libraries/HeaderLib.sol#L176) + bytes => bytes32 casting occurs in [header.globalVariables.version = uint256(bytes32(_header))](src/core/libraries/HeaderLib.sol#L177) + bytes => bytes32 casting occurs in [header.globalVariables.blockNumber = uint256(bytes32(_header))](src/core/libraries/HeaderLib.sol#L178) + bytes => bytes32 casting occurs in [header.globalVariables.timestamp = uint256(bytes32(_header))](src/core/libraries/HeaderLib.sol#L179) + bytes => bytes20 casting occurs in [header.globalVariables.coinbase = address(bytes20(_header))](src/core/libraries/HeaderLib.sol#L180) + bytes => bytes32 casting occurs in [header.globalVariables.feeRecipient = bytes32(_header)](src/core/libraries/HeaderLib.sol#L181) + +src/core/libraries/HeaderLib.sol#L143-L184 + + - [ ] ID-12 -Dubious typecast in [HeaderLib.decode(bytes)](src/core/libraries/HeaderLib.sol#L145-L189): - bytes => bytes32 casting occurs in [header.lastArchive = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L153-L155) - bytes => bytes4 casting occurs in [header.lastArchive = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L153-L155) - bytes => bytes32 casting occurs in [header.contentCommitment.txTreeHeight = uint256(bytes32(_header))](src/core/libraries/HeaderLib.sol#L158) - bytes => bytes32 casting occurs in [header.contentCommitment.txsEffectsHash = bytes32(_header)](src/core/libraries/HeaderLib.sol#L159) - bytes => bytes32 casting occurs in [header.contentCommitment.inHash = bytes32(_header)](src/core/libraries/HeaderLib.sol#L160) - bytes => bytes32 casting occurs in [header.contentCommitment.outHash = bytes32(_header)](src/core/libraries/HeaderLib.sol#L161) - bytes => bytes32 casting occurs in [header.stateReference.l1ToL2MessageTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L164-L166) - bytes => bytes4 casting occurs in [header.stateReference.l1ToL2MessageTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L164-L166) - bytes => bytes32 casting occurs in [header.stateReference.partialStateReference.noteHashTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L167-L169) - bytes => bytes4 casting occurs in [header.stateReference.partialStateReference.noteHashTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L167-L169) - bytes => bytes32 casting occurs in [header.stateReference.partialStateReference.nullifierTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L170-L172) - bytes => bytes4 casting occurs in [header.stateReference.partialStateReference.nullifierTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L170-L172) - bytes => bytes32 casting occurs in [header.stateReference.partialStateReference.contractTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L173-L175) - bytes => bytes4 casting occurs in [header.stateReference.partialStateReference.contractTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L173-L175) - bytes => bytes32 casting occurs in [header.stateReference.partialStateReference.publicDataTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L176-L178) - bytes => bytes4 casting occurs in [header.stateReference.partialStateReference.publicDataTree = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L176-L178) - bytes => bytes32 casting occurs in [header.globalVariables.chainId = uint256(bytes32(_header))](src/core/libraries/HeaderLib.sol#L181) - bytes => bytes32 casting occurs in [header.globalVariables.version = uint256(bytes32(_header))](src/core/libraries/HeaderLib.sol#L182) - bytes => bytes32 casting occurs in [header.globalVariables.blockNumber = uint256(bytes32(_header))](src/core/libraries/HeaderLib.sol#L183) - bytes => bytes32 casting occurs in [header.globalVariables.timestamp = uint256(bytes32(_header))](src/core/libraries/HeaderLib.sol#L184) - bytes => bytes20 casting occurs in [header.globalVariables.coinbase = address(bytes20(_header))](src/core/libraries/HeaderLib.sol#L185) - bytes => bytes32 casting occurs in [header.globalVariables.feeRecipient = bytes32(_header)](src/core/libraries/HeaderLib.sol#L186) - -src/core/libraries/HeaderLib.sol#L145-L189 +Dubious typecast in [MessagesDecoder.read1(bytes,uint256)](src/core/libraries/decoders/MessagesDecoder.sol#L150-L152): + bytes => bytes1 casting occurs in [uint256(uint8(bytes1(_data)))](src/core/libraries/decoders/MessagesDecoder.sol#L151) + +src/core/libraries/decoders/MessagesDecoder.sol#L150-L152 ## missing-zero-check @@ -181,11 +179,11 @@ src/core/messagebridge/Inbox.sol#L122-L143 - [ ] ID-17 -[HeaderLib.validate(HeaderLib.Header,uint256,uint256,bytes32)](src/core/libraries/HeaderLib.sol#L108-L138) uses timestamp for comparisons +[HeaderLib.validate(HeaderLib.Header,uint256,uint256,bytes32)](src/core/libraries/HeaderLib.sol#L106-L136) uses timestamp for comparisons Dangerous comparisons: - - [_header.globalVariables.timestamp > block.timestamp](src/core/libraries/HeaderLib.sol#L122) + - [_header.globalVariables.timestamp > block.timestamp](src/core/libraries/HeaderLib.sol#L120) -src/core/libraries/HeaderLib.sol#L108-L138 +src/core/libraries/HeaderLib.sol#L106-L136 - [ ] ID-18 @@ -256,18 +254,18 @@ src/core/messagebridge/NewInbox.sol#L25-L128 Impact: Informational Confidence: High - [ ] ID-26 -[MessagesDecoder.decode(bytes)](src/core/libraries/decoders/MessagesDecoder.sol#L60-L150) uses assembly +[MessagesDecoder.decode(bytes)](src/core/libraries/decoders/MessagesDecoder.sol#L60-L142) uses assembly - [INLINE ASM](src/core/libraries/decoders/MessagesDecoder.sol#L79-L81) - [INLINE ASM](src/core/libraries/decoders/MessagesDecoder.sol#L112-L118) -src/core/libraries/decoders/MessagesDecoder.sol#L60-L150 +src/core/libraries/decoders/MessagesDecoder.sol#L60-L142 - [ ] ID-27 -[TxsDecoder.computeRoot(bytes32[])](src/core/libraries/decoders/TxsDecoder.sol#L291-L310) uses assembly - - [INLINE ASM](src/core/libraries/decoders/TxsDecoder.sol#L298-L300) +[TxsDecoder.computeRoot(bytes32[])](src/core/libraries/decoders/TxsDecoder.sol#L256-L275) uses assembly + - [INLINE ASM](src/core/libraries/decoders/TxsDecoder.sol#L263-L265) -src/core/libraries/decoders/TxsDecoder.sol#L291-L310 +src/core/libraries/decoders/TxsDecoder.sol#L256-L275 ## dead-code @@ -323,15 +321,15 @@ src/core/messagebridge/Inbox.sol#L148-L153 Impact: Informational Confidence: Medium - [ ] ID-35 -Variable [Constants.LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP](src/core/libraries/ConstantsGen.sol#L129) is too similar to [Constants.NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP](src/core/libraries/ConstantsGen.sol#L122) +Variable [Constants.LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP](src/core/libraries/ConstantsGen.sol#L131) is too similar to [Constants.NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP](src/core/libraries/ConstantsGen.sol#L124) -src/core/libraries/ConstantsGen.sol#L129 +src/core/libraries/ConstantsGen.sol#L131 - [ ] ID-36 -Variable [Constants.L1_TO_L2_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L109) is too similar to [Constants.L2_TO_L1_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L110) +Variable [Constants.L1_TO_L2_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L111) is too similar to [Constants.L2_TO_L1_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L112) -src/core/libraries/ConstantsGen.sol#L109 +src/core/libraries/ConstantsGen.sol#L111 - [ ] ID-37 diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index b9ba3fb6926..c953f7d54ea 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -25,6 +25,7 @@ library Constants { uint256 internal constant MAX_PUBLIC_DATA_READS_PER_CALL = 16; uint256 internal constant MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 32; uint256 internal constant MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 2; + uint256 internal constant MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 2; uint256 internal constant MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL = 1; uint256 internal constant MAX_NEW_NOTE_HASHES_PER_TX = 64; uint256 internal constant MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX = 8; @@ -43,24 +44,26 @@ library Constants { uint256 internal constant MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX = 16; uint256 internal constant MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX = 16; uint256 internal constant MAX_NEW_L2_TO_L1_MSGS_PER_TX = 2; - uint256 internal constant MAX_NEW_CONTRACTS_PER_TX = 1; uint256 internal constant MAX_NOTE_HASH_READ_REQUESTS_PER_TX = 128; uint256 internal constant MAX_NULLIFIER_READ_REQUESTS_PER_TX = 8; + uint256 internal constant MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX = 8; uint256 internal constant MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX = 4; uint256 internal constant NUM_ENCRYPTED_LOGS_HASHES_PER_TX = 1; uint256 internal constant NUM_UNENCRYPTED_LOGS_HASHES_PER_TX = 1; uint256 internal constant NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP = 16; uint256 internal constant VK_TREE_HEIGHT = 3; uint256 internal constant FUNCTION_TREE_HEIGHT = 5; - uint256 internal constant CONTRACT_TREE_HEIGHT = 16; uint256 internal constant NOTE_HASH_TREE_HEIGHT = 32; uint256 internal constant PUBLIC_DATA_TREE_HEIGHT = 40; uint256 internal constant NULLIFIER_TREE_HEIGHT = 20; uint256 internal constant L1_TO_L2_MSG_TREE_HEIGHT = 16; uint256 internal constant ROLLUP_VK_TREE_HEIGHT = 8; uint256 internal constant ARTIFACT_FUNCTION_TREE_MAX_HEIGHT = 5; - uint256 internal constant CONTRACT_SUBTREE_HEIGHT = 0; - uint256 internal constant CONTRACT_SUBTREE_SIBLING_PATH_LENGTH = 16; + uint256 internal constant NULLIFIER_TREE_ID = 0; + uint256 internal constant NOTE_HASH_TREE_ID = 1; + uint256 internal constant PUBLIC_DATA_TREE_ID = 2; + uint256 internal constant L1_TO_L2_MESSAGE_TREE_ID = 3; + uint256 internal constant ARCHIVE_TREE_ID = 4; uint256 internal constant NOTE_HASH_SUBTREE_HEIGHT = 6; uint256 internal constant NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH = 26; uint256 internal constant NULLIFIER_SUBTREE_HEIGHT = 6; @@ -76,7 +79,7 @@ library Constants { uint256 internal constant ARGS_HASH_CHUNK_COUNT = 32; uint256 internal constant INITIAL_L2_BLOCK_NUM = 1; uint256 internal constant BLOB_SIZE_IN_BYTES = 126976; - uint256 internal constant MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 9000; + uint256 internal constant MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 15000; uint256 internal constant MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS = 500; uint256 internal constant MAX_PACKED_BYTECODE_SIZE_PER_UNCONSTRAINED_FUNCTION_IN_FIELDS = 500; uint256 internal constant REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE = @@ -95,9 +98,8 @@ library Constants { uint256 internal constant MAX_NOTES_PER_PAGE = 10; uint256 internal constant VIEW_NOTE_ORACLE_RETURN_LENGTH = 212; uint256 internal constant AZTEC_ADDRESS_LENGTH = 1; - uint256 internal constant CALL_CONTEXT_LENGTH = 8; + uint256 internal constant CALL_CONTEXT_LENGTH = 7; uint256 internal constant CONTENT_COMMITMENT_LENGTH = 7; - uint256 internal constant CONTRACT_DEPLOYMENT_DATA_LENGTH = 6; uint256 internal constant CONTRACT_INSTANCE_LENGTH = 6; uint256 internal constant CONTRACT_STORAGE_READ_LENGTH = 2; uint256 internal constant CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 2; @@ -105,19 +107,19 @@ library Constants { uint256 internal constant FUNCTION_DATA_LENGTH = 4; uint256 internal constant FUNCTION_LEAF_PREIMAGE_LENGTH = 5; uint256 internal constant GLOBAL_VARIABLES_LENGTH = 6; - uint256 internal constant HEADER_LENGTH = 25; + uint256 internal constant HEADER_LENGTH = 23; uint256 internal constant L1_TO_L2_MESSAGE_LENGTH = 8; uint256 internal constant L2_TO_L1_MESSAGE_LENGTH = 2; - uint256 internal constant NEW_CONTRACT_DATA_LENGTH = 3; uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 4; uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 5; - uint256 internal constant PARTIAL_STATE_REFERENCE_LENGTH = 8; - uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = 223; - uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 218; - uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 199; - uint256 internal constant STATE_REFERENCE_LENGTH = 10; - uint256 internal constant TX_CONTEXT_DATA_LENGTH = 11; - uint256 internal constant TX_REQUEST_LENGTH = 17; + uint256 internal constant PARTIAL_STATE_REFERENCE_LENGTH = 6; + uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = 214; + uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 209; + uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 200; + uint256 internal constant STATE_REFERENCE_LENGTH = 8; + uint256 internal constant TX_CONTEXT_DATA_LENGTH = 4; + uint256 internal constant TX_REQUEST_LENGTH = 10; + uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 13; uint256 internal constant GET_NOTES_ORACLE_RETURN_LENGTH = 674; uint256 internal constant NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048; uint256 internal constant NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; diff --git a/l1-contracts/src/core/libraries/HeaderLib.sol b/l1-contracts/src/core/libraries/HeaderLib.sol index 8da581904fd..9123f0e262b 100644 --- a/l1-contracts/src/core/libraries/HeaderLib.sol +++ b/l1-contracts/src/core/libraries/HeaderLib.sol @@ -37,19 +37,17 @@ import {Hash} from "./Hash.sol"; * | 0x00e8 | 0x04 | noteHashTree.nextAvailableLeafIndex * | 0x00ec | 0x20 | nullifierTree.root * | 0x010c | 0x04 | nullifierTree.nextAvailableLeafIndex - * | 0x0110 | 0x20 | contractTree.root - * | 0x0130 | 0x04 | contractTree.nextAvailableLeafIndex - * | 0x0134 | 0x20 | publicDataTree.root - * | 0x0154 | 0x04 | publicDataTree.nextAvailableLeafIndex + * | 0x0110 | 0x20 | publicDataTree.root + * | 0x0130 | 0x04 | publicDataTree.nextAvailableLeafIndex * | | | } * | | | } * | | | GlobalVariables { - * | 0x0158 | 0x20 | chainId - * | 0x0178 | 0x20 | version - * | 0x0198 | 0x20 | blockNumber - * | 0x01b8 | 0x20 | timestamp - * | 0x01d8 | 0x14 | coinbase - * | 0x01ec | 0x20 | feeRecipient + * | 0x0134 | 0x20 | chainId + * | 0x0154 | 0x20 | version + * | 0x0174 | 0x20 | blockNumber + * | 0x0194 | 0x20 | timestamp + * | 0x01b4 | 0x14 | coinbase + * | 0x01c8 | 0x20 | feeRecipient * | | | } * | | | } * | --- | --- | --- @@ -96,7 +94,7 @@ library HeaderLib { GlobalVariables globalVariables; } - uint256 private constant HEADER_LENGTH = 0x20c; // Header byte length + uint256 private constant HEADER_LENGTH = 0x1e8; // Header byte length /** * @notice Validates the header @@ -170,20 +168,17 @@ library HeaderLib { header.stateReference.partialStateReference.nullifierTree = AppendOnlyTreeSnapshot( bytes32(_header[0x00ec:0x010c]), uint32(bytes4(_header[0x010c:0x0110])) ); - header.stateReference.partialStateReference.contractTree = AppendOnlyTreeSnapshot( - bytes32(_header[0x0110:0x0130]), uint32(bytes4(_header[0x0130:0x0134])) - ); header.stateReference.partialStateReference.publicDataTree = AppendOnlyTreeSnapshot( - bytes32(_header[0x0134:0x0154]), uint32(bytes4(_header[0x0154:0x0158])) + bytes32(_header[0x0110:0x0130]), uint32(bytes4(_header[0x0130:0x0134])) ); // Reading GlobalVariables - header.globalVariables.chainId = uint256(bytes32(_header[0x0158:0x0178])); - header.globalVariables.version = uint256(bytes32(_header[0x0178:0x0198])); - header.globalVariables.blockNumber = uint256(bytes32(_header[0x0198:0x01b8])); - header.globalVariables.timestamp = uint256(bytes32(_header[0x01b8:0x01d8])); - header.globalVariables.coinbase = address(bytes20(_header[0x01d8:0x01ec])); - header.globalVariables.feeRecipient = bytes32(_header[0x01ec:HEADER_LENGTH]); + header.globalVariables.chainId = uint256(bytes32(_header[0x0134:0x0154])); + header.globalVariables.version = uint256(bytes32(_header[0x0154:0x0174])); + header.globalVariables.blockNumber = uint256(bytes32(_header[0x0174:0x0194])); + header.globalVariables.timestamp = uint256(bytes32(_header[0x0194:0x01b4])); + header.globalVariables.coinbase = address(bytes20(_header[0x01b4:0x01c8])); + header.globalVariables.feeRecipient = bytes32(_header[0x01c8:HEADER_LENGTH]); return header; } diff --git a/l1-contracts/src/core/libraries/decoders/MessagesDecoder.sol b/l1-contracts/src/core/libraries/decoders/MessagesDecoder.sol index 0749f008e2c..a6252e176f0 100644 --- a/l1-contracts/src/core/libraries/decoders/MessagesDecoder.sol +++ b/l1-contracts/src/core/libraries/decoders/MessagesDecoder.sol @@ -18,6 +18,9 @@ import {Hash} from "../Hash.sol"; * ------------------- * L2 Body Data Specification * ------------------- + * ------------------- + * L2 Body Data Specification + * ------------------- * | byte start | num bytes | name * | --- | --- | --- * | 0x0 | 0x4 | len(newL1ToL2Msgs) (denoted a) @@ -32,13 +35,10 @@ import {Hash} from "../Hash.sol"; * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 | d * 0x20 | newL2ToL1Msgs * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 | 0x1 | len(newPublicDataWrites) (denoted e) * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 | e * 0x40 | newPublicDataWrites - * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 | 0x1 | len(contracts) (denoted f) - * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x1 | f * 0x20 | newContracts - * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x1 + f * 0x20 | f * 0x34 | newContractsData - * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x1 + f * 0x20 + f * 0x34 | 0x04 | byteLen(newEncryptedLogs) (denoted g) - * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x1 + f * 0x20 + f * 0x34 + 0x4 | g | newEncryptedLogs - * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x1 + f * 0x20 + f * 0x34 + 0x4 + g | 0x04 | byteLen(newUnencryptedLogs) (denoted h) - * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x1 + f * 0x20 + f * 0x34 + 0x4 + g + 0x4 | h | newUnencryptedLogs + * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 | 0x04 | byteLen(newEncryptedLogs) (denoted f) + * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 | f | newEncryptedLogs + * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f | 0x04 | byteLen(newUnencryptedLogs) (denoted g) + * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f + 0x4 | g | newUnencryptedLogs * | | | }, * | | | TxEffect 1 { * | | | ... @@ -126,14 +126,6 @@ library MessagesDecoder { offset += 0x1; offset += count * 0x40; // each public data write is 0x40 bytes long - // Contracts - count = read1(_body, offset); - offset += 0x1; - offset += count * 0x20; // each contract leaf is 0x20 bytes long - - // Contract data - offset += count * 0x34; // each contract data is 0x34 bytes long - // Encrypted logs uint256 length = read4(_body, offset); offset += 0x4 + length; diff --git a/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol b/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol index 442b6a41005..95ad430f138 100644 --- a/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol +++ b/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol @@ -14,7 +14,7 @@ import {Hash} from "../Hash.sol"; * @dev Assumes the input trees to be padded. * * ------------------- - * You can use https://gist.github.com/LHerskind/724a7e362c97e8ac2902c6b961d36830 to generate the below outline. + * You can use scripts/l2_block_data_specification_comment.py to generate the below outline. * ------------------- * L2 Body Data Specification * ------------------- @@ -32,13 +32,10 @@ import {Hash} from "../Hash.sol"; * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 | d * 0x20 | newL2ToL1Msgs * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 | 0x1 | len(newPublicDataWrites) (denoted e) * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 | e * 0x40 | newPublicDataWrites - * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 | 0x1 | len(contracts) (denoted f) - * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x1 | f * 0x20 | newContracts - * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x1 + f * 0x20 | f * 0x34 | newContractsData - * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x1 + f * 0x20 + f * 0x34 | 0x04 | byteLen(newEncryptedLogs) (denoted g) - * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x1 + f * 0x20 + f * 0x34 + 0x4 | g | newEncryptedLogs - * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x1 + f * 0x20 + f * 0x34 + 0x4 + g | 0x04 | byteLen(newUnencryptedLogs) (denoted h) - * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x1 + f * 0x20 + f * 0x34 + 0x4 + g + 0x4 | h | newUnencryptedLogs + * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 | 0x04 | byteLen(newEncryptedLogs) (denoted f) + * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 | f | newEncryptedLogs + * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f | 0x04 | byteLen(newUnencryptedLogs) (denoted g) + * | tx0Start + 0x1 + b * 0x20 + 0x1 + c * 0x20 + 0x1 + d * 0x20 + 0x01 + e * 0x40 + 0x4 + f + 0x4 | g | newUnencryptedLogs * | | | }, * | | | TxEffect 1 { * | | | ... @@ -54,8 +51,6 @@ library TxsDecoder { uint256 nullifier; uint256 l2ToL1Msgs; uint256 publicData; - uint256 contracts; - uint256 contractData; } struct Counts { @@ -63,8 +58,6 @@ library TxsDecoder { uint256 nullifier; uint256 l2ToL1Msgs; uint256 publicData; - uint256 contracts; - uint256 contractData; } // Note: Used in `computeConsumables` to get around stack too deep errors. @@ -145,27 +138,6 @@ library TxsDecoder { offsets.publicData = offset; offset += count * 0x40; // each public data write is 0x40 bytes long - // Contracts - count = read1(_body, offset); - offset += 0x1; - counts.contracts = count; - offsets.contracts = offset; - offset += count * 0x20; // each contract leaf is 0x20 bytes long - - // Contract data - counts.contractData = count; // count is the same as contracts - offsets.contractData = offset; - offset += count * 0x34; // each contract data is 0x34 bytes long - - bytes memory contractData = new bytes(Constants.CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP); - if (counts.contracts == 1) { - contractData = bytes.concat( - slice(_body, offsets.contractData, 0x20), // newContractDataKernel.aztecAddress - bytes12(0), // We pad the ethAddress to 32 bytes, we don't use sliceAndPad here because we want to prefix - slice(_body, offsets.contractData + 0x20, 0x14) // newContractDataKernel.ethAddress - ); - } - /** * Compute encrypted and unencrypted logs hashes corresponding to the current leaf. * Note: will advance offsets by the number of bytes processed. @@ -199,15 +171,8 @@ library TxsDecoder { offsets.publicData, counts.publicData * 0x40, Constants.PUBLIC_DATA_WRITES_NUM_BYTES_PER_BASE_ROLLUP - ), - sliceAndPad( - _body, - offsets.contracts, - counts.contracts * 0x20, - Constants.CONTRACTS_NUM_BYTES_PER_BASE_ROLLUP ) ), - contractData, bytes.concat(vars.encryptedLogsHash, vars.unencryptedLogsHash) ); diff --git a/l1-contracts/src/periphery/ContractDeploymentEmitter.sol b/l1-contracts/src/periphery/ContractDeploymentEmitter.sol deleted file mode 100644 index efa55fc0f35..00000000000 --- a/l1-contracts/src/periphery/ContractDeploymentEmitter.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2023 Aztec Labs. -pragma solidity >=0.8.18; - -// Interfaces -import {IContractDeploymentEmitter} from "./interfaces/IContractDeploymentEmitter.sol"; - -/** - * @title ContractDeploymentEmitter - * @author Aztec Labs - * @notice Used to log data on chain which are not required to advance the state but are needed for other purposes - */ -contract ContractDeploymentEmitter is IContractDeploymentEmitter { - /** - * @notice Publishes public function bytecode to L1. - * @dev Emits a `ContractDeployment` event - * @dev Unverified and can be emitted by anyone - * @param _l2BlockNum - The L2 block number that the contract deployment is related to - * @param _aztecAddress - The address of the L2 counterparty - * @param _portalAddress - The address of the L1 counterparty - * @param _l2BlockHash - The hash of the L2 block that this is related to - * @param _contractClassId - The contract class id - * @param _saltedInitializationHash - Salted init hash - * @param _publicKeyHash - Public key hash - * @param _acir - The acir bytecode of the L2 contract - * @dev See the link below for more info on partial address and public key: - * https://github.com/AztecProtocol/aztec-packages/blob/master/docs/docs/concepts/foundation/accounts/keys.md#addresses-partial-addresses-and-public-keys - * TODO: replace the link above with the link to deployed docs - */ - function emitContractDeployment( - uint256 _l2BlockNum, - bytes32 _aztecAddress, - address _portalAddress, - bytes32 _l2BlockHash, - bytes32 _contractClassId, - bytes32 _saltedInitializationHash, - bytes32 _publicKeyHash, - bytes calldata _acir - ) external override(IContractDeploymentEmitter) { - emit ContractDeployment( - _l2BlockNum, - _aztecAddress, - _portalAddress, - _l2BlockHash, - _contractClassId, - _saltedInitializationHash, - _publicKeyHash, - _acir - ); - } -} diff --git a/l1-contracts/src/periphery/interfaces/IContractDeploymentEmitter.sol b/l1-contracts/src/periphery/interfaces/IContractDeploymentEmitter.sol deleted file mode 100644 index 9debce8240f..00000000000 --- a/l1-contracts/src/periphery/interfaces/IContractDeploymentEmitter.sol +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2023 Aztec Labs. -pragma solidity >=0.8.18; - -/** - * @title Contract Deployment Emitter Interface - * @author Aztec Labs - * @notice Interface for Contract Deployment Emitter - * The contract is used to broadcast information about deployed contracts with public functions. - */ -interface IContractDeploymentEmitter { - /** - * @notice Links L1 and L2 addresses and stores the acir bytecode of the L2 contract - * @param l2BlockNum - The L2 block number that the information is related to - * @param aztecAddress - The address of the L2 counterparty - * @param portalAddress - The address of the L1 counterparty - * @param l2BlockHash - The hash of the L2 block that this is related to - * @param contractClassId - The contract class id - * @param saltedInitializationHash - Salted init hash - * @param publicKeyHash - Public key hash - * @param acir - The acir bytecode of the L2 contract - * @dev See the link below for more info on partial address and public key: - * https://github.com/AztecProtocol/aztec-packages/blob/master/docs/docs/concepts/foundation/accounts/keys.md#addresses-partial-addresses-and-public-keys - * TODO: replace the link above with the link to deployed docs - */ - event ContractDeployment( - uint256 indexed l2BlockNum, - bytes32 indexed aztecAddress, - address indexed portalAddress, - bytes32 l2BlockHash, - bytes32 contractClassId, - bytes32 saltedInitializationHash, - bytes32 publicKeyHash, - bytes acir - ); - - function emitContractDeployment( - uint256 _l2BlockNum, - bytes32 _aztecAddress, - address _portalAddress, - bytes32 _l2BlockHash, - bytes32 _contractClassId, - bytes32 _saltedInitializationHash, - bytes32 _publicKeyHash, - bytes calldata _acir - ) external; -} diff --git a/l1-contracts/terraform/main.tf b/l1-contracts/terraform/main.tf index adf899760a1..9a337e1580a 100644 --- a/l1-contracts/terraform/main.tf +++ b/l1-contracts/terraform/main.tf @@ -55,12 +55,3 @@ variable "OUTBOX_CONTRACT_ADDRESS" { output "outbox_contract_address" { value = var.OUTBOX_CONTRACT_ADDRESS } - -variable "CONTRACT_DEPLOYMENT_EMITTER_ADDRESS" { - type = string - default = "" -} - -output "contract_deployment_emitter_address" { - value = var.CONTRACT_DEPLOYMENT_EMITTER_ADDRESS -} diff --git a/l1-contracts/test/Rollup.t.sol b/l1-contracts/test/Rollup.t.sol index be9dc7192fa..93f4433a5e6 100644 --- a/l1-contracts/test/Rollup.t.sol +++ b/l1-contracts/test/Rollup.t.sol @@ -62,7 +62,8 @@ contract RollupTest is DecoderBase { bytes memory body = data.body; assembly { - mstore(add(header, add(0x20, 0x0158)), 0x420) + // TODO: Hardcoding offsets in the middle of tests is annoying to say the least. + mstore(add(header, add(0x20, 0x0134)), 0x420) } availabilityOracle.publish(body); @@ -78,7 +79,7 @@ contract RollupTest is DecoderBase { bytes memory body = data.body; assembly { - mstore(add(header, add(0x20, 0x0178)), 0x420) + mstore(add(header, add(0x20, 0x0154)), 0x420) } availabilityOracle.publish(body); @@ -95,7 +96,7 @@ contract RollupTest is DecoderBase { uint256 ts = block.timestamp + 1; assembly { - mstore(add(header, add(0x20, 0x01b8)), ts) + mstore(add(header, add(0x20, 0x0194)), ts) } availabilityOracle.publish(body); diff --git a/l1-contracts/test/decoders/Base.sol b/l1-contracts/test/decoders/Base.sol index e74a5e20693..4d2b9a85e9b 100644 --- a/l1-contracts/test/decoders/Base.sol +++ b/l1-contracts/test/decoders/Base.sol @@ -72,7 +72,6 @@ contract DecoderBase is Test { } struct PartialStateReference { - AppendOnlyTreeSnapshot contractTree; AppendOnlyTreeSnapshot noteHashTree; AppendOnlyTreeSnapshot nullifierTree; AppendOnlyTreeSnapshot publicDataTree; diff --git a/l1-contracts/test/decoders/Decoders.t.sol b/l1-contracts/test/decoders/Decoders.t.sol index 9c53d7499ab..6227407d6ba 100644 --- a/l1-contracts/test/decoders/Decoders.t.sol +++ b/l1-contracts/test/decoders/Decoders.t.sol @@ -128,18 +128,6 @@ contract DecodersTest is DecoderBase { "Invalid nullifierTree.root" ); - // ContractTree - assertEq( - header.stateReference.partialStateReference.contractTree.nextAvailableLeafIndex, - partialStateReference.contractTree.nextAvailableLeafIndex, - "Invalid contractTree.nextAvailableLeafIndex" - ); - assertEq( - header.stateReference.partialStateReference.contractTree.root, - partialStateReference.contractTree.root, - "Invalid contractTree.root" - ); - // PublicDataTree assertEq( header.stateReference.partialStateReference.publicDataTree.nextAvailableLeafIndex, diff --git a/l1-contracts/test/fixtures/empty_block_0.json b/l1-contracts/test/fixtures/empty_block_0.json index ed0b3f5bdd6..5769185f450 100644 --- a/l1-contracts/test/fixtures/empty_block_0.json +++ b/l1-contracts/test/fixtures/empty_block_0.json @@ -35,27 +35,27 @@ ] }, "block": { - "archive": "0x1bb1134e3fda61b56e838d68034e7c1e3a8da99d2321533b579eb1ae7588cd51", - "body": "0x0000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "txsEffectsHash": "0xdeb8be229731acd5c13f8dbdbfc60fdc8f7865f480d77f84c763d625aefbd6b1", + "archive": "0x12e61edc1dad6fb9e81e4157d0906a171a2d2cad5daa767594eb07b7e7c1c189", + "body": "0x00000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "txsEffectsHash": "0x9139297703640b243028d35c29ae8c0667886c4edc8db5f879c260d2051bb8a9", "decodedHeader": { "contentCommitment": { "inHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "outHash": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", "txTreeHeight": 2, - "txsEffectsHash": "0xdeb8be229731acd5c13f8dbdbfc60fdc8f7865f480d77f84c763d625aefbd6b1" + "txsEffectsHash": "0x9139297703640b243028d35c29ae8c0667886c4edc8db5f879c260d2051bb8a9" }, "globalVariables": { "blockNumber": 1, "chainId": 31337, "timestamp": 0, "version": 1, - "coinbase": "0x56a54c9ad4f77919e45f9b9a18cf55468a60ebe5", - "feeRecipient": "0x02db69f955a50583c56b7405d887a720030cefc20293682c3eba3574e4c77846" + "coinbase": "0x837ac4b411a7a5911031e82d3f8799bb21c34795", + "feeRecipient": "0x1296779221953ecf9e3c115440521940f216ca20b860f64f13af55b8cdbdb9c7" }, "lastArchive": { "nextAvailableLeafIndex": 1, - "root": "0x0f045bd8180c4de901e18a10e9393ae42d9ef7928fe6b68568cb48b91d1355a7" + "root": "0x012a86560737adb075e12af8253fb09abf17aa841fb56d180bc89f0d2d473c7f" }, "stateReference": { "l1ToL2MessageTree": { @@ -63,10 +63,6 @@ "root": "0x1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80" }, "partialStateReference": { - "contractTree": { - "nextAvailableLeafIndex": 4, - "root": "0x1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80" - }, "noteHashTree": { "nextAvailableLeafIndex": 256, "root": "0x16642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb" @@ -82,8 +78,8 @@ } } }, - "header": "0x0f045bd8180c4de901e18a10e9393ae42d9ef7928fe6b68568cb48b91d1355a7000000010000000000000000000000000000000000000000000000000000000000000002deb8be229731acd5c13f8dbdbfc60fdc8f7865f480d77f84c763d625aefbd6b10000000000000000000000000000000000000000000000000000000000000000c78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001801864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000040572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000056a54c9ad4f77919e45f9b9a18cf55468a60ebe502db69f955a50583c56b7405d887a720030cefc20293682c3eba3574e4c77846", + "header": "0x012a86560737adb075e12af8253fb09abf17aa841fb56d180bc89f0d2d473c7f0000000100000000000000000000000000000000000000000000000000000000000000029139297703640b243028d35c29ae8c0667886c4edc8db5f879c260d2051bb8a90000000000000000000000000000000000000000000000000000000000000000c78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000837ac4b411a7a5911031e82d3f8799bb21c347951296779221953ecf9e3c115440521940f216ca20b860f64f13af55b8cdbdb9c7", "l1ToL2MessagesHash": "0x076a27c79e5ace2a3d47f9dd2e83e4ff6ea8872b3c2218f66c92b89b55f36560", - "publicInputsHash": "0x0115bc353d66365ef2b850d1f9487476c969eda2b6bbeff9e747ab58189010c6" + "publicInputsHash": "0x14d3a7d947fc1660f01d5f41f7768d9bee4a74809484cc80535183daf0346d1f" } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/empty_block_1.json b/l1-contracts/test/fixtures/empty_block_1.json index ffd4c00e0ee..94c96156ebf 100644 --- a/l1-contracts/test/fixtures/empty_block_1.json +++ b/l1-contracts/test/fixtures/empty_block_1.json @@ -35,27 +35,27 @@ ] }, "block": { - "archive": "0x16c6e97221a803dec7490cf710172aab5438818de67450a58d111d9f0184a48e", - "body": "0x0000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "txsEffectsHash": "0xdeb8be229731acd5c13f8dbdbfc60fdc8f7865f480d77f84c763d625aefbd6b1", + "archive": "0x2eb0c375f9f387ef03e8f470f7f976a8213cf31a514b72cf3499a8dd251deb57", + "body": "0x00000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "txsEffectsHash": "0x9139297703640b243028d35c29ae8c0667886c4edc8db5f879c260d2051bb8a9", "decodedHeader": { "contentCommitment": { "inHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "outHash": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", "txTreeHeight": 2, - "txsEffectsHash": "0xdeb8be229731acd5c13f8dbdbfc60fdc8f7865f480d77f84c763d625aefbd6b1" + "txsEffectsHash": "0x9139297703640b243028d35c29ae8c0667886c4edc8db5f879c260d2051bb8a9" }, "globalVariables": { "blockNumber": 2, "chainId": 31337, - "timestamp": 1709734014, + "timestamp": 1709939104, "version": 1, - "coinbase": "0x56a54c9ad4f77919e45f9b9a18cf55468a60ebe5", - "feeRecipient": "0x02db69f955a50583c56b7405d887a720030cefc20293682c3eba3574e4c77846" + "coinbase": "0x837ac4b411a7a5911031e82d3f8799bb21c34795", + "feeRecipient": "0x1296779221953ecf9e3c115440521940f216ca20b860f64f13af55b8cdbdb9c7" }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x1bb1134e3fda61b56e838d68034e7c1e3a8da99d2321533b579eb1ae7588cd51" + "root": "0x12e61edc1dad6fb9e81e4157d0906a171a2d2cad5daa767594eb07b7e7c1c189" }, "stateReference": { "l1ToL2MessageTree": { @@ -63,10 +63,6 @@ "root": "0x1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80" }, "partialStateReference": { - "contractTree": { - "nextAvailableLeafIndex": 8, - "root": "0x1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80" - }, "noteHashTree": { "nextAvailableLeafIndex": 512, "root": "0x16642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb" @@ -82,8 +78,8 @@ } } }, - "header": "0x1bb1134e3fda61b56e838d68034e7c1e3a8da99d2321533b579eb1ae7588cd51000000020000000000000000000000000000000000000000000000000000000000000002deb8be229731acd5c13f8dbdbfc60fdc8f7865f480d77f84c763d625aefbd6b10000000000000000000000000000000000000000000000000000000000000000c78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000002000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000002801864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000080572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001400000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000065e8787e56a54c9ad4f77919e45f9b9a18cf55468a60ebe502db69f955a50583c56b7405d887a720030cefc20293682c3eba3574e4c77846", + "header": "0x12e61edc1dad6fb9e81e4157d0906a171a2d2cad5daa767594eb07b7e7c1c1890000000200000000000000000000000000000000000000000000000000000000000000029139297703640b243028d35c29ae8c0667886c4edc8db5f879c260d2051bb8a90000000000000000000000000000000000000000000000000000000000000000c78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000002000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000002800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001400000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000065eb99a0837ac4b411a7a5911031e82d3f8799bb21c347951296779221953ecf9e3c115440521940f216ca20b860f64f13af55b8cdbdb9c7", "l1ToL2MessagesHash": "0x076a27c79e5ace2a3d47f9dd2e83e4ff6ea8872b3c2218f66c92b89b55f36560", - "publicInputsHash": "0x13156a7477a2a9495da438dcf5f43c02f171111e62a94bd1e88a3c46f2895cc4" + "publicInputsHash": "0x18091cbbf29dbe3cd4e5387ea7cfa360121b458b5fb9229ff822cfd32288436e" } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_0.json b/l1-contracts/test/fixtures/mixed_block_0.json index 47bab763463..d128737e1f0 100644 --- a/l1-contracts/test/fixtures/mixed_block_0.json +++ b/l1-contracts/test/fixtures/mixed_block_0.json @@ -52,27 +52,27 @@ ] }, "block": { - "archive": "0x136a8f7d7909e8b294472fef24dc3a6187259aa5005e2e0c32bfd1f49b80b5c8", - "body": "0x00000010151de48ca3efbae39f180fe00b8f472ec9f25be10b4f283a87c6d7839353703914c2ea9dedf77698d4afe23bc663263eed0bf9aa3a8b17d9b74812f185610f9e1570cc6641699e3ae87fa258d80a6d853f7b8ccb211dc244d017e2ca6530f8a12806c860af67e9cd50000378411b8c4c4db172ceb2daa862b259b689ccbdc1e005f140c7c95624c8006774279a01ec1ea88617999e4fe6997b6576c4e1c7395a22048b96b586596bd740d0402e15f5577f7ceb5496b65aafc6d89d7c3b34924b0c3f2d50d16279970d682cada30bfa6b29bc0bac0ee2389f6a0444853eccaa932b2a60561da46a58569d71044a84c639e7f88429826e5622581536eb906d9cdd25a2c0a76f7da6924e10751c755227d2535f4ad258b984e78f9f452a853c52300e212d8e2069e4254d81af07744bcbb81121a38f0e2dbed69a523d3fbf85b75c287ca6f33aadbac2e4f058e05924c140d7895a6ed167caf804b710d2ae3ba62b1b51297b3ea37637af6bd56cf33425d95cc5c96e9c2ee3077322fbec86a0c7f32c15d2a888c6cc122e99478c92470a1311635142d82ad7ae67410beeef4ae31f0902ba2fb964922a4610bb18901f7b923885c1d034da5769a48203ae6f0206a92855e2c01ddb3d6553386b5580d681b8230fa4062948668f834f23e0636eaff70aaa64519aafdf4b040bd2f9836e76b9dc13cfec8065dcdf2834d786e06260d100000004380000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f00000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000171000000000000000000000000000000000000000000000000000000000000017200000000000000000000000000000000000000000000000000000000000001730000000000000000000000000000000000000000000000000000000000000174000000000000000000000000000000000000000000000000000000000000017500000000000000000000000000000000000000000000000000000000000001760000000000000000000000000000000000000000000000000000000000000177370000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f00000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000027200000000000000000000000000000000000000000000000000000000000002730000000000000000000000000000000000000000000000000000000000000274000000000000000000000000000000000000000000000000000000000000027500000000000000000000000000000000000000000000000000000000000002760200000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000341100000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f0000000000000000000000000000000000000000000000000000000000000559011dedfc544c4f1e5f047e5ac2e76a30e407c87cb473bac191649e7f8e1576396200000000000000000000000000000000000000000000000000000000000010400000000000000000000000000000000000001041000011000000021c000000b01d3997dee1edbb7ef7c403f226e122d3d7bb8389be806c58ce0c654c049723707b68b2724538d7f1f7f6ada6e299ea0f83011e3b7b9b06539ee5b999fa332bf5d61b8ee778e565bb06196f27671150e91124bd403b1296f3fd2a74d04c4b1e9eeaaf715cabd221675127060cc62ff21b13be783f59e1898174ccafd0dea8af65ce95b2d9c406c023524d7bdf3931e3cd0cd47139b2decf80410d1a099cd92016e04c75da8674953cdc135badf63b441a000000b0260359f16ab52308e7faa499bd9e01d765ded9f2622ca0df660f5ccb58c4fcc1174435db2fff62885a0f941371f015a6d03da08367f074c6a31f875bd0a57cdf99afb308bb3e8891249fa7d838f7bc27b457efec42bd31b3f1627152869f8af1cfbd48b32bdc8f7d8960d7bb24a124fc25bb0f5acac9df6d45710874016d83a25d22f4c334f062ca45eb699901ad175d2a210dc2a46bb2ae40cdd0aeeceeb9a7bd3dd68e7db26150dbe6921e2f43c156000000b021b1c08aca8bf1e1d6b1f2fd7df97576515f97837379f5dce70161b16f555d403908420de0f9836afaf79691d21d318d1ae577ce362eaa6382fb117c927e3b278f5d429723734c38ef6939555747bcfb94838a1da206ba9a8aa4622139550791c1c91ff8365a26d8dfe3653c2ea31b211dd6042939757e1c1390f94fcf615bd3d1cf49d0afb2d3713d1f3a01f25d2fb6214a3309a27ee15f97cce516fec5d806e1f83a0f49103c045e0862cd1fc8ef570000021c000000b0216bc82309c419ceb58924457e8d7a297aca024b5e37d97cc3cbcc62707b0cdaebcd0a5b5ecbe22b066f1f5bdfe36f0b03be577d28a0227486a0cad6597570c99f12eb0232b098076096f699dc03ef93c1cfb66f245c617364cf570644ab2d291cc74001ba8471c4e9af016d55eba1fe0260cf3de99a5d5ff7e09a31a71eb6cae645240ff497169c9652fbb87193f0c41cc48e915dd93a0887ebb0b75c33dfca5e2de2bb5d67ba745492e865c39287dc000000b01a379a7ef4e1cb541186767b819353e6b090a6f90cd19ceeffbde433c6e5d9c043e02860a9c3837fb78d083175fb30df5857b645a82320cf97aedd92af6d96e1563937235211afda07b4d97e054762dda2f750e3714ce773250e968bc00d6053eed1c5fc963bcb4f577c9a283d3fd8b22276207b12cf61b15f8b5b00ff37bf82129bb65405af19031252e942587c2cf526eea148639833ac35fdadb83ad2d3779d8cd7002919b6873f6ab37361d80ba5000000b02e2e7bef01839fac64c0cc34b3dfa0faccf3f882efe3858d26c556001e86762576f15120e8e1b48b1aee5d3870c2fa40ead7d0ace6aa1d3764f2e90ee7fa6ea5b37369819ba9baa187c022f37b104a3b4d7c4ce3e5c03f6144249042cbaaf9df4177c07340eff481ffb94d328c787bf70ca27f21f88fa21f4f70172d020d9072f84d3c9f06f9cf9f071e7610e598a95f2af27875cb0ed25ec027ac6ea72eb0367fdee5b6447f5ec633b81d605e9567c90000021c000000b0014e8c6e9dba2b685121f150a0c6a496d5abbdf8c4eb7b33725bd3d5bd0b809e08d77ab57c2dd8a823e840c7aebe07d84b8880f8efed5ee7de8fbcd4cc3bbbaa2623caf66612be45ebb748b44d5211fd3195f21a2a662e9050ae21080643ecfcaf592f150ebe1150716e49e500c39a3b0a4191ae426edd10fd2961cfa765d518ac59b520ec3a887b0fe4abf369118ea82671726af89c896caf8fb13b04b4d725b71d6e25ac099212229766bcb37fa56a000000b0188d99db5fc204c1a7ffa3b03d271aeb71d3e1bc0fc621e9db31ccbb35c73ed09a774388d34b67d755c00661e068e377fe0d1eacf41410bcad74ef12f71d4762cc66e4fdfb8b1a7e4c9c2e510a53bbdf11caa41f500f043cf27f2105d8be018ba5a6c410a73d8ebfdc20960f0b1fa1220af50a029a9b4db4f465ab798bb0b1371eda734288edb52178c065221d3b5bbd04c8c7f4c6d1305bf0826aa1a7664a8cb234c3082ebcb94a7cdd9123250b774f000000b00bdaa7593ffd8c29824be7af0e3b4e4e74230a4ab1e44d329d91666389b98a114b23dce55385948fa200bd9d0422483ada36e5a814b7dda6d410648f3d8cf5526ffd318731873b9c07f84c67b6680ba33195402b1fcee07e9a9bf3a3da6f39a85f471f937e8e5d8c43bf84e192f051be16b867bf93059085d68e235460c79b6d776da7f19ad4775e484977586eb5857207e32e9bb027808aac3fd60e8a2df42999149062d6659983dd0ecd70045914ac0000021c000000b0232157d86e289750306ddcdf622229fdd04fc365bc7a1521b7070714f731c15ee1932ef3aa6c8ca1b2f85428d2dde123dce2e69dbd6a33bb34139c52f6e2fef1419def0b14d6510034ee4425e73333e17f648e9f33818dd3252f38c9ce152b65f7fe6de3532e502846e22125db70b27b1aecdeea49276243f3787be5831400fce496e3cf0f8f77a05c386d3e9aaf4fa52bc5c36301d6bd848f2fe6dc03d70291ad4d2906fce4a2a7fc295c7c25137cda000000b00f9060c7379a9aefddf97d65685c86c7b2e298df1941dfc4016bf30f05387952fb1f138089fafe420410f21136ee98c618c9ad1049f35694b87d8616c92afb074d616404ca9b0454bf1b8685189035f5e57fc0c58603c5dbea2e8d30a6527d3f30e81c5a3f76605e37506e563f42aa781192de4a8e98f436a019fb2816920501ab8bd79d44f32a80b51d68f2015571291f753c8129ff9c06f6ec320f8f5230a4d2aad95ab31879cf9ae495c0ef1600f0000000b022c3315379ffcf05387502a5b2549d555ef3ad8a0f65a755aaf26ac4eb18d486f7e164ab358d516444360616a92c16791bd3d6cd020e5dbd8353cf66baaee9b7dd4a7aacdc39159cf9dab017139b54d7d78d452fc3976c11f6474531a32071aff59b12032aa1e600401cfdb637f8f7a92a1b4d9779eca2274dd4ed4e7c1f6e5244c1163431036534eac8967b2bb53a1822c2351bbd438783fb6b7ec31e8776599220520a8851e9e50e4c6a8a9f8993e70000021c000000b0149104a19aa10185cc36c579aedd401d9cd0e0af11842e7b1cfdda07660b8fcbee81b162ac597cb3eb604ab0630c07d5dac58530c4273fe77ecfbdcf85f39696044c447685a967743770c51727e678075e65f7922fbe2c7b43a9d4199529b93d82a45f3d9d4fd98eeab5c9c0009999453063a137b6a7212bf5aa28527719c569b2ea60e8f35780b3912e98f0b8198a7504830a88450c0b038296eed468fd369a7efab809475b52994042d5592864637d000000b02c4c0360c3922ae08dbe9d6a874c133ef63299885eaafaacec62b8f5f7f9a739f7bfe929de1bfb65dbf4f9b36bb0bd7600e6d19c51bf398b317751e22e5e9b575029c3d1bfc99d8603d47d7d925c978ad4e10355cb136b23c864621c0903697971b4d7884507c70eb716094c628b434400377f9accd28d77b2d4f1d7a19b2b7656423167da836b538e51fc588c6ebae705cb21e4aa465065be992995aef9e9383f7765d174fe91fe2d18af127ec8a3d1000000b02ddb1be8dd5daf54a9cd062d401bdcefde8be16079354781afb0ae2a2c4c65775e8d315c83df8cd9a2235ce606117d4be4b789388eae232b8e3beaae7a7b93e5e95cbff94915163671a0290350f9da16e6a0e29c7732f1004b1c3d8c758a3918962968b226fc8c032f250fb3bc3f958c1122336cace9326a1c285ed440bd6569f942ff8540f0af9f40e1f74b41c5de2b08732150fda5bafc68c1000f8aaa38551995288554c954c131194c5f772d0d730000021c000000b00d705cdbd0b66960836766f11621140358f3c8bdeaf41806f7f6259de5cefc3f3866f222a8af9192ab649ac84ed7d629212f439b6566a1e6e85445b5999586fc9226f2dd1535110e7b5a62e73793619860bac464ebbbd230ac6ded1a548963a4b980d8a444c78cf40a6d5fd0412204ed18ccb2ca36bb0aff493373bd45b9cb8956cdd82bcc1e43aa9aee301db33e38c425fe7843a0640e2eead36869566122930ca7ee094252c61553d6ab4a00c182d7000000b00483aa98b79de68424a07211856fdc69a4cc40944cecf9dd87ae532be5385ec5b8f02548a182ef0bd4fd477f15094756f1b7fbeddb4c268694c7e76bff5f4fcdce8ada77ebfbf1c22c77605473b00b7054ee400955ab92bedb06d04dd3a95f5f2ccbaa3e3b6fba47663ef1afbf4570c12da2a32339de6eaefbacc3083fe7bb91e93ad2c804d3502bfe88aa1b28733080115bdfc0d3647edd5f387e8c8a1b37b3209fb0476305e0333a200222b599d305000000b01bd4bb14c7ff12576b36220305ca4a8bfb55b888cf8b78c8818103bd98529d8250382378f2a1af979faae378dc553cd22fb45b59315467baba85cac9d76a107fee4c71a6c0c2f9e991d6d69128fb3336fe2a746c8943326e28930a1642d4aeb7b6d0f5fe211cac49952e9459b9f187b42f7a52d174d68181a43882e9c06e695fb5a621411ff2361d2127cd1a0f88ed1022fd91dbeda422db98e847eef3f7e0f621457c1b33a8bbaf349ab96ac88c483c0000021c000000b023c9053bc95ea43242fbd35d2d655035420e61f791bfb5c16d7a751e2e411c2092e791281f336ef9250cb4078ea80198858e208a8266826eb829853c8e59b39de1bc809e2402b2cd22481e8ff72c01465e746746554ee9873a328187fab4a8ac88d628dbe9e323a25d910a07f3f1fbe411d56f23bb4b74c2d8db9d395aedc72e8a4e3e904ba64006db5a9dd1dbddbe2e1bdf05725ead394621896834a75828817f20c291cbd8389587bafec6fb1d060d000000b006b92a03a448a93f3303d032a9492808d88870f3c3deb20b007da6cf99e0a46b521efb84faeaada34c04b2681dae64ff7b58ec9e5797bb59a321aedf3433e3b16e43a68d7dbdc24150f93f4aa13346024b527dbb762fd952c9d752939473416d0a8e0e69b0344dc845d8f68a88542495182fa8303f64196f6ba9f2eb54e30a49b9898b8b225bc7d997a6207d0488fd6d0d08b153aa0733d3969736f408806ad0e522348c4dbb623dda8011b19e85df44000000b01f4a6295f315c0383a6681159b7dc280624255a48ca4b45a1fe8bb782f88231165449badd698e03f8f2f06bffc410cc24b001aec56fa4a00670c97acaf57ab2e43831e2732efae984bfd5f0520f137d2d5c9507ebb0ce1bcedd1fb0b400867c371b16eb86861cbb4540692e57bb3a76d2dbfd9b60c2d1105d06ade453ee9a724bce9c5ee16bcfda66a95cb65ff2f8b191b40653baecbc5743f361510ed8c784754283bcd5544f1dd0747f11dccfbf3650000021c000000b00460e3e801b58afd8f125216a3da33ca8fbcb5c8507d8c56f8411bdccb46f136152d70c1a29a6a371f6c6b53eb4e83dd37167bbaaa61204eeac0306079901a2ab8f7a83d6d0751af8c40389800eadb0c57574eafecf388c3a0d47c1170e6cafd524b6394497934a19f3d6b65e1c30e280651bdc533b5880b71de971fc6ee1827483bd13c07f96cf6974bd587e9047aea1a93ccaff06277b44cf7a1add65554ecbede568a9677e403d2287ef025743997000000b016787709a80034c9dc0fb2f39f6234b047c52f3c160e640669fd90260b2eb2d2dea5524942937f032f21774a722bf17dec2484cff9eac716adb661e5b8d4198ce6e3b2b8203eedef4591f52d6d1642e49840dec7ff1a450f2f0fa5636b50ef8a84a1ec046537acea23e32d00143f4f062358bd51903021501573205a432d240fcf5cdc7df2da0377b27800348498d7b5047599ed8554e236c36f36a8b81868dee01ac54054831a25c28491b3a87284fd000000b02a2e52bafdffcfeca7bd1da085e893967e375793119394df95b6fa854a4f4236fd034355bdae04c4c9cc669ad5577fe9df8c1e6c14fab5f0a6d370b1c566be7c0c6e9b8cc1decb0cb90200217f8d922e2c68672676d34921fa713dc2803570139b25dffd2d6051a38c0f39b03a7da789201091033db872392c77b7385bdeec03247d638979a0459f1d9b4e3c9c108d4b189b006e11fb36707ca424c2d68b3c00aeba12b9cf5a85bbb705b72cf8a1bd9700000fa400000168000000b02d946b4e2bae3d0ef4007aedfde3fcf0405b8701d4a990d5ec700fc921052dda8319f59add5a35ea6b02bfa654dd65b83e79db2257c1f77c3d0b911fea04ebc10b2db3814aecd65cb91a5de5c022f730ac965dc2d5527a7a1bd3215b35a19419a776fb633f2d8b4fb5531c2249a4d37e18acd5c53516ec6ec43dd43ad7f6233f50b64968dfdfaa18bebd9c7a735fa4901590692d54ff6b2eb5a4c38d90c933dcf9a2c3358c290ad49859a4dfe1ab7ec7000000b029ccecd2419f7fbecbb95f812f44b1583c26e9390c896001b72e04270ce58bd419f40fa31048506295e7a8deeb13d357c14875677bf48bd59ea282b8a72a8ac0081d3aef56c47702f7c8548de02d704b543cc053675374535d6226fc4d995fcf31c01e025521f652368347b29ff4681324ac10216f60cc100217e5907d822edcf035dc242b4b4ea78f50e2c7a99765dd0f0acce997ca0c8480af38843e272ff670d2a070d862fbf9f4498414afb5abb500000168000000b02418964c5c942f2b374450a2ba919c7561f1cbfc07985473b8aaa144dfd277622a1377e6cfaf4b5b1c75ad606d16aa6dad813bb2d5d8adc5c9c43bf509a62a0e97eb6071623ac9eb5864a9ed6f88204bbb3c96a2c3eb4372676faaeeb595f961832e30477ac20d00f9ad7d9b92020ec313b3261b4b99781b8a1b28d77a03730d76931e54d7fe1edf5b140fb3ab57b107251888b8d7ded7705cba2f7966e5ca9fc158ea6713d0f569c663c0e787fdfe4a000000b01c3727083d0179f1e703cc844f9ec0b5ba486e8a66c7f2812ff61b95caae7888b2d58faf7b02c1f6619a1c37246f1bfdb6a45e19efb0353d159055d107bd35f1d1ca2f9dc29364e8061d8d7d5436b3b3780c3a7f9daad14468b6c3c8cf2a17d17a940cac5f2f06072093afda935f819f2518497f5e72b9a3a737d1ef81ec1624cd5c9040b28606b8fbdefe058ec10f37262e914474222771fb2eae95c8cc08263e88a3bfccc857ac24490950b9cdc0ae00000168000000b013551747eb0a06d3c7c509054b92789b00a9c398304fbfad5028696a9ac7a5c12675a74e42da650b2e6083bf79aa151d01f3ace34397603778e8bad2187b082de583be945d0f4f0a345bfc2fd6ab71898c78ab59b8152d691d6fade183415d3bc0b22aa03e2f1e9a31e6a0cc31c4d038020eb201a63d92e3aa5c5eaacedb2d26fd83d80a4138656813094fb8f2fdefdf1a2151c0c682eac499000bf30dc89899f9e8c4440e8e644486f8e757e2dec1eb000000b025124e0a7e741b07c7b50ccf541983bab609b525b4d6602b0e37040876fb588a217442e229df3c230a20cb2fac6c4ca60b5f00aa850bb73acb43abb73eff721d26609b896c5c96f2621d87f731b808bba9a89ded1187110e818f889bf939b7e770d47b2e026b28133f8e4e8f2cf82a3b27e270a4864e8003f0e06318ed0aa1c4e13f10d7c8abacbfa89165fc2bac2c8226573ac16967d1574061ade76bc2332db4d71dc70157c6ee1b36595ba5f42a5600000168000000b00909b65149b5c6dc7e4f37de9bfaa30856fd67966792b032a04b56815075c3cb82bc2de2af44e51a9aec53e8b9c1aefd26f921e740a362bcfe6c51b8bca3c7c79a5c7ef29e767743a03e3df6c7390bfeee6e9b6bdd5c651447b688e63c67edf95e4e28bec271b104073cb3ee0f48e30a24db70ed90f5ad7ef2892dcd71e2c366a87bc044730b25eceaf619b2fe713a090d0fb94e3483267357b22f70a2a084d940d287ae6189f40c1ad640979391c56a000000b00dba227e21fd0a04e80b29253e66aa198e50c1eea38075ec2f510442a3d514dad31590f4807aba77009fe4f92d6f4ef71f72c47f353ad5eed58437d37c6c17fd36df8053615f71cb2a19e32749fc9e70c6da58eefaa37251a0c412dcd948eb6e8b7779153f382163361440e8cc899a442d3c5e3767ff75fc6328305b2707af179bd549cc01f8ce959a436e77df4dace804d2b01dae4d63c25c5a3132ba6392fd9af984ac5b89025c744f540d657bb97b00000168000000b00a1c5328af9c347577966be4c14e9b9e5c6e589d32f25b428067cabf417df3767167d0ef1f51462f8b44227f49f82866e9fbb407b26f921f69b6732202925dedf204eaef4d4b6cd8c7c98259602fe92a789168b611e29708a19ca7c45af5a8de1b15aa30a52fdf919901ef212ec1f4a600463808cd1cd0431c43d261dd3d151103ae01e92c056d46c0b3563d19049d4c1aa160ff0184067c58329bce153ff91ef60e5baec643cf9e65117f97ff3f9721000000b01762a10c825d7cb9c2fdb8e5aa99fd96443ae6b3d41491b0f73b8fd17cbb8278b7960acf6db9fdc46ab6399a744c7ba0bc7bc83b51cec3da9f0ff13da242919d26e769c02ea6db5713389694946be608542452ebf9b8519f37e1b1cc9bde9bd3606b823541debc4c22ced82da312af2b2fb93c430f2eda0c6163aabf9ca716bd821f3d1dfccdb91f3ba1107b146b36781342374c1a618e1b7990a6d653c94824fd031f84ad47ae74099738f5acee673200000168000000b00083728a42461a163a0febba99fae3220b9434cf8bc835cb14c5581a5ee7219d9f831f2c61d207b8fe1c84b8d5258c66a45f1f7d366860f483973606f3606c467ec351c69cccd1aef5938fe81a9e2a88e9ac00994f00d3cbbd4839d7405cf0d002da0cfbe87cc8b7764ed89cc5d5093f19c353010e44935fb9c985d60f714d5231dca1521d790fdd3a724e949d6c5c6112723c602619f9d92928283213c6d11307c0670df46c004cccf01c402304b4a6000000b02b6cbd2dd0c6cc1e3888a7c63b8acd0b142ae0690c751a1a7fe99e76cc05171273565dffe2f3f17d27166630ddc94f9bdf1c7585e9d175d2ed0e3dccfe9c995c1dcc5bf33aeb17fa056b313c13a0efe9b7245f64d18baf5ab4e911224646acae7a4f037980371a5c9f385e710676643028009426f0a60a339e3eda0ea95442a69c138d9fc85797e58e8d0eb6a83c1c2e2c8421c6ba7e661d24a67bb28758d3e3d3db5f51a2a93e5cc0d3a2acc30476cc00000168000000b024cf23e0509894ff3f26874ca1ebad6ba645cd6ff738b3b5c25da45d0093c921e61d1709915d3762d5e3f79a54677bdf3b482372f3efb68084d5cedb62918ca38849adc2123ed07f83e0c9461b81f4712ecd81caf5e6650b85e37620eebe47ffedcdedd9c33970b5fc7bf8c28875d4492b46a9a0358f8414f316e54c243c3d50791ddc20f3a028ed5f7d848828ed6b372e9c0e30cf1504e589b66a7a59acb958350de918640e3b3ef58ca1be943348ce000000b01283f2db772cab926c5c2f0e3065d26e425cfb1d3167269bc087242188980f62c548466105d0f305f7316af310c2d08840c187b537b04eff447627f559ea164f19b5368cd75f7b5d7156bda8296320ad760838443a139585719396287a750faf64df8135e4191fbd40ec3639f46d561608587427ec7561a3693c822ccae7015879d4f740278d364b23398b872821ea9505182ae9b8cec485b7f9f2e4b7554707add275cd92f0e4c97611c70909a76ebd00000168000000b008168f9e17a71df21b009a479cc4ec7d725876fc1ff43d4e8876bac38b83319f1aac66317524390bef0be64e8d4c5f07fb61a640ae5674e79f27a582e30eecb1cc04e0a8efb1665f708a5d8dee86ebd281d5e3d951e997f9249dbd45393bee0ed890a2e4abe5ab8e78220e41f8f7c78a2d75181bbd109284a43e07bf37b0c1468e13b669177ca846f940d3cf2eb773bb04cc55379db92fe351ffab014ebba89b48ba85228fa0e115fa9b2258159bd6fe000000b01f8aa984e6cad2c76c94f857608de0f847e13cfbe6b807b39e6da24ab2ccb0fa191b91209dac1dbffe6c85ae78da7e4691e9c764cedf69005c79ef59deca26a4f35c0812aa9653a447e33c4a9c89a700ee3d0a145581236cb9b33eefc84902e927f39d58ba7bc0cf8cc47bf7d970ea7f0e411fa2bee5ee9b765fd0859065317652a01fc4b3d672fcf2c2b28b2587962926a8411ae2e776cf89310697b0f5fe52e9d775b8e52387ff85ee1c8ab1c34b7900000168000000b02782d9e3a062692c0dd1eb2975979cd8d321fd18168cb02281962a815047c94395b1e54096208061ce8c2796557fb1b0eb91da6518d6bf7f1477bc188605194b36f28d797ee933393e0ee75209586a4298d105b82b260895222842dfaa89f14a33bcb293c583dc39eee9a631fe84da80083b41159d539c921000505de0d2d51bc1d377f35102c560cd8fa5b9a896bf27094946232ca9de261ae964a305ce65211528e2666886fc9a1225f49b0254bb1e000000b017d62a6e89009cd0971abf632dbdc36ac008bcc1860c3f6a0e3998ef4a0ae39e17defd1030c2ec6f199e52e14e3e3ee0d0ab480ab6e9e2babbdc64196d712c78e35101e1efbc784ddad18e76da28790e76bf914118c4aaa4ed4ad7baf9a3fa39d6f8d50e0a9d1840f123de24e46699642fe4d34047765a55470a3fe1a4b5babd05c20087edade6dacc8a9cc372bd9a84191f3a56d04b5d06b176a5b8e5d6f6d418789fa7a736de967907e1942af4171b00000168000000b012fac7044863e8b0e47f27b31ba187c5d1f3c0a08166e5ff62dfadb575d7d27878732503d38be2ef539896bd75a358cec40dadc7b2ef38b1587bda7aa3170045e30f1f87552b5a8b6f7b0314f17dbbb9d73f005e862e3b1eff074ca1507a9bdabd40a98b8ecb51b8a06dbe23a3a7574a2651be7e7881111226833545cf7d8b94bc8ac16d8198d8cb0225a497dbe5278a1c3bfd0b783ee5e2bc249dc2c0d2c199849645bfac4786139a60e68678c92ded000000b013288a1cd8e013e13874f1bdbc88da037b582b0fac3ae6bdd95f844c735c901a0b5f68df0958e32212abcf49eddde58369838b348117ed55cf824e1735af573d9ee74b7a292e7dfc076c4c033e3f06b5c11a7f5cf71353abc7eacb2c5cd194bcaf1e172d629c62de575e3f37a54bbee711aa3ec5f8c3113bcb887613ddcbd0ebb0dd74e0cec904dea6902f06a40a4a831cb00efc721063e01eaea95a7f55d99c0f1b6c1a01b686ad49a264ba502bbec900000168000000b008043ad9e5afd1fc35b24bb875a13e186ee547437bd82c63a2becbebd38869c6174e4fe7f798bb3cf3057739993a8b027bc99b36b34f8583b9f80fd35fee876110d044c27adc942b18baa7ca602a03141529fc2a97e6bfef42894d38712a1f0a6ac79246fa3ede1a667fbb11bba7113b272590d2703a6505c1fd92f1670b463270cc1517eaca17783a00270e917023c71ddc67bb750012cb7ff5fc5610634532c2ef92d83078f915dc83089409a86b31000000b002811ef51db81fa0636ada3375f29b3669908703add2896cec35a052db6e7e806ae8661e888790f6a88f6cc93d316fffa48d4fc7572b07b637440d81315bf5fd911679dea7a1aae9f4ff2b36004ffb1013c494d1003fd882d957380c0f5509083fdcc3f4cd4501da86bcb8e7cb8bd61a01de700bfe099acc40a7886e174ba921b9c3d3a533ce584a274b3a7bc3b01369161860d5504c419098290641074cf870d11bc6485fcd2a6852769a6709d57dcd380000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b7370000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b60200000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000381100000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005990121646ddf88c49342087fdb65b3c93f6d9c0bde5d6a57cba4cfeb51de93860cc900000000000000000000000000000000000000000000000000000000000010800000000000000000000000000000000000001081000011000000021c000000b028af71e3cf39b6907d2c040e7edaf822812677748a2c67fa76efb2ab698fe3f2823fc7f53ac6e00999e105bf8f2c3ff4e147f4061884dad80d638cf38508ec765a5858b1f37d302e8bb87f29d97650d60a97500f1099b1b31e87787d9ce79dae74004b3bea953755228a81b396bc48b114cdd89c303ad6ba4a0578683df5eeb5980917d15a78f60b0ca90259acca9a510fe6b1a1b0b616e5b6daa0bb49df341af3c1624a66fc9f13a0f9bd067877074f000000b01590bd33b113f4c35912d16531e3e3795ea7d70ecbc9c1e141d421902565fa266dc3e6a250a7266dccb91536275394ea7e1885b28ea49865c18087f163820e48499aefab8ee869e77046db6559d0167b7fcbc9d1e98e728d1e50ec05dc7eb0bfee78b115e76c8d23c2f02b255ea535de23f1e8744a59bff8c4024653092421ea11065b1b3481fd1356d8844826631c0227fddce690c623ddddd6d2a5a4f43eea20a863a7878105cbabf70bf83dbf745c000000b01d90b229d7ee00cc66cc79a0d3eaf5fc10865c8589d5b6b5117b8e416a9afa7087e98137636994ff2b04c011656bff9f61c2a7e0410d5dbdf6fb052cb9198fd55b124c6faefb224577e7f639a7a2c79a5526d624948a52da1b8327cbf82f9b20121f7ffa20b2d3bab92e107997092afd27dd3dc8029857b46923cb955259726bfc52bff332115fcd1088de24415a8ed80d79cbf6e979fc68dbc563c8446c5b74db1e753630020bcd9c6646d979a402160000021c000000b013d723bb65b13a316680d9bcf15eae685ab616e0bc827a9c495a251defd1d132a36d92da8d014b48e8410dac23a5f9bae14cd6ec992e31a35bb79e34e1922b9e86944d60849e0f7fcffb320af9ee52e7248179c4c79f716ad938e5122a5c39d64e59ba6c38e0d96b4503a95f37140cdb179dc9c94a583494e5497e16a97af3bcfc7c58b04d6d086f7e7ac621c5135efa0cf68d6721626ca1edd2cf6c1b1a7c4198708499eeeb4ad1582ad5ef0affa04c000000b0293c20cb48f70b53cb37502055242da70317cc6eec626a4dcc78408f45288f622c88b3b7bc2619014d8451590037f12094c56a8d14ef6894ff7e48ac06a98a4d17e963e1d4835cca15cb3eff6522fd1c86e7f9add301efaa9ca8dcf62adf6cfe9cf8fdb654cc74fe2bf16fb2da89e10424b629725ea17c66cb040ef65cc226a0813a0a1c02d278ab268c6369ae6af5b21b1869b42f6afa0bd63f61d2535b7c41bfd2726edd5d32762223066192997ce4000000b007f01c1ac5bfff29528225ac1237f36b4e636c320cb23534644ec55dd5cac984a945084a4640bfd1000d970c9a3aa1c5777b8e138de0cb98f6d2ccab3a1b3ba8b455f4f18c9be682ea3b131f42bb797b0768bf018d8bc8d326cf5a40c08aa60f0011926d6be03141cd8b3af79c0bca0117c0361d01d5cea076c8f9c207d3be407e346b7575034c087cb289e9ce1cc1220e070127b77f6fb818461bff10d911235ef61b9d6ded44185fab1a8e038cc2330000021c000000b021467a59920dff95a1220c135cd30e45f4d5449db558b205d95c14cfdc2c7ed910aefd73e3bc57281a099ea5f4c5f399aefeb2421c7259a0f333db7de19fda6c2b4b9fe4269c5475dcb42083d8a9e12789f1b95ccd639220707ef84a6cdb1bf8a561d9bada5c72bedbde441cdea6370a1a7bb69f6ded55769bc912d9b9ce7eeba8f2dae87a71a35b07415855a34b43c80dd2eff43d880a10f809f2f38cea9c2d76440783b62674c5bab56c902212f427000000b0141ffb153cc8a5ce07a5656e6d5e84c4f925bf01e053c11433131d04b3a0627490c83316b5edf3f9a803a90710a8207530ac7327c297850558e66268e7095686da0ce22381dce9f9afeb9de9eeb931e1b30b9305df66919b70c5e484a1ba42f8d2bc10e0e6063d01f9600b519ee42079171964b264531d7c006e20b6bd2107b30ec797d251d93b7e3b722b857acb2af6113ab79f6dd087d44c3494d73d93187905c9ba498909e979315adb52e4537490000000b004c5b23dd37585063c4374bfddcf4724ffc64702ef216af8677cb2f7836fb9b7513b3a8a8495146fe58231e67dfa124e7bee22de16cac980aad13a28b98240895f13a689a9d3308f437ea593be962905f5d0d630ee08c0b37c2d5556121de4589ced2892ff145e4bc144d2167106fa4c0f9d090b938548490616f067a2f8681eee4c2b642dace80f9d1e37f45fb20ac60dab28514723c18ae7b0b2a5f5839c78e075443f177a2d6838f05ee202feca930000021c000000b01b7d5e6fde8aa63e2f971770a9f6a3410c8566e6b8a8093db748bb6bed7c914e80aca52cc936572242babebc0a4db3fd49450be0f953ad662a2781b6b8e8f534ebead19c7f147eb2f4f4f2253c9a783b3a7eef70fd05230a214c6f71105def66ade26144b1b06284a124639cb3b9aa81107c87820000afca291394ab630cdddec1935a8dd06b088697b6db527d1240dc0c7f6c14e4abb522dc72b5fb96f3f41a63883e48ff1e1b191128339f12be496e000000b00e5584ce46829013f30591db40b83c0c74f2661741f9775862b357b6641af8f73d6c28f2a133223f68b11b565aac8a40323024138e14e0c0ad1e9a62b7b0d9812e903470a4dec13e2f086a2eb37f8be013d22e5cb34d2177279df2dbfa841e4b10938e2b7de00832dad1deebb35367fc27accf94e799e75645746824eb55472231f768bb9251303d58f85c3ad93f53380d70b515a16c763ae87fb5c865dca56213da3c924a02d86238c652c51d6dd711000000b0242d5aa5c2301f646f26bce897ae95db1737360796a7b6238cd4fefc113ac2782331d4e0d90393c5ad030ee0040999cc3bdd7f8711309ea017cb24491b1f2a5bf8f2b91569708f9de6902e4eab5b97cfe52037051e00d77e5f39b379a8dda51a77af3c010a305b18fa6a589444ae47941134a90e753c5605d25ff5d999363d57196d2917ff23d7e601708d28a5d76899247c5fe4d8e6940998dd55656c7c169715a76dadea02b3a16667bda224eb445a0000021c000000b0111bce86732d12025a7b042817040283326206402ec03b1f7420b1a060da3a8cf42e62546d5e92781724c098ee8c43f28485d71504f3069b57ade358b63f8ea8677b324f2b5a3267859f9219e01def03bef5d1824fd9efb1c4a5c3be3a3e846df81e07a1925fe4b25524efaf0b247a290d5a622e4373b30a7e048a662383728699b2261f98561f1827a40806f731ad3e287ff3618c0916585361689dcb937fed96b64e8117cd78102d7a9770041cb9df000000b01fbc505c0c49aeda9899c1c3ca095600e9d668ad0621156494d69bdc3d37b8ede3c1f2fb358df02276c77d950064f469c1d28c7dddb9ca8a8f9da800c7b3494b621512aec38d625fc0e388089a515f3a1f7c77c784bf02bed456713da33862bc73ace72bf77014b10829366d72f5d5f72d9a1859526053fb89901823be02155e071f1a529439549c4438c64ef648418409642745a9353ac95d04a5de86f00d7fdc9876ed305fdf825e3e8fbd5db5a391000000b02320939a4b967710515c9878d09ad807e61bf260736a7af5d874465c9cb86192c818776390ced5b86e38721f8e69d67541c33f0e0804e7e3e1c3bc86423bce952d817e8c0af61ff7c9b2973866f1abdb59179a176c2ff6e4b481fa3ae8a4fd954ed46b9be4869c9cc397a4e99918c1c02b8ac1b9d3de72262d0ab87ee985b7477cd4246c842140fd832cea79a9e92e050b578f38ac13740b910956bddc15ae5b5a06b85f89ed450472018a3ecaf8179d0000021c000000b02767677f69d12c1b379686f3ca00ff76bbbdb73cd14169f8336046f0a8690fd67776465f5231b1b0fa2339b9d5eaec6dd1067fa65bc1addadc1624aea975b38dfcaf1d6bdb86a2863f767f2929d1091d17e0999b9855ae6646c2e460a2677c158c3211d63dbd43b552700bfaa70ca06423011b80ddbdb50bac729ade36bee44bc42cb8bd1e5acd190ed2b4368a7688a8043ce2e6b72f161ae77fa76ac6c4e1cb34888ff376eb8ba77c15d7920c3c3549000000b01d721a62dbb8b9671e920eb69af9675eac818c2c8066e2a25287fecfbd4f034c0740a78cd5bf6285c9f1e1c1da293eb1264c302c082c2b24ca87a261cc039329e1452edfb70184f26521dc31035a694c8e106ededfe55e33eb445cf88a52fbdfffa350b5a39f7d825394c79d5e719af7212e6e717260c7c86c0f9659af7c27649bc059d731014577bbaffcf434ad0a2a2ab1e69770165e0592c8f08e1796e8bd730dc7c35a97edcf6ed14cc394231235000000b0099f04e36e4f3f7b8c2928fe57e5a5050a029ea9b66326b30167dc533d9bbc54cbc2aef43aef01e58467cd4d3161b18e41e4dc1c5457f78385db64a3779e79818a8250ccd331e8c673cc61e6d08337a19a411e8265548054f30ecc8c2ed9fdb6ac39fd5c07dae7f8cfb94fa530c5c00c203abdf92de2e4eef5be94fcdd950ac0c0e0a5e26987e8c5e5566d81f7140db116fa0b90e2781cad2317d53e949095a1b05e9eb23cdf18dce60e70457190a3540000021c000000b00812eac67910abd48d458ae5ba6e72cb0fd8eb1bf18d5b52d06e88c6c9189b4f06c5fb43ea5461c78d4b6ef1f4e59b25531046757f58d88171c3a47f079b7f8ee7beb26d398cdbc3b07f9a3cb05dd5d99ae4721b382c95a7d710d2236c407873e7d2e28a388b68931b52b6434c37cfcb266c88d8cdb85659a598193d0f5a3d25084dfd95d07befd75b29ffe1031badf81831719f3f49d5dea2ef8763de8f3da22ad28013767808e842e660056c9407d1000000b00b8c389e50f6194f4935a93f1f69dd5c7621bf625f4b951afb8cb8f6ab346e670aa615a5ab63b33b4706ac106495f3a0f315837046f314da0875900866b15c8f5baf38e0b03ea8d8988468f1a6c2798ec14b8a2082f18b3a731b2f9aeaebe27204fbac7ab4db159bc69645ae5570cd762fe3a1d483479dc015afc8d7edbc93af9055a7c0940ee7c1c9fb877c00b66c1216fd2592549faae6d644d5547b5535d28be9892a8d94844a30c31ee6d802d8cb000000b02a5f747dd67a94972908353f284f63ccdeb9c5456a065f16267abed064f07b8c3386531b922ea63503c47267dd94f41b2e20db0e24ce29d824d0b197c463d2a1d8c012c946ca50d9732f38f97f35d6817a29a857f6f64703902bc64a05a57967f17f8804d0e3657f5347d8fc2c55762627e2524e4bcd4505d1e9fdfbd981fab793a53d6fee2ea3e35dac183bd6c135cb23b8a7d308c85a39d5778dee434fcf55607b8263e73630b9b49e61a1bfefccc40000021c000000b02236a683125b651761790f86824677291184078f9f78a58b8002bc26d9a5dfd7bebc01e6a46d8e2c295b844436a1412ccffa1c23d461f0ac6fcf8242efad0408b48d3507df34ec230bb575a253af27e29fba934644991488a9d0ef030caf0c2d66703a08347880ba61d74d7e549916b80ea1b4257035241c7ef4616cc5c71b2abb45478e2295284d4e9b1e821b01fe0d063973c93f9a44227815b2ce2ef49b8712b231b94b8d7b0d7993f6db43a3a910000000b0177232976d2132807889472788a18394e9de0275a706ad66ae9900b77b7d5a9797499a2ef3ee0d904c41675379a9356e0343cdb90ef60048089f2c6965a835df322b8bab15186eef17b208ee8e1781e3bbf1c012f6c748e4fe1ee7557613b329a1692040c81db1994ff6fd3981ec580d27bde001c7875a1d3f4df0b37d016827eaba50c183aab6b499f0946e3a4d13232f4bb4903b739b8f8ef6e1b428535006e5ef5227f005850dc2a4fcf7f23f76a4000000b00050a57758e773bed114d603f92db4ccd35811f756265e412f4b3867327b19d5efd179d51b22387976cf9244b3211657a5582a69c79d853e577ded1db37d6ecb34e83a8addee4c8ee1a66b38c766843e93b27c509e9e56316b4929fdfb59816bc171443b9b97a05653315ffc5b3a1a9106a1bda2f1c958efffe4c01c83c38fcfb095c8888181ec9577671d1adf35f7a42966014c2be242f0cbd54a01bbede9f5d4e988d53897341e2559ddde59f26db200000fa400000168000000b004012d1bdb68342a9c25ff708a2c24c8ad2ac5cf891292879b1fdaff81408c2188be968777575e96452fe58e784369b0c0ab4e0859b9f4ad3f04539122696a29c5295eb3b66dd9a565714f595a2e66281a4d70f05519347b6a446468f90e53e35206cb4658678b297fddc4262042929c1eabce3c5c480830477f78e081285cd9df6624430e897ff3644a98d99e62e3c40544ed37d456c0a1aab184457d564feb996f37d9736bb836f21dc40210ae937f000000b0001cfad969e044d24ba5b1e18e9df1bd2ca06be44faa9b85a89cc173f696506194450d4cba96300f1313ce3a39ce44cd0fb0444036afef9e7652c7ecee2961032b3f8dccb736a8ffef83374580620a421542763809c031428136c50b3520401ae329273f14dbed0aa6afa05f27e2600b03616f5508ebc44c16a4424d65ca33b5b537282e255a0aaa90d0587805f7ddff02a7609824a7f86a42f6b58e59f463a538eefb8fd848c0166422a2d4a0fd352e00000168000000b02bb6ec3e8c9a24332d09a72028ac7fe45df4f152eb0003c03a7bd9b152b3eb0c6afa5e65df98e6b95c1a0c09034ce77fb2b0542c1e5213a4f9e411fa0931f6cd15224fc7af4c276762e6f9cadeea5358df1c7c51d4c5a0d33bbfc57dd4b7dc06fc55a68535513e6d38cf6b0dfb3726f81282ed3942002680882d1451f52d155d010a9fb0cf8298c6f0341baa0c7d9d6d2960b7c81fa009011e8aab47134cb177c60493ba204c1027bad33119c2dc791c000000b006de0dd7f8e786a7c8d4150ba09eb0e9fdc4ffc99ddf6c9eeea52fd3c0c353ea20c6c18c479bed3de363d34de7080d6df23f894cd84c5c6d91e9f97e2495739a775e87dbb36aaad505f8543dfa475997cd321f382b00a465818df78a39a3f0d32bb25bf121de71252bcd8f98a8eaecf92761148cb09d71d60d6fd1961631d9f07953bafca71d6c97cadf0c3a3b8fb10026c0eb777180ded3be80f3a8a0cef59b21f00957ed38a78025c34dce1983404400000168000000b02940e2c09f05ee629616473451fc069c6631b906661d7d403787fc1a58060dc9162e186f20db214bd3bf2c1cd87226587363d7feb99ab4e2456c20f087a2c1b10feca95b6f0a999168150f36824b9b92907d4d62b9a4b9e21c68b6678bb9256241ca88b7e6ad51a9935cfbebde3c654211f54596bb42e0352e8cc1d453fe8ac25bb36401da77abaa85630528edd169e11aa2e1430a4ce48fffe0500900e873d4a8af1f20eb043a9abaea47b37d301390000000b02396d4625a310caa70d01f1bbf29d863825763da8d1f0c5774fc49f53df5b85f31a7d75fe0c9bb5b4b82a7c959bac5a804c609fb40a0088cf1b3092ba19fcdf579b1810aaff9f07a8ad0c9a79b5669bfc7e8a5bd2cb9f5de7dbe5618501f20309d97a5967027fcd460003f78c66674b40dbf7214e13aa330fe2bea3aedb358d99c75d98244700ee0056184e7845fe07203c93da515c088435252f715d228a4d2537c664ea8bf46d9ada1b3a1c5bdc7c700000168000000b00ff0841351483895e108492cffe28e6b2d8dfa8c4dd411ed8ec2648420ab1264aa59a8dbccd220999ef014e3b63fe69a386cbdc449317afe482e5cd116ae3dde050ffb4bfdc68412ea4f96f1ba6ecc757ce97a4a0457c1263f7e4ef412f01fd3ddd802511d38110b25faad8ce723311d126966b05cac14f654219e2c514cea74e5787a2cdb7426ad01f0f9bdbfe49234279bd837650abc6e5beba2ba0b1dddd33f6605baa3c7c9a753b96bfc6b95fedc000000b02cdb5619e17e313c26b1ae9c2fee30c583df4a29536c649de3911fbea3485cff3a895d4731510482b5fc94f3897cc80e421c9cc6270c5952d6588d26767a19c42696ffe4717ca89a4b0408754b47dc320d968301a205a1cbd639e24733bc9c3d86247649fad121a54c95a3552bb3cbd1302524ed3114dbfa5828c653103fbbf5c5f0cded3194f6c47ddfa5ba8063f6410d6c288203e7618069a528d55d09b9d6f60d01f5dfeb4e76747d9ab67829e1d800000168000000b00f16bdc7b3b4d0f491fddc88d3c35a6da1b73da7e1b93fe4f536e941cfb38fac227778909885d6b2fcda6c07b51593a4fd79c6fcd23f0a9a22418631248879415fdc49b57ec5d049a8b3cc529631c9461e93416dda8343ed46b79652e571e328b189b6bbcc8e597585ac308bbe5fcd1813a6baf8219bf9801903ad21ab14fb5fbcd9efd58940c5e2ae12e95df0aa18400a8ddb4c26b408ebe28d7aae4ad5a12e0576c0a0fd578ba4abf2a9c3ee885dec000000b01de650c0e6a2435e12c94ffcfe4ddeb14f16a75283e74f4439e7ef499334771324e68a8bbf0c1af727a459b6770bdec08ae76cb9b9d4283ac1986e64a493e8df9668fa9c9b58d7415f2996858c185721b0551457fcdc64599246daf7e56ff19c2b2a408897d99f13d164a3481439e0f31afc9608e73a27d2677039cc7abc1cc29a5768c0232011e4c46daaf01341881f2a309f2d150c52893b00503753a57ca6e7af9fa0f1cef680c24193cd0ab79efc00000168000000b001ea06cc58d688d938ece274eff2581edcf09e82e89d82bf5defbe4d28f796f76a18e78f900b4ce22cd5cf3900e1f14a53790573c0799e51725ba1f80427fd2b2b74b566431a68d5bc0f86d26dd10776dd60f3ecef987778a1a887ee57f8baa42bc2ecde2ccd9ad44268335f7d8e15bd0e135726c3e9cc4077e59daddddab9537ed750b84a5c6696a420904fdc22783628bed1f544d196f27374a067ba441162cd619dd8d88c47e5cbdd476f1b7fd63f000000b026811df3f9a0ec27b6161b4e75edc04c121c792d298ca9f2094d5e50fb01d68b173b9bc4068a34e098b25fd3de954199227ad2c52805b75c1c242ff5f3644be399fa21a532345a72329f4efcda351016f055047b7e82c9e803ac83981ca337dfe80c5f3f0a1d73e7fe8ce16f576db6070ec0340703b9c16e239bce7024cde8ab40e969f362e877560301ee9dd2e4f56117785f56414e4b93113d3e24d5630e7bc4e2be9acf70a124125fe5c30a9d99e600000168000000b0131eba5286d5b8f9e21fca8987192b742b2c164a75db3411dd0caa39a16fa4d45c352f33d5a1c89ae664e9d4c6658661c65e181301dd4a0ca88c93a507dc41740799514456c4201e3f28c8782f9f00fcf32c76e612ddbdf1f4dd1336c6653f4c396100223ee734312dfc18bf2c93a3010580092066699b4a2505c8881be5fef5e87ca98a90ef07b9559baf592937bc061b6e901162a602805f72b4a3a5e4d34d2e8d8a3e26b4c9a6e398d8ff746bb60d000000b00c7172f9aac16269cea7563ae94d883b18639c636a242fb57dc5f6afaf73edeb25eb6e0d5b93923cf296f5df2270cafeec8d1b59db99ea96763c7f0f73f8718f46e63e80284a0b0577de171fe45d28c6824807f5d2dbdc9a47c17b18db9d6899fd35f809fa183b4c8ab1ad2fcf83b83e0257a00c227131ef15fec26b9dbfd4200eb595e05768cd101131c6d7175b19081c419188e1a1ad1ce1181b6cb21e65a00247d14ab0716cf413b66955745fa63c00000168000000b006157e0e36d281ebdb8c38d7456a0351f27351bc25efec336c4538ac0d8858eaf8a51009fdeb100b43be5a487c8cff21414ccd5e514d3ee40fd63c0331c5ce336e86cb19d27ecbb0660b5663aafc27945786aa4a2d5d93b74d06baacb547b030bd4ad8babb559952e55f95ffd31cb6f01ec7be1d841ebb807e37d268bc7b3b69c55bca85847b01a4fe7f64b99a8270ce2216b3ddbdeaf67bbb3becf6f1e039e5fbf11aa9a4a7c1f5fc2f00c8d1f9df46000000b00b0990367631f90cfcf04068b0c1c2937abb4aec14c0c68c0740ce3047af4734dfb43eceb2b66baf1f8eac039f2287b045b763ff9334cafb317c16a7686cfa13f586a561300bafebfc02a26038c11b4eef3eca3a06b66458849cbeb4d9111e1f52299ee0eb90c4624fbbe7fc84384ce0133a608ae182af2e9cf872c80226745cc8e3896dc404e7d154b9c408e6993e200a80f5b63a4cb53748d0e437c058ba01391652188fd0143dbb8ee2362946c05800000168000000b01987d343e23ffb885c792400a41254ea8a6f0b24489087972e5e56492b3c5e4f031d0f0149af777613ef63c7f22b7da23ef67f7a70f289c0891b00630934d3804c1dffe3fae6adb528a9cd1534692b175384378d882585f3f029adfe93fa39189f7163846096b6c931e96f46c25968672fc75cfec4d9157724dfd0f24862c5c6806a7727335e52da52a56f4f84c075fe211a26c7abc9ce508ea914d17a32ee04f6bf1165c1fc5cfaa93f8395b9206445000000b00845b111ceec129e3b8d1d12916d0e55fdb47b7d4a974291af352d8fb6e3ac1ff5946415b887395135e87ec88b063fb738fe3fa560143c28a81a5ed2d6d145f570f5a8e970d79e2a50f22a237e094076a2779704375b57fca913524687109701dfc68c24f04406b2de556723d020f317174e0099225dea53eb373ea8e894e22ffda7f3e83c3396d50988c2e251deb32505fa374d6be815708bcf123e25df2f6511e8868058692ce86658e655fdb56e0300000168000000b00e8c0f6172dd78e3e8c40b7c6a34133c8b0bd2688a3ef79dcbb29724a2bf22da32a662af7681c816adc15b50713d212679ac0161bf472987a1411e33cc55bb2af7a47d214dd48c2b987447dd2ff636e14ca75ded969a72f8dbfd884cbe8b5e2af518e8d802b2f21e718383ed5384bdfa0ca9a100e300b43760a851cd75ec082d0feef9f444599d28c5e284d2b7157e53042a47ed15d59173472cf5a577adde20ae944ca2e2b469058fe2b2df9391143e000000b02edf72a3f6ca639e7c27b2b74ad010392fbc9a23528eb3515b0885f5d7b2ce448b30a3626edac6c349952c1bfc22131d32f7ddf8f9b265be42cd2f3733c13f69c84e7b9b1451c4d5c4d3b38a42b6a0ae7770bb03fceec01cd68b4fc452624471b32b8dd17861edc0ce7c8155185578550bf76f841853a0bdcd3cfe5b6f607e24a3b7d91c89ae36be25385238390d58b72e9dfe16cc0324d2bad3ddf3bfd2e725412cec7d2b2e503b62fa99a8e9a0ede000000168000000b0141e6f2e46e53b2be770316dd8df73a1d40ae0fa95503f2022fb20d78db1989b164afb30ac73e31343e6d40835f2ef7526eb79cd4fb82405446f25280922e2eefa1f0a301ee1da8fc08b154ff2877e29a0a833c367908ef0a806fe30d8a5b81c1fa1ffe97e74d1f9704b85a30747011020b792eb95265ef02e53e87da6fdac249934b73a0f73191de5e3c7936d3dd28413e451199268f243d3f24e88fbbe75a61f9b2e28080e0c933b18e7a814525d3f000000b013faa2680c0919d0e33f51bd76e9cbfe5680e94b6013d5fb581e8205ce188269b4878822df360e59015a691029f818e10d56574f289ca05ad8959f3ceedff324e1ad3c9554c23e255aa29eddaea38e36aff9361578d84a18e515e20d7383865d873e57167061f3d444dcab77909fab9d1b9ba933a49d806d701123c928c94ac8ca527874be2d0cae0675ce6666a77dbe282b35da604b47e45a5ddd7c5ff4f904664e0543e09f2e027af1460c93f0440d3800000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f73700000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f60200000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c11000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d90112ed2e4b38f6e75420101b372307b3d2f38c00ab0b31792eb6f350bf881b71ff00000000000000000000000000000000000000000000000000000000000010c000000000000000000000000000000000000010c1000011000000021c000000b01e5230189319f14ab0efa39e4b60d104859784ae68282f85c8e52853e303be387fd1a9bbc3447c87780b37c8509cca3563d0d0f653780288094f51d24f41a79356933470652c7e0f5191778bcad0134f70bcc1029e49cfde87ca163f88cc1051693ea0c26d6021ee358ce60d1afbd8d30785b0b9536aa12e8fc2bd70d1ca9b9940fba45bf539d45037d6f48be97cdf592b908819c0e35d1f14a0d5129014c6c8b5c4ce351ce5f4e273a53cfc98731154000000b01dc8d9999fcc6ad54f110f053fc7228f3a0c153946de89dba66100da614a413a39e1b52c3f8f2a54b6ef4ce6b9adf469ac3ff4223568bd4631c443afcb7670e0df29726b8dfb8c34bb572a2ec1295e597840f204996825768e6e4cded44c3371ff52d008eec9187c53f269e973dcd3ee26cd4136515041f19134677fcb060c42012edd8b8a3a1a44d5d49b6b3128ba82161938edf6081e776e0564729fe9000bfac8be86c61c2d13331f66d93873bb56000000b0010b8b8c1c736cfcf7dcce0b9ab8454e7e6728a4da56559693744ab966f14c17ec457a90391aa8ab6576cd04fbdbaeb6d58b0e9404076ae7323c7e8fb960c6172242ff184dc5ba87743b18f359e6dff4f0a666cf3a88b55404b3f41936295553366440f400bd8aed3dd8e373232d3b8c2cee3c81587452ff6cd31742f5dd7b03660a5320f485de8d4745eee01ecbfc68290151dd58a44f4bbb692a4579b606dcde65ef6410914f59bb394469652600070000021c000000b0040657fd6b4b21c941e9085d59398e0d80d642e991c67c1f01bccbfd1d63f7b81fb01d7ac8a96948232b75ec5671a24f450c843b5338d4deb72963316f115a335c5e4d5c288744ec9f06ae119e727a26a1786bef7b3f9e0ac5614a42bc09462543965ab2e55fabfb749061dec004d3e81e8c41560ab599ddbcb5de70162d73ed08cfb85f7d0f7036e751d65c8f64e09705dc5a976362d2a1e5cccc07fe4a39a8b0d0f94f917a910e2ee47e82dbc8fd90000000b0140dcfdeeeab72373afc37ead979b38fb0fb13f1a6225ef12a1139139485656f6c4bdfc0e511a0c42178b98d53233dce29d6fd8781bb4f593612ab3ea6c652a0105703b0c4e3a4be5c1becfe7c44aef30f08ca75da86bbf30850ef0bd9fca1b1d3d41190b3ea823987455ae7fd4dd5e720971db1d3848924b2aa519dd3963958150ebe9b17e98cad87b5ef673378b1881ada0d2d1d57bfd611abfb9553a7cc19729ff9f185021ed3b9fa1e1db3bfec12000000b025de2593c16146d39491a91219ea3152e81d1e11f2cc4ed06e646f65c5cf1f93babd835ba43dc6158ade659e925d40402151ca1162fad8b97d43dbd4796b882d8949d29b0d333f98f79407e556ee9d6195775e323ce690688547f69814af8c899d099098b069713fd0472f0a04805be0034eafe1186918c87716ea86b9b872a48b88cc30a4a42962b910f730d3db693b2d89ec6db1dc403ebdb4ebc35bc5e4f161c9aedfe033e8f1b9ec58abaa61d71d0000021c000000b00edff87809bd75540d58aeff67fef959a0d5690499fb55021f75ab30f87f49d083319c483d8727c1718e56108a1618318b373dcfcbc01e83029e8467dfde4e4afb7afba6fbe63caea1dd72a4b57f9028e0adea31bdd9c0db76d7acb509d1c1add9ced1b4391113196ac335d545102a5f00df1225ba84b67f35970c446ad5711e0e06d9f38e2332e8180bf758f6df0c37030e89e09a00c55ba933288a1ab7ae561d417d1095594ee05e0f4b002cc70a08000000b015d8148338d5955a60b9023216c899eb6c2286a22537219dbaa900a14a354d3fbbaf2ec6fb8edff397d0f5d112d1a1eeb7ade24fc024be67005bc5bedd3da44a2dc7d93aa42092d5c70fd2fab4ab90ed8d8a6ad33e058e9563cedbecee1eddb773d240de9c3b481bddfab817e1d6ab5e00be620be1ee30fdfec7866cc53fb94c8c7de0afb5fc036585a71dbf547727a229d326c6a850b63aaeda890ab673d6c25d19c917f2a73a52297ebb2ff49f9691000000b02d6bd4fe7ba13886f9346a7f36491938b5f07f8e4accb1f4ca5849609a773d9070dd85f9f4d86fabb78e6c25ed34374c9dc0d93af2e04a4be722db662df98e1f44bec7cc60047d2d73a6cb5b67b97beb69169b798bb4abaa75b2b38607a60c03e11e6f5791d119e8e595acdece318aaa1524fafea967d4e30c2875eaa903fb1581f138655c327200ace755c748dadcf30f07931398bb467af7c1609426eee76f62baa0eb0e1267bea2e579e3d502aee60000021c000000b0194be5d29733de9417607e3bc57fca64fa4803d637c0bdec5dcb6de05b544e8d2e2d02349826667d4924fd130c5c4fc77726e333fdfc8ecb8069de7e951516597cdf6b26b68ea427bf225fdd16b27a3aa674489feb392e4a65c67b085177fdd52c3bcd2212e6415fd8f6805b3c192ac5298ddcf58317c2ce7eea998c25c2bd91789f5e5923860dbd2996b62bec211f28282ba1c797914dbcc7b0e24beedc7b5fb4abee320aa1f77de3e26cdb0d73daf4000000b0251f205e2459d5890559f8f3e9c25ec05ad834ff0ca7f8361ff157b3ae536e5060080eaa664cf514ccfa0ea7684837bb99335be96530608d194f7bfdf857df4faa48d87b06d4a16b0a665c72bcda643031136868020f7dc8c107371049aa4a3a7fb0a2ee14b6dc422b2c8ead02cae16913ce6cf8464c68b1117b5b79ac8cbd0bafcbafea2dc35de053aaa888fb2fc94b1a52eeb8d3f0539208c56217ca0e250d55c3779a9e1de22342e876bd67b2bef2000000b02f8fac27fbf4a08150350aaf3747372b27e0e10707e6b1b37f1cd7965b4f33694e316a91e6cbcca77fdb8e7966fa3f324a776f89b55c6ea12bf974bea09c0bdd580eed35bbbc64328771e042b08ca93ee09a6b9207de34924c57a2e8c513f3bd9b94f26136096054d0214d50a590f67d07f690fac72bf771f6b93f961e829468c53a2505e56a43e1497027b6f1117ac821f3165b7fe86af679f69fe5c3ebd852c0a56d2cfcf992f281ceb4099d3ca0d10000021c000000b0124a707e0449d96a720377369ae5a088739171736b4db65b3f6caa95afbc2a5d7217346efe05430c1b6941f76107a9b8d27980ce12e6dc413e83beb573abccf2b156f750c3c873e8e601c27eec01dc1debe4c44cfa911030ed2f6d4298a7c00ad186123f25e0fa898dd5619ebfa572ef046e12d555d7be24db7ee0e35a2213b1d01f76e385c55af1309d6b90c34afe4721c50f8040f7458debe594857d35969d7251badae2c6044cb9f92e25f7d93a4a000000b022b85d047c87b3fe773ad1fdf6883eb77689455492c52b74ec2e0084976e76295323d323413c1130f0a22295e2abbc1d2a9f28b77b1d1e6b6dfac460a810e80a60bbd501f9466c921f7d0e490243f69b25c5179f95d1b4457f03c7879056c0057ae7b4bf0f5bb6de55748eeb20007299178b3d1d859c6e5028dbe1fd1851e58d9be5ab47a29b6ce2d6aea9c4f1cd7f9418d9bac96947579c062eef42095d3f3af5f61ce4baa5bc558df6784e70fcaeb7000000b01d8a3a82d6236418ce6955cc30282529de49cce6b43f88e0ab4915d5a1d2d208621629500a1efd6e2803d790c9a3d73524259b1504988f88f26d97ace1375fbda81dafe309654ee051194a000fded20f5b5272e908e4284b8e091ee9cf8eeee56f394270136ceec38a32533129a7d37e0300d228e4310b5b42dbc2f0f461b706648aa6a436f6df87db174f309b824afa2fc44f892cd9c086c7107e163653bc776304652072c1a86e52bf5794dea2f3f80000021c000000b02a2816c42d45814e5030bd2ed7d4028e1e0b7e85509054e746de4659d3d2dbf28226681b59d5a0577e1e550e08ec436af9e4029981b635232439404bb5353ef336bf27b3822806ba012e6631ff378d67afa3d4da6e17dfb72b7121caa5d06b656873b60822129faccd24414e1b79da750eadeae84b737ba859ffe7b3791e75d57d14861af28f651da3bc63a1c347a18f1f535c14dc43675fd43481d8e293686921e6cca55690806ae98828eb97fc0913000000b01c1f62898750b60d23a65727004e43ded160a7b9a400b14c860fad973a572bd42109c660fa81a5f82eb7a84e22696575e53c8eb9c1819dc75efe41c0d3a1a024a7a2024015e241c5a4dd7faab548b2558156364c4d9f7854d5d76f27f4400f641cc577ccfcc34a0e513124cb2a660e8e2f2490cdb95314a59aa30d082ab3929c2e7b4fae5aad9e5ef51e60441d605b840697071e4524b360e7807336280e73aabba58798e5add86cf9fdf519c3d0d320000000b00f6d15b98c267fc54fe5a5f2561e8c3f659ced80ad6ea51ad994b94cd46ed840f836cd66d7a84d56fd227dd9c5b1adcaed554edf36cb5432e71d84ae6d28f880ff609c88dd8de38afafbb64f74518648b06f7e22ec0e466ab765f169dfb4f3db3c3ceec2faf023bc9061898f18d1a48b25c56da17032ef29a424cef69ba6ee5560b8419df58f7eaac7359720d914e8e6119939e9de45195afe5a7590a1fd183ffd129fd3b9705cea74a1c1fd797e7f580000021c000000b01d5001c9aead2e11916d74740aca1f2249d355b9aa1650fdd3e6bab51f7718a514e77702d7d915a6ff509ac76a84b4f2635d089f2c5a82bd49c5cb2e324cc84c73875f6b3d08017a7fadaa72ba348b47c8a1ecebc3de09a5a68f88ced5b9b5524d6fed0109279e9c4e053595202dcff80405ba1ce814279b7d361f0a7ae2ea7ae730326c83906496d7be3c3f74e750ff304a2cdf95f2fc116b822be0faa3ff16e82f5e84bdb26d391d65850d17a7f064000000b002db2b2e186c315cc0779ef608375e99941a61742df38fc1fbe3c2e3eb3f7c1f56095eff3964abfc98eb978c65fb1d6acf488cd11e4bddcc44b66a0555c8dc494dad5dcf0dd89fb1dcc47164aeedec7d740b23a93168869e7ebfd34237f3431e1cc35b1aef7f131529bd7de27397ba341b6821a0cac88164ae57d0cb44466c77036c779c1149f3c3cf9dd9d354dc64de291d279e7ae6190bca4989fe41a078e5d30a170fce2fca374320f58799ad2724000000b0250bd8125f11b30dfc6b6fcfcf38e383f0c7226e0f6235db7e9e7f46cd29a205b4c43d408cad8ad168a1af44e12e4f34d4c2ccbcea2fd26793377a647b410755a2d83f4eb60f4498fca3c26ebe08adf60c4c4ba011b4412fd921ada08e4766498fd96d164bfc7f4ff5b20a73dbd9365a161bc2ae7fcf54a2f46be12894541a935bb1a41a87eebe603a30e8deab404089048a00ce4e8944fe5912d46f7304f1bf4b11ded77bbc6b43bcf874f384e3fa8a0000021c000000b01d106f3d1a5a6809d15d461e12a5220f18ac27e79aa74923df5b9870dca65132b18aab60143103441b21354dff15fd5034826266b2e46747b2d77473a35a1662c50fbe381f2f97112c2abef7ef443b356bdc71e465f02510ab1d57f6e09af36828b893362518a84995e3a01ad80b93691cc854f080d0b6f9570244db21dd98c73d56eb361cafd440daa79c4c29e03f7c0dbeaf33cf875be90b028f659fd50d2c38ea9abb3f43eda244406b2cb76d9fae000000b0151dc5d9cda2bd54f954e17f41df11c0f2a43f2be957fed34c672b5a94b60aa97acaf918ae9a1d40045e4f6533d28bcffd0a52f25c1273f182ba577121fb4e2a9479f8733f75771c2faff22866c7e00886c96dbeac186422e978848aa579d93f877c5dbf978765691899ce129bf714d223b38c82f30131dc4b6e807e4b5a9f2bf4ba61a537d89a72c0ac88388d026dfe2d5483abff46037189535726dafc3d67bc4e6245689b89468659f2260703482b000000b007ee3bcd0a172d6addd3acd05918ae1aea9ba129e67fb01aa6a825071ba60741d65aa8da298a2bba9a098549609f0b0d9a7edc04a948efca33e2508fdc68d360835d61539c582fd270955e0d4cd26ac81beb24c07c00aba623dd447f6f68e6a1e168b555a78fbb0947ac7f0215cf1524275ea46cc30181857a942141298c7e7d5ce320492ca24c47cb648cd39e091b0b0e04e0798232d6654347b9a9bbbc39c8182f43b243f5404263f8e5f133c4671600000fa400000168000000b0030e0d37d06f53b2c2a703d52b6d75a00309fe38bdc2aa2a03343f0c19fa0c0777ac567de5cee26a5f9aeffa56812cd93b254f6ad0f2569d1a47fb8d831d1bd686c75f02987c6e8423fe90e4770a37ffc4a3f79737bdb970be87179b0832e7ba5e6f64afc1801c76ac6c69d8b7ef1ddf2bad1fe29382da15f36e4bed6d506c3d6b716adf1f9ee0cd1ec37faac404c9880d2b9a13355097f698c688a1d1daf9492125bb2c8979cf52dc7c7b45c70b84d4000000b00ba5867af12c49f9b715bf5ada2c75cff35e37cdda3febfb1fd133f65eb168fb458118642b36b7b0f6bb598bfb0d8edee887c842f6caaa1449f8d4524caacd4bbba2e158201dfc8eb11d0e04845ac82ae95866da91da4a825ec7a52009d690178c32c361e979008855cfe2374b909def12f0e5747b4a598548fe03988cbfa9c3b9ab94655f78835275d89c84e2d9f64212af50b226b886dd9598f075f5e78079a054431de22fda98e5125d1de60b023900000168000000b01080812459bed64bdd952f740c1d4198051243ff81001b0198f4c2e98f49b24115e9793f16eda35096b0cdb07d44076c3afc025c57e2c08b5de8e21e916b3d85ca0d14cb4ee03e121c0f66d76ff46f0819cee80af0537c21e03a4c82b64e345e77eb755e0163e6c9bbe6049621375c94145cc77e16ee5e68e87c5eeb6be6afaf598aa95d72313a2380811308a70c50501079164269036d467c641771c89cb101a8b9a278bd87cd1f9abe5d4689576318000000b01266b0b738a3afcc2d3e6bc112d04fcd95b7292423a5cb105918ff2065c53c1d5cf6c8427f1116f776b254d36167bb7eda28d118b4fccedd204c937373d15b2c458ccd72e382a96856620141ef8e627fc06d0efe5e727c448f5905b7892c1670690a8b2da51745082a8bb3a99df1d7b02009414a1e14c61d9cc92a4767da0360e04f8818b27f283c1fda04e3cbe7b51c09a47ca32b6cb097046ad9364a70f36f9bb4a7e797f6428b7db980448c32354d00000168000000b02464ffa1c0ef2bf97695ceef0f03c79df69aee260d074d760f04100957b061daec3cf50abf63af003bd8c77254375dc5d1f510e4059a85e45f0b00468bfca8baaa012dce4282dc851f07de90afe4d52477a89c6d417803f8cde38cd415b3b6a1ec0fe71f2b9b9bb35d3131867ed4ebab0c217cf6dc6657f8f2b22fd6ea1e35c72b5f696e38bc0c3b2e2d8b94199f1f1503e8f1638e14200cbfbff8746e9c0a79de856a456341c6eb65aaebf32ac0a5e2000000b0208169c12919e4b227e7891893178edd65fd7886ee195e779f6ac16fefecd9f9ff1d34449e3fb612484ae13338932fceae18fd5f1d2b03ad8a315ef1f2a2aedc641d65c84f8c891aa09255c7c366a5eabd6627829629f1a3f836c94a32b792bf75dfa523b5194db43aa77070ab5c7a0107706f710174f8355cd5098b4df2d28e39f893b69b57fbf5d6fe825570f7168c2c103c2043afbbf580f218ad6e514ff9d821bf27f93bb5a8718123e56a5e7c4e00000168000000b01a58d184b638e1dd51b1669a6be91e6f4a9cf9133f84697d57e8a94dc9cbbd4bb948237525af6f71c74c07ff4fd80bbe919e1ef12d340c2025578f2473dfe118e4a2d0c9fadb63d7508c0f5f9933ef4bfb29249dd53df44ff56724b92da0d8cbd806c60fb8ea7e5d8c6355a91bb92fa416fe2f8e8a9f69951b2b4fee24d1b147c24da3c5077ee7b6b0c01ac06137031c0aae9147b19e182d85570902b16a627357770f276a81535fc2b889c62a6e8d42000000b027a57897f8b0eedd209058949c69ef76d1133716ffcf3f14ad6b3fab2448a13df5f2ad29a6e5acd0f6aaf788e983c3fbff90ab9065817c94d5e203e69b88b99afc0d111e9b08d23db18f27a16fcca7446a0f9da1b825489a048dbc92137173d8c28a9c60b88d1c2a581796471dccc42e2e276708c9a261eee8962ca6208dc28779524de5215d9a9fd1e1d83358b9a0e01bedac1ef990e0955691d7e7fe349c202df91b3037fab7efbb284502e62bb8b700000168000000b00c33561f388276d7cf50b719afdeafd51deb3dbc4e32166eeb5b0ec7890a3bbb7a92f85474ea7731c0639cdcb74fed6e1cb0ec730a89c5c4b7da46eaf68780eca4797c7da8e1ea71ac9f291111c4cb3d30c5115393bd5d9d3fa255524942c09ef912b2fd3d9e1bf0f27fccfa2e27c9c81e8495e9f604438ba950964d2be67dfd0a88c13535506667c91de4aebdf56e932bfc3f8dc523eab18470c5aca4287c4b7fb51a1105c8ed55495b6e7598ba30fe000000b014998ec4473f43a897234482c4391ad1e50c097f21a746dd2ee4eaf4845d521cd345f34196eb2a95876d9dae465eb497ff14d9d8eeb48c9ac3f31ef7f8721e0c50438062fbc3eed66a5e33bf742178974c9205295cc7225303d195eea98633cd54506857fad0857699dcbace36a5ba4b1618d6e4ebd2b76266b4787e6dee58081e39d548ad2e5bc2fb294a929f0dd94f2b7f51bced0ad927dc8a565adc2121f7946a7598e33171f7d37df00b47ff5b6400000168000000b01c0740d7da631077d84b795e81e1e2912a2925c4cb06c67a140d0a14698e0138680ae095c892226120f96f8f9dd79297f95537d0040de3b73aee54dbfea018109206ea69ddf8e72108ccc07a8a365ddecbaf5301724abc297617d5855559fa67abb3fa70c5c5aeb7e0a29c5ab9295a110c971ba9f3fca93fc497d321f320f5cf304ca1189148deebc72b88672ce3ee1d0f223c76e1554476ec13eb2ca43fd354c8958f7b9fe2e424fd54827b581cd3a7000000b020dfbaa01f90e588f612cca5ae346556675f6f55a49e675fb2be33e1f8fc308ecd0c5ced8dcd3f3f4c82c0a6325149de03818a30607ad1150f7bdaac86d3a352482341fcb8d076e4ecc42bb8692b430b5b8622241feadb354b52fb86c47186c83bfd539102715187e0d52e5409b1962124dc1762b18b853947f9c0c610de81d9340b5ca9e49416d8303b1dbddc6458b303870bed6d31f988da566cd7ebf699f695cc5dcecfde37ec2a87c8b830ffe9f800000168000000b00f892c0db9372ffbdc31adb8ecf5b877239310b4d4d90341affcac9db4461587a31a86dbb7624e391251ec5ca053160716ecf2fb3141582e817f969cd1cead892ea85b1f2bf4a8bbdc57424497e70a32602697b53aac4336b99781aabbec364901ee641584f24563ce40a130f9ccb9150b6aafbf98bc4217e8da019cc27e85049e65d72bf9c909233f0d67ff8af7166104bf1ac4fbb159433ad0d24cb96e74249dae2837d8dfdf91be41b199789fc26c000000b0156b8323d03eaa58c2615b3429019a2e1dd7cc710be9b3628e8e8b0618b2147a2d22bc30959ac0028ba60dd2ed96ee6bc4e987b2bf5e1bab42ae9be0cae9df6b0069ff000d5fa68c5fad3666a19cf87424376dedb2014b7e7120e8f0c253a35f75188a0d57055825ad19930f360c00b811cb041b624266bb318923aaa686ff3016573b5b213215ed4f3fa8ed21fc702706193161f3a9712c0eed2a52f7852d532d1224d3098ca7d05f538bef68f76a2300000168000000b01f7ce232879108dca501e59023f273bf5b5818ab03c0dd7fdf2eb7218da5843b60efea24413430cdc76c259b2173a40e11a559c45c77b5b750ff8906562e415c2494c2026d27595846a4f7d94e8e890537174d43356d9e4ba1c870288f438cf0d79d9ac42fad2a235b12f88279c2aa3c26210a832462dada291b60b77fc691ad5cf58726b7b46520b5a3d170d9b5d3fc26eaa9af196efb573b0326361e43e5b0eaea63c941a441753a7760b785eb69d3000000b01d04d18b51080f0ab3bd6854d44b4a727a801eb651d5beb8650add59a96a9af8bb51cc3c4b98f5450b4df79c3cc68ca820e44bef49f363d2d5920aa70ba2943a5ea637ee6647ea4cb57cc2e7e0ff4811460d1e267227bb32081fe183b26e072e33777c29cd00f8790c0736289df0b4291ca462727a93a8fb7f36f2b716b7155dd02d7c1fd5b781841c06b9390b3f27d529ccfc011b7e2c22f03d5dff36839ca9e2b537c64f9a36b04c66837f20ccb6f000000168000000b0000a49a54c6d55828d92c40628802e3d273f52e967260319f73cfae97f41c1f1b4f9c6e8fcf4b7a1df5eda28df42c7b1b315f9d966b9aa907dc75c4d73ece8b30de6e2fd132a9d815cb5dd7c1478b0570b04b35841e42070423b51a91e5be7081c33c95696bf2d6bfec7ee0e5668f14403802c4dd8f33e3448581a99713625b4586ee194a8e14bb779446ba0d62a976c144105e19dcec5f6a7b5691b90617e0ca97c9a19011881221c296350333037f5000000b02e025d5807f478403a6e1e23155518bb93e329646de0e0269f701ea20a45f2a68ac8b66d8fe54a755d6b96dfca9060ce82b4e15890d6fd88673f023198677f4afe0d1762fd3203cc08886ee80eed9f17bea3e376da5c157846d1a1f68f6b309b78cbb5b69922179d744948a784be44fd1922ead640981e2c54d06c98a5a0db4d620fcc7f7a6621e42ed49659fe846ca706e3d2825b0469b20fb796c557705f8db58656ad75d4dbe096e8522477763b6c00000168000000b0075951f922f6ff6e6f18c8940b93bfa399b688c42b725ca3e6e26045862a32ea4eb8e0d41889e9a3c2af56527610401e84ddebc8a543f3d19c1be107eecb33baeff9fa043f17c17972e7a183bc923dbac63f70fe1309edb3379a67c62b9500c9d7d1804be966bf7b7d2c813bdc097cb90d436f9e27602742a7becf917db3f122a7026d590e89e4153a5799aa6fb3c8a601f2577d4f2cebed0f89706b94856e7386a0ab2104fae8c220674b32f0a722fe000000b008e59a641ea6f2a735b9b860d75e3a263c254cc737d1832d215eff96e53d043d9cb73aa9c158ea4e089be5e8fc3297172bc0150c9489c31f6de3aa738028b9f527a39e1aacd166cf9a4521eaf32110d958ba9643b2c2b9e453d1d01f1f826e9342259dc0dcdfd54e646bcf963578593e0f9b709860eaa1f7c2299210c3fee688f22a20385e09a24a03f045d31b2af51d2c87516c7cc752f1294faa66fb642df2c38e1301ed9fb552e714c55d25a3f03e00000168000000b01e4179e5ad7826acd5a7efd8d9170775d1f2f182538a2aee1c77d80044eb2334c7255b7ecb640f6810d891e71609e418fbe670ef8d5fdc3f8fd0c6ca29cbb6344fcb4cdaf4a9c3eba84a685879a9c2b33c9cecd3c15a86ec4915bf470cbf1e0ab701d221db475db33fa391c4686496e813bd1f871a8a9f81c033b4d9888f57681e285f5d56f196abdb58a6513947b747113cfed77a5a59061361546c72bee1502ffaa7cd49b1549ca4bd9197d5f57571000000b02d6cb6745c2a463652cfb52f33faab01c1f665bbac6460f12dcd19a6394e7c4398eb60f8a6c2d7b9c13aed45ae928f6145f3218d4b40d815a5ab8c3cc2373faba8c3ac7a02807dfae60062bfad0e230c32faf94bcc3154418e2c11b0c64ed487317b0f0eb78d7c023301472b74199f38240174eefc38043a74dd0cefd5e5f55f8c8a306de615f210c7802248e07ff44d166e57422e585cd4a110da89b891ca9c12d17b0236e5a28d8d4c27e4046bbe0f380000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f00000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000000000231000000000000000000000000000000000000000000000000000000000000023200000000000000000000000000000000000000000000000000000000000002330000000000000000000000000000000000000000000000000000000000000234000000000000000000000000000000000000000000000000000000000000023500000000000000000000000000000000000000000000000000000000000002360000000000000000000000000000000000000000000000000000000000000237370000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f00000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000331000000000000000000000000000000000000000000000000000000000000033200000000000000000000000000000000000000000000000000000000000003330000000000000000000000000000000000000000000000000000000000000334000000000000000000000000000000000000000000000000000000000000033500000000000000000000000000000000000000000000000000000000000003360200000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000401100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006190106cba39ce4081d9dc4db5f51166f401fd1d0361fc9bd30cf6d907ad61f27376400000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000001101000011000000021c000000b02c44cf1daef3a0f4db25e7ad27087e6eca4602194dbbf4fb9dfc8725bb0bc7c6d28ae57d84279ef1a32ed7a3020f76e2df5a956a1fbb238d486e19bc6d213feffab064689847f2843cbcdb14a5170562298135165ad2fa52f3c7a4814a2cfa99807384781d2d30eba66525afda47c40e12a0278eddc53c7947c9546ba13a9f44fe955d890b15d2f2932a9b48476b5ac4202a7e4e6f3b3e31331fdd7b2add0184e03204b0fd607ceb509c2f6bfdf73971000000b009c9e13350abe0731e80e50559b750802417ffa6ade44103a372e88d6aebb532b8d775011cb96edff560375dfa6baf9960bb0e2fbf478d262164004802f170af3a57d9bd9bb35f249080a7742130cc0133b722d786f477bd246c4875669cd15cc6261953b0adb98b047f419af519b2c0148b25d250496427a1f7221c11c54762f41616106b247a80be2fc8814f1e8dcb192ef8e5a2e8b912a303e5c307a9daf18c92ff15c7eb350d9360d19573eb9eb9000000b028787150626f72b9d1dd8b3fafc000ce240c2cffc542b2689e0805b9c5f6af27aec3aaf8db08e4143f4d84a398a41853e740b20538331a0143c4ca50c4781b0d09ee6cae55d20e955df3e5519c3ed650b930fb657a33526b29cab708ae0810e984a3a8bcb3a4ee2d703798d61c7650f017e2ea1e92d2267f9e4622c2fcc5d971a25d35d2e9c248df43c1fafd2ee929052d4a74a4e822fe352f8afe171e74a98c9e13b11d3c5d038efeac68b5350852d80000021c000000b02a398b0901445c7ed2159f29f0256609e85363b7efc3b3e0aa344a7c6b24d40f74fb76335949e2c9550852ea7afe2945fcf9318a76d251f11cf7de97bc71bab4f4eca8dc9f6270b09333071c60bb42e3ad353eab4f6edff5be36576708e17404ae927c5a330452855f3cc8bb3a62adfd0498d9545e02a74903eda94d9203232a919ea9c86b1a32643aa9986467bdb01b0332a22c8ea3a8fb64a9e367571e732e62bf96027ae4495ca42cab82002d56d4000000b0096f12ead4ed9f80ec8d38eac23da17dc0c9d19185b9472dd6d962b3d8dcbf5bea062b2f8db8cbc07ed212361df0844da136985574f5defddd5f8b6cffafc0616f8cd90857cf5d7ef5c9a392ba2c8657f0c2d0bac0a98468a0fbd4595cab91c6380f46a2e3907fff928720fc33052bc40f8aa35a56c657823e53b73129796763d42bef1f0a2a841765170ea34ef72c08023929f9860066cc6c74a4e2ed8e3744e8fe04222517a41008f9f7dacb55daa3000000b004be03bf208a7d7f8c1f2dcde8b9060fd05453820f6311df936149daa4dbfac161ece7610501edc5afb8d4d0e35530652c79d2ccba362991b99b4d6e42b5e3b1189de597f93fbb73ca969f1a69815a11f993117a67b55ddfd3cc2a702ff3b7a76b1317c5c463e4cbf515a887294aed6d17431c4e44b26c55e9e8f3fc23fcb8240e17ac618829b900684ea9177d5781a427db309398648dcd6e1101ebc965790569c748271f3523b123aea8061b830df60000021c000000b0165483cade72cff92ad9268d39277d2acb7ca16f0be32c39a3f0d9dd552ac3f2408f3c781e0856754d5ed3a2923e0cca2e167cbc3e1279f2bf01341f5c90f4297fd20723c76d0c1890b9febb991ab31b512c612227012802094a84e9ed7ddb87c9eff3fc6dea7bde19f8441c1c5636502d2aae9b0d13befbb866adfa6bbd7a590ee99d6602c4e38fbe009a268d75f7121962174bbb3cfe83694bb8c77217ae0cd2b2fb553bf9a03ea6de29cedda3f6ee000000b02422c1e28403da617120254c7725b64a3bbf6bb8e64d9ee4f6a6fdbe551408abdf336bb8d522913366256b036abf028addc1dd9eace0698a751df59cf35f5947e8b6fb9fd2aaeb533aa7746f1746b64e78d48a54d1c3c9f46830da2e5b6ecc8b8f4530d6b084a8b1c767c5c0a4a215aa08fe407bba9514b91cbf7078cfb3b0c035583632d6c06a4167058c7fdcc7be892b76fed9077452b37faef77cdd2403318dcdff767a0e9522c8e72a1895e7a5f1000000b026d8e0820b0849488b031d424c10a6e8cc1e5b9b1b9fbb1c4f7d2e530eac93ec0af3ed43842d680a4b2b9761ed72130955ef01bb3bde6cdf1a9ff0320b0246e9498a67fa643f642f16f6bdc6d26969fe0239d26079a8fd0873043bacd21c879bb871c7bc5bc75ea699853d82ca510d471219702122272310e23f403ef208bca44327c09c856a8520a6597bad28d565c4116ec4444b2a176ae16354fb535c1c180e772bc2169e5c4645277f4b47c3c4450000021c000000b01e3f7227c3637bcf2a84f2ac9a65583a19030fdb5e006a496f6765235205d812ae5a7d87cef9910733155131be00b62ecd343dc8a90160a68cc78ae253c57b34722aef3c672e9e472d550c3e0f99817f6bc91619df1eb5eb2b0fc884cb9cb19bef7ba878ab67d26758ea7595bdacd8742e902eb8d743080f602e2a2d83fda535343aea021a5be0388461f74554095de40aaa7770ab3ef48d135408627312a7c2f769d19d83f4f13e2216c30437e22e5e000000b0247e1b93ad56a66f47bd85e3084b7688996597ae0a272f3203d64f54374dc6d0cc6ce1fa42d6501e89c3071f2b07f15b631bcfa5b9710c7ee4938a7578e96beaf980cce73219a0d966253ee322d360bbd29f42943bcdf93fc6f33c4df7b125576d6865bd270f645dfe83dee842cd9a5e05004f8503d4b12abb0cc94e4715c85496ab14af6a67211b3302624ae87f865d1f25e448227b36d99f0bfd7362838347837ae490ca72ba436a49e96c9d6bc123000000b02e72fd1e481aad1d60c4edacd1cb7b45291e441f6bee3a9fc8cb833ffc91b92c2c2f63c8e99b435a3f1dab0dc34336d34517e25920dcde0dbc3edbae9a2798b7335f697ac9ba9154f45f98e7845fc77bf2b84cca209cbc1fe78f249e4f9087fc85c24de3cfa3e80915c654ab03db15692cfd652d4b9cec78dcd53e2b11a271348af584c33e4755719f62714253c652d117e8603dd14d203e725acc2b5ee1aa79e91caf79dd28879afdcad1ce0e2d0a700000021c000000b024bd2a65f1249717cafe44bf601a54e886974ac931895d32a4b7b369c4b06c96dd35c378bd53930a648417ce08ef34c40493ae4e52fa28547c27efdc506208b18142848f751bcae9e8c1eb7a3d0d9f888fab9b4f635fa36aa1448fdbc168795f97c9d81e6b633778bd1be6aee2b21a5f10f0742698bec359c2ae6a209a0bb1e37f426f7e55d4e9c444a53f145232405b1064e62ee13de91ecb054b21df455af4aa7c81058b0138080068f11c78134187000000b028000d932f1d588e7d2a8a86875007f757d2dd2add83691f2db9119dc0de5a80962e5afb7ae16aa8c86c90d8bd482f770334af762c8d9da81000b31a64c5f664fb87bdb5346a208e73da4b31e46633c20d9cce41e680e75b2f45e4387459845e03ed16c65e311cc7631d1fe176225bd72c84b4a80c56523f03029c8fb8c0357b9b133edb650f9bc4056f12c923390a1006056aa18938e422685df0599a0014217f2d0301ebf4cab6a42a9c831e1e4141000000b02ca8b99982a0d3dbffd9a9781b68384fc077ca137f4c4d072715ce2766920e148d288171052f80d83af84f7146cfab72418cdadb2ec91877627be60ff96fc6e67876e6ab65974d0628a65fa6e365f2d5c2975528e741937c381b7ff2b0a7e27833b7718c8141aae2d04876ae5b10dad902c29a2f86bef47146206862b2a69bfaca6f15a9c5bab868d3d7218d54d9095c0631950a0bc341ff30bc3712a615880ea5be2be9884cbde98ca8206531c737450000021c000000b02d3503d4cce95cb21a90373f61ca1588dbfc9787ad78e3b2bc8d613d64d59c7874c16f7618accdbe6618f9e53e9a9034029b5808d7cf48c521521b5d352cf07f2f28416b93573ed8ad5aab9d2e25c8ff720c1643d7a3d2b6f30c851b34b0f75539ed55b879db3b04f64d7181efa7c1f42e2ac38f4d50734278e5d142474b232043fe3699333d761089069cb501db8ac206a01875140c4c058b671ee709f3b2498beafa9f62b36bc11c00aaeacebd14f3000000b01c864cfbb4bc44d771830db333e5f246b53a1ada94771486465f7cd32fc14c00d9defb2a2cb23ac7bc393341b49547541962901ad0e98de877ba9c1764e1da2503899b0a868bcc6c5b6ca7556ac4d75ecda8efd503080934a33e94adeee18158247959f3ffad91469fd83985247e65db2f8de719affd416af1ed5c2cf58aefec0a852e236ba2fe1bbe3a8f0cf7cef6d015da24622a409e465dfb26c6998eb8ecdc5bb54bf823b4cac7fe272af12515a1000000b011093861d90ac1397267599cbd756ec31b4ad3b2b3df3f2a7457e0b28e81243760f6b5479571fd7004d5d48e879d28d085e9429e7558d42a6ff4c1885fb298c3d48bd53b769bc08124ddc453cb05de7d05dee5dd929f7428d5bc6f6522f6a1c0c69ba2539a5fd3206aa592c37df9f229195f0530d8fbdb5bb42fa35dd1fb429a1f3eaa19b17152e7fa2d777e8269dcc01933c2fab084dca70dc030c1c07531505fe55adcd0c7c386131b8c9f6ff355dd0000021c000000b02f1ce0268ff336aaf8171d835a2e4f62b86db5d56c1d32c60fa777d6ab5e0fbd7a2a64334a52cabc36aa0f6c02fa471f49e23f6acd552322f56e11af8e8daf8a6aa3a535a0d3784d62b236e5532418a3ad1326c938ac55cbf5ed86c56d26090ba5108e76f96da374e12146b0728301e70f4eabc218272179249a6cf08ce0bf6f96679b20f19fb944e3e80a7d8298db4719ece4b00039dd61c64c34d96cb28aa3f185e1178af56999212b36b77a1758b3000000b0193c5f7b14bf1fe6987ed7839304811250ed31c42bc7cdbe5b6204a0b2bfd6473a2d4e7adc1434d1d0749103ae0fb69e29b404ad794fd28824d1e1160227894e61d9e5dfb18af11c4c27bd81e22c2dbe0c79c055507b94ae9a8321bdf85d425767cdda075c01de03574731a0923c8b7b2577c5a2e22d6e681b1d5ec0eef1c59280a2cb9ae55752e3a3c4b2e623f0e8570802cf8a3c66ba6ccf35180dfef0246a975918ac5119f39af175278f8884e884000000b03033b27f0c4890c3816e1ebf2ed7c37ce53753b540916593f9e20c38df9124cc85972b2f034e46859f884effdae861102db23384e205de5400e73aa86bafab3906ada9a368e66da6ccfc9362d7f727c74f07dd31c72403a9f25d4b3524dbdbc7301a134d6bf99da381a2e60c4265307a09b6dfc7611d241e5090ef429512b208a22ed764faacdecb7020798a4d6181d02746157d5623a3587f247abe7d0e9e6f9203338dbafbf77e510d74dfde54b8a10000021c000000b01a3b01ed828dc67efaf1c157e1b864b5cd8af662f2f67e8a3998968ae2bc2530a92e37f57fcf0d25c98aa368acef50965ca10b5f1c9d6508e6e615d9cb52dee75b6e66462950c3495073ec700a1f4d59526d9289bfdf145961405ece6cd6026eb97aa415db56a2293f713e36a7735559102bb7aa0ac4fb6a6dea062de2a228a072823b098708bb608e79aff54527ef4603c65e7e9e5a35b0e7782d81c4a077de6364d93fd9863ba1971e0a440a571cb3000000b0004364462f2de9a06a6ec063100e18ebf4204ea0d0957dd9a728c7554357991e1790568607f4f672cb04aee3b7514d6cf70e6f70fdf381749ab0e5a160b5d0273f45593457a3ec9901d18071b533bf75d29d317b93bc762c0dec1107aa441775e8dfb2b160eb818bb4dd3029bd76564c080fa8a33d60c9dbca0201e444c6ad0617652879e6d41b9f09f718c421164f630a0878ee1d918157636fd12408a49fec777bb24164cbb21b5febdd2a521f9b23000000b00727d640a18311f2dff7c7f98fdee05ff301d76bdca05f7590846c022ca257796177c3205d0e0b471e1f6a4fd7137a4d55eee10c89a37107cf26de293fce6258203d5cce92fa853a7258f10b77ac9b51916dfecc3c15abbe7b3a1b17e139d4888fdaec43246197d2098ed33ea9de870430529cf44ae005ff582a2b8dff9f3b6f4e474ffbe939431642958d8e6008ac5b2f636403f99e1e9839633e0925fb53570598941fa95f31138624e57995aa3fb100000fa400000168000000b01025b62054a062bb8f96963c0e39b9de9932c56cf386f2220a51787f0610f999202e2617f008d24c399bf83576becdf0581b87178215aea88e23fc9e172730c9cdf6b18508d8d6297ca035b82f965911ef499a08c54e1c26475e710529f5520c07bf5db76ad000ea2a437af1d3b0bf4026e7c0898f04d84f03944ea3f2ca21956338f14a7b9000c4af734f19160206dd1a0a6ccf0462c90b6a85bd2926ce4fb0fc088f15bfef02ac77f5fbd77e9ee7ba000000b0008733ea5fc7195c7d84e7137bd8a3d8bb01f291aff650098bb63a9da2c9f0a2a201318e165753b31c8f41db308d95d41d948cc0224f7859164044ca72a4b50025be50a17a007c27d3ab9395977fddeb6239908ac3470bd90e5babc6fd02dca205a62cb350cb34ba4495a901cafa42b8146ce68999cc40ce1f01baa0419ce1ca46b4757b7c0157e33eef611f0c338f311b361a8da6bdbbbf77307d0194dcfabed9698cb84078fd4d1bbcc87af1eef50a00000168000000b00d81515e8f7333ad181e1897561c9ba58036556439e12d13a3c6c7639c9721087ce2ef19de8913e751745e06b5d1dcdce59d3c435bfabf15b0abe372fd96d507b4df9ae3e439b2fad4e93774ea300d0195196f8ac7e448d44a6ff699c3558c3535b74a7818aa70cde9dc642700adb3640eeff8e22e60879541db5653616fe34c776fd99343e0fc1449978c5ef57c2d7c1c298131deb5acf75fa3a0ae52cbf4152441489843d0851c2906d3e9f2ad728f000000b0070c863ce3991ef82b248c8d76e043fec034c4c44f5a5bec691159ab905ac830d21a76cd0298ed0574cfe16e6d7111bc3a3a53a0f3fceb4fef61070dda6cadf31f5fc779e68f525f88d499d82fa96e0bf8dee7404950931b9a889bf8945604da9248a8f7c359e1258895d717f9e1c83f1c59e7053248d88e10b52e3237138b94552f78f7a59f1b70980fe302612afee602120b97f805b24565134e196e9d8feb68eeb1fabb398290715292bfa053f28c00000168000000b029e13941548de2d6051e83831e6cb49dc38595c28f98c2addbef49e5d7eea3fecdf14333b23519d2bc85f13ab889c885aca55153ff8db26f63905a02702459137db0f844d6b96c414e2e3806c3f31134474f2c475a30f669ff69c7e9862fb9b582a644745879ed62cb49946006ff48821e1d204c9aac0d33263f0b99d5f6f2631d352a03afb326b774a38a8b3347738113ded5f41a1ce9e33d175a6abb6c7f0e73b840ff1e96b5ec3417a6f7754eec20000000b0091d32305e60f345d7cc10d50a194bb4ad47336531dcffe919ba174db3bf7e6f024e857cde107b145fce75f8886e9fcb62e288a50a47a10644e7ab8972576baff0e0df1bdbaa1e05236062f87cf41dfd81db649ffe8a1c5778c90b70b4a48b5c90895ca207e903c09789dbc7c48e7b2504eeb572dbbe3d54fabe1036cfed74a8ee6b315f975a6c20ca4fdda67bf220461ff9ffcfe7c8f54d7ec3000f8dfe1fd8024fde5a34eeb73591b7953d37803c1400000168000000b02675c0a0bf19702cd2169daf4ac6402c40b5a8ec2c7f0b99b5793f4f1067045cee1c9e5db795da39feaffae57b86221b3187428273e9fed467b71268777aac5430372d8fec8f2c09bac2d042155e6d152f0cc8874504ebff8fe0f33ca1ab71cc44b6ccf636c8de958e6f693526ed61af19781949223e2f1ce7d0aed58969c4e6c723a520837d8f94067803c0b71a8f7603327f1044699ee9d2a8ab36e14be8d7fb9cff66ffc39d37f12261d199758036000000b0228d93ccb2b08dd9c42a706184774595514a460f780f5a3cd0536df742d4cf9ab8b1a8f96cdacfb7d09bc75b4086165a16df84f077ee1cc5e44bc966efde59a7edfbff18d879262e7db290ae0e47c36d95ed3bfa275156ac7bc3548aa4506ccdc8d7aa7a04ace3c8ba83eb8ad89919f820be96e238cd6d4562e3b3c349d512cce10607e6ba64cd759107e5e508b0d14f285d2a917eddd74da5f7bb40f0dc9bb2d377519586a875c81d7be07460fe600b00000168000000b002b2796d365bfd58933a2d1958ffb7c03e52334a84bda8f407bb45f9f1795421bb19d9caa36f3826fa6b477c1bbab5148688c7c4fdf13eb697da85e2916741b67b5dad529f1c2120efd14dba56757a1e2bc35f5f40ef684b937acfc54f349d59a9265fa1dc3becdd895b78d31e7b89a60ebb448c078c5de09a95fa20858d95e50f08da97916252bef97f8d269e69ee9f0ee2aac70431feed7c541edeea9536284be9ed6caa35792beef346738820cfaa000000b001f6042832f24c51376bf79ff97bb572bd3121ae7422ff8a62b5251d27df9fe5276070f3c785b815cfaf5969e3069f2d7643d047c31a7605430c257e12e6081f97270d59713b7d89cc7fe28ef22397c8963e4d2dcb429e3ee65e621962a4eac66040756455f5d5fe5771977e53e6013e21469f52739565c775e9cbe65ad722df9da814c05a546838e2983aad0f1480352cec891e08d15ad6506d7c740197a7bc7c6959800feeb6ec88e2e8ebdb5d2f6c00000168000000b006ca575cab809c00d8f777d46c7710cf67c26b3f8729adc62b5a5d574b83652f153c07045bc7253fe11f2e0f79bdc7a2eff85acd1ec3430f59bf678549f8f0be844eea6bb09ccd885cefb5bab3584b1873c0e7421bca7e95b331d9822a18f80de43bc280c62a6402ca0747dd7fb1389e12ceebdf80a6994d57cc936584b0807f34a8fb90fcb622af545b489f2b3ff95010623eb3e09afb6a4b6da80a17c0d1d5d9ca05fe701327c5372bf8ec12245024000000b00b29cf4b03fded2298d5a76488f0b0775e2fda5641d4236797435b631b1597375c25babde14100b55f0c439a510286b7947030a10ad65ed025c40a8df590c10adfa82927a029e470421d6db38b52696a99fc87755158852e184e9bc21650e1566588696d8bea8d5cdc69266fa32a61de0fcbb5f1cdb7237fd60901d153b46ca627f7d1c121fd749c67140e098da6fdcd1c07a9052d21d26b7a2ed4a7b359eece06ddd5988f412392e53ae5773d0fd98a00000168000000b003599477d3896bd7bedc1abf16e5e0a16814a9fe43adf7ee650ca48f508abc5b8b947a517cc5075980aba76a5a68a85e30820334350d18bc458cc624cd2851c6ae9b40747721150cb2f846429d1ceb9a5f97bc1b713f566bba9761e47964e9ffdd19b33a563ac505418f2d8fbf2a03a31b5154b322a6550aa7e597690ac48056dbf019ea13cdb4b67271f972e39885061a02d9e272d33e16be17f819f0b3d010351276d2108b9de499ed885b42de5633000000b0091cf19cb865e1dcec874d2da0b3279bdbffcbd124ab88aadace5d187c7ffd0671467dcfd4b776be572771b267f2e62159e8fa8721632f51b6629c41a1a679f6bfd6fa36b95b661633407a188290c557469549901f7b9ee827031c54526ac5cdceb3038b43a46825ef9a1be6aa82e9e209361356b98b6f7957df31efd48a95257547d4456e8c1e975c093c0601b826f92770ed6e1dabf88e210722e78d229c73a9759c0e858699ff51645f287735cea600000168000000b013b4f4678dd21a30d9f2ca1916511e7116496fe3345fb92dd5643bdf1db76d50db8e1551201bb2b6d85b94e5a1b3508e2f8ef86ff915fe415c348eadae7622fc64f518cac7bbb24e195a80efe0f54ebbfcbc83150039ae0b31cd3525edf0b409126165735a492d4852214e068ececf1e0d01ce461dcc3af32008a84621dae8208922d7f2bcb7bd83c2358722db8645cd1010fe6277edc78dd2e9790c94c55b9d0cb886cbb9ca6d025ba7641a9b3f3ade000000b018a7f661cb64c636ee30c9c371a764a3f80e657fb14d087d58c1dab506944853924543dbf38e68b579d1efef7f28e61991c763a9c4e8389def1555c264091c1d142ad41bdfe5a119287a076b70d2e4046dc4dbc8204ecc6cdd1f7e285a89c54054c0748af4cc9ab10ba54fb1da3e78ee0ddbf0b52ee9c624859e55a298b1f7314b971de0922f1b127844744720f4a6ff0194ce9f6145f4a40a3a19c55a05cef8ad36641b8ba4905ba5a77eba07cd37b400000168000000b02c4e340ef4edfb799826a5b8e449efaa65a0c31d84df572101b0cc5c348374e7516bcbd027a160563e725d188c6238969dda734281ec81082cdf53a6ca0a92babfe4766dd50b497c69a7dbc407d482ca714a117948f4372d2ce53643de88f7127b646e4d944efaa56a61758d6a9ee3461b4469fd99bb6f408f84f657be85a8f553da9fc8a1fddb1f7bd8137238023180036e2a1423d1083b2ea849e245e57fef533d1302fe76a709b23b9423f2114305000000b02e639458bcd5beaf682cf7777977b2bf4804d8fa1fa9ba300aaa4206add43d38553e03d645d32e0309823a2841b3c5b062c57443e649036fe3e4cf0e713fc9c94764acc7b987a41c1d91c3f3d02bbdf25aa807f9bb721f8b6a6929e953b7ec6c8c339e2c24797007d46f6b5dfc6c5a5f04f972eed9b4f081cd0659d65dcffcd197a79a6f60179814fef45f0a3818ecae2a9961059b4a1a5b9a969b2edda8590fd0f92d460c691642c6c47e6a0d61837000000168000000b00dbadd9e9f6729f491a2b26a2fb65b62e6b9de8eb6160e599da4eea8284d094ef3acdea12d08a2b9e3fd5ca9d8fb7825bb52f9c1ff82e8b2304b1909df9030e7ff71dd71e4eafd79c66fccea1a46e88ccc5e92bb2f1a113db7f5617a107f47f11e7f712d4a84080bc9b37716513e530e206d975ff2ec276c2f91c82e7b9e4ded3a3459423e30d6dc0d99b8b0c7698e870025d23fe863b48f676208e39c6a0f05d466edc78baa622aad1dfb8e42082487000000b02620ec53f2b876a2bab2acd8ee08f0be7623f51e74da90600a87780aa88790599cbe1a13fd7f6c1f845ccce8b3d9c20c9c15b6ff9100e5d4404d49610964bd3f036bff0d9bbc0c776bb0d241598060b57528038748def77031e2c062dcc86cd57f5a22c6a7bb241240b1e2ff8cb8060126ca27cddf485fd5f4b27a260541023df75f56d2f79d6ca4d226afee7e439a3d1976a0584dae2259506dd9e607061ab2769054bd6998d548d8375caff3bcad2c00000168000000b0083bec20b167b79f445aaffa47873be161b3d27539d4af3c055e78f9311b8ba0541578134cf6286bb56e346a18347a48b07f60bc785d211f735cc5631a7f5794d7c227a21336ff14300d164d2213a629b39d17978eb2d61fef27ebd5820aadd77a0579e846c3327a49eee7cd2b4e34be0dbc527622a9c77aaf8e54955ba6fd7776fcac362eeb58891a6d908e2032bd7e18b50a966ade9700fc802eb438ee8ec812ec25546ee726e7cec4703ffbeeff32000000b017348eb4f9fb8a0ff1f035c91c0da3a49547ccb5aa6ffa5084ddb0fa09d443f5753a907132cb1beac6a2befedac1f8ef77bc83be9d5074d9ac2bb01a07577106e4f5958ac96a66300f98ec7f381478f662dbfdc7ff77679e4bc06084811d960f13276675aaf560175fddd08fe79788a0012cb10db47eb964254d04ca35de823882a00c06424ea4a23bf064c86edf81b52862d75e05f88f65f507b5cf30fb938016dd570b70493bb77a48a93ec757183f", - "txsEffectsHash": "0x96d6dd6caa42f221143e36451601ea093b69d59d2cf21ef49822ed185f9b8e9e", + "archive": "0x00f4e742fc0ed23e57b5bdbabad8806c1fc9f51695dadc9fe2dda7a6dd16e830", + "body": "0x00000010151de48ca3efbae39f180fe00b8f472ec9f25be10b4f283a87c6d7839353703914c2ea9dedf77698d4afe23bc663263eed0bf9aa3a8b17d9b74812f185610f9e1570cc6641699e3ae87fa258d80a6d853f7b8ccb211dc244d017e2ca6530f8a12806c860af67e9cd50000378411b8c4c4db172ceb2daa862b259b689ccbdc1e005f140c7c95624c8006774279a01ec1ea88617999e4fe6997b6576c4e1c7395a22048b96b586596bd740d0402e15f5577f7ceb5496b65aafc6d89d7c3b34924b0c3f2d50d16279970d682cada30bfa6b29bc0bac0ee2389f6a0444853eccaa932b2a60561da46a58569d71044a84c639e7f88429826e5622581536eb906d9cdd25a2c0a76f7da6924e10751c755227d2535f4ad258b984e78f9f452a853c52300e212d8e2069e4254d81af07744bcbb81121a38f0e2dbed69a523d3fbf85b75c287ca6f33aadbac2e4f058e05924c140d7895a6ed167caf804b710d2ae3ba62b1b51297b3ea37637af6bd56cf33425d95cc5c96e9c2ee3077322fbec86a0c7f32c15d2a888c6cc122e99478c92470a1311635142d82ad7ae67410beeef4ae31f0902ba2fb964922a4610bb18901f7b923885c1d034da5769a48203ae6f0206a92855e2c01ddb3d6553386b5580d681b8230fa4062948668f834f23e0636eaff70aaa64519aafdf4b040bd2f9836e76b9dc13cfec8065dcdf2834d786e06260d100000004380000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f00000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000171000000000000000000000000000000000000000000000000000000000000017200000000000000000000000000000000000000000000000000000000000001730000000000000000000000000000000000000000000000000000000000000174000000000000000000000000000000000000000000000000000000000000017500000000000000000000000000000000000000000000000000000000000001760000000000000000000000000000000000000000000000000000000000000177370000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f00000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000027200000000000000000000000000000000000000000000000000000000000002730000000000000000000000000000000000000000000000000000000000000274000000000000000000000000000000000000000000000000000000000000027500000000000000000000000000000000000000000000000000000000000002760200000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000341100000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f0000000000000000000000000000000000000000000000000000000000000559000011000000021c000000b02f18afa46b98b711a77e21c2968a4ff69a25c664ef3f785df0cc7f8cba63d51eb45eff48bf8c76435053018127111de453b2fd00414f5703143350a769bdaa5576c1439e3861e7359e1da58054981a9f96ebf2f282fc835d16ca9c6249479e79a76b600a9d827d0f433d1a327510fc420ffe235712caebf2e24ee44113105a7c153f1b5edb0dd23609cbb50491c2154a007ca2df022474bb61bd006282e1fe845c8c800d5d31728de410e03b8d4e7e67000000b00c6ee596e46c31b1f667c29e83ada67849b41de622709f161e4c9577965e7f5e5130d3bb02b250e4e7311bb8e54225676efec2c117c7c2cecfa67ee195695be1e8089980536f38c9d196633c76938ba701ccc7125b84c9cf88285ba42a0064b1b49427277b31be1824b9e6e1aecfc3a613a6973828d958a7ad5c275aa06a1449f8b72def723d7d80d20009986b1f04e71ae19fca71dfb32cef076637f95f1a7fe3e3c8d2a0450d8cd2f172aba5ff2125000000b01c1f37edfe0e7c544e967cd4d0cc6c802358565e66bf2599bb6ad9aedc4b786c7e70427d5f1a5c536b27969f4fd8d81ed5a9486863ab81c0c71a7a505e3bd984ecd579a162e481afec69deac5ac1a58554350b29974ac2c3c069baff5a43b9faf2686000caf06a29593a5e07d78fbf8b08d67df02fa1cbc6b13991efb823a5cd36c03eed3dc8c81b3f84b052df9b08bb12aab8f7dfca0486e323c7081e7c904a56fbbd77c1fe72afd40325c3674ef2250000021c000000b005f953479bd63e87e184b15375cc6476758fa6c183aca9433e4259a340a046222f032be7d0ca38c398e84b39fbb893b9e99d77a0bfc461cc2608b8ad4e54626511d2956b5d6ea94b01af332ced30b99227c5c5fb9ab32d8a00bafd3fe69e3f022b620ad6befc153571cc0d65eaf6c44c08935b3d344ba0d029ce37ff84a6f89106690f840c765b5dfd4ab83797d054b72713090d4dc357aaff123cf660e550f1743a6070c645c8912c5500b64506b32b000000b01011dd9f25d0077c59e794022eb70fdae43a8c743746995fd7554bc6f76441abd637cd671338b2acea446dffe88b0712cf0001f6333da0e7c6e69891893d86ac7b64e60f7916b8d8e77defff9a43295c8f7b30ba3f6eff07c71643822a2088b9e12e3811077fa52d59b079217822f3c3088d303cb38ca173e665846d192ec41d505c80fc4c2187718b44e088fcfabbd709a6cde2315959bd7cc6f7431193f656586537e797202ede791e0785fb2fdaae000000b02a7d3559922d8358dd4e451ea1b2f170493ad131b1cfc0eaa92f33205e6bc6b14e8c5e2952913b1431c46217cec89ebb946a5eb0d4e55a4e2c36db836162a20d5974ed0782625a2c689157d824aa779c5b630c8ddd9eed145ff95fc87408f099ec77a76dea03379822734416e52063531f8942cc037d3d7bcd2c531be676a9e9348d5ef939910b39c779b6c461936b38150c2f31156eaefee74e19008eedac87ee73a90508bcfe08067acbea1567845c0000021c000000b01896f05ae29197911477be7fad45e7bfbcb46b5bf396eec69589a2e6a7b0c870814ea0c2dceee51bc013b3a1bb34b34102bbc5f6359d037edc93e5d813a2921259a451bd286cee6e1aa5263383125314edcd886aaa511b4010def1a629e0b166fce69eaa36327e46b86674506f8f6c8026bab62a1b2ed0de2c7844217a5fa3919980250811e176fba2f462285f6204920366e70a88ef7b540398a48ca82b9057348aabbe0636dbaf9787ba72d19537f4000000b00c7f903fa979646fa9bbbf9623d9c160eeade75673040c2d893ddfa94c1a6b9ea3be4f23c84309fbd77a67c27866403253b8f2a2fc99b9322666926f79c408df0255277f3d4c2ba1739b0facfb21f1c6795f08c9cfdd1c06627f2982954fb8365c47dfcc26cd444879a5b45652a5520d023de432c71d4b89123b50c7377e20293df9370c2597d9d923ce49e6db93660626d773e904ee686cc3dfb839561d156b88acac2831fd3edf975048729a5fd67f000000b02bb3891589315dcc2761b6b489069dfdcdf04701e3f1266f70988531cfee8ff32172b50c869bf167edbd40b3c478e9eae676002aa714f6c7c57b8541f62ea123fc9cc973b714cafdaf99bc1f5fdd144ed61b6513279b5ca009fafe81be32d0f4732324ce4b5e71e1e4becffaf35372bc031d8cc79c25bfba6d600261f890b1cfbef2265a6f8b0ad2eef198aca0f1272c1ee6eed5d9b835752150c53520b9bced77e0ec7340916ff076d63456590f782f0000021c000000b00df5b70c823aa57f7d3405a913b778a8ef593b6d4f67f34a6472d76586d2bae6892e32c68dca0c35b890343eb5058340a73223cbfbc497e9412d6e155dd3afa668c548edcbd4ea0e6a853e41def9e40a60e2f2dfa0f0a2a64e7bf62c90dce17472f6f20edeb4a1087a182ca1bcaf5e6b0ab4057b829e3afaf667ef44f1033d400caf0ae944944ac5bee2fa5d8544a88a09e15f1ed3bf1cc240ff8f7fc27ac0bcd944bd162658b3fa6d5d2bbc1e6d0a5a000000b0267c7b67e9762a3deb02b049465233d16d5224025c7e7eb19ef72b96807900869f9cc2a2c554bb764459e24b04f017ab82a999e359facfd9ba741d51e13f9e91f7ecc883775905c55f5e14bd70c541d245a97c55e6447dc78471ec292eab827a125320fd7f1a9f61e2d795e69466c7ef1d70cc63fccbfb8c5fc40f0848d70c80042c6e5bb3559b84f2b7d8ba49728d850adfe3b1b9560f3d1a97ce4b42eca41525d0d8e084ddfbe68f4059a222aed7a6000000b0126b797b50a23045331c9931d025338f2f2389d5e650638dd0f009e8f78441a862f34b1a461cce741128aeae064d5880bce3fcffe9a999547c1316ff907640302d084ab3c26760e164be684ee9eeb77ca8b4c2ceb4530a3e545c03d8be4caeeb00644fd3ce0d46653e4c158c31d926750195023a33a125b0317090a21106e59c3fb03b4f5cbc0c2a895ae2da2f5a407b2b2adad74953dd8992dfe2667154131d81fd5b7a2ed282025a94f91f348ef9820000021c000000b0007b98538d7c184df59bb96f5a36572d754d2f88c3d281cbce9a6689df308d533185bec36308523944c1188d14414f16332b75d2ceb397bf65cc04df7e1cd1250da85395441c92530c084ffa0347734026aa6235e6a1aae67288261aedc6e2bd4742f9f6d7d1dc1619478737f6d90ddd14fa066eb1a94f9d62e3a55b737edb31265d1122bf475f1cffe313ea8301a4592b3a2c5b72acf492e669dc9d36cfaae850499643788370eb1dbfd22401c36f8a000000b0206063d67d6c900d2e539fa9ce1e0bcbc3232299c2b0b091f8d800ede3ae1a3ffa526c8bd6ced3ed5ab263789de1359e71c94966a3a72cc1e2a8a8412033524b57f0a86bf9fae42cc04975db1040c951f671ee8a246508dbe079e88c7b50de9cebce74b03235ab7381458f84710c26d92bd54cf1c6a50e4234aa8fc02392cf94674dc06ec6fd1fa6790f4fc7ff6fb06e1398116f15533f98f76265c06313445ab984a08f69dd31dd6e76ae7a21621a7d000000b005d61644b31d6b53ee88d09652bb6b1ba55bde34b499ac43ff6458df5ce5b39bf72342d5caf40d5846acdb10cc425733c60602317c450aff3ad84c38e5678568b68c8df63f8ffca5972c54f7a4dfc8f7f439b12018860001145b3a778f9971beaefcb1edcfc05394f4cdd92f566292830db14f172edd2ea3884f88780558ea3cc94fe936b4da474aa53fb4b7f6859b590b93927f6295de38bedae520787dc850ac04918b595724f8c1ad560fe67c32fe0000021c000000b01cff3e84aacc8f3b0db0da2817140b8d6a18c71b6824abe2afc8803ba68b6ebd09d61eec82e88c686c30bc0aa5c39bb6afff0ce525e08f8babe6bd6ffdf479055de5bdb93fe30d32ef8adefa2c7f51844e1c8dc4ba324a90676b8c74bbf7ecbc34d8adda63849debe03273d36eae5eb30c97bf93b0cdeac68636410af6f825fbbf2cb2759d5bc21f8a267c2a463bb7720352d1fde856dcafbf714c5eb8935da48cc210f7095f12425ac7981e824a3606000000b0043351b36f2b70487ae3d9f97f7e793478da11a29044e07f27b25457e434e72da61fab7e2e673e2c4ba1dc275ac0384106ff337348110d2a1732d8cd9b8388180f099c44354b3de5370375f315cf048e707939418998800805afa1bb1be66723ecc9b33b38facb03a7baf5f9e7ac6262038a3b5d97bc5c1544c3014fdecf9015134d13a68a6d7817085c1468f89202310ff2e6f86dcad2593461168f7b75f36a650382a96fef8d666f9b5bf523d8ce81000000b0271b1074b6f78369cbe1cbf05c615ff5e34014eae1aa3ab6fe0382a169df040b70d0a9fa68b7aeba09192fdd72f48b82c10547e6e286fdf5c5a91e425f07373bc6072b68acc2a6a529a16487ca867c7351e7a3fd09e47224aa6241e6d6afedcac0990580f90397be8dae9849f17580892e8870c3e8b3e6e965d64baed3919849af4d028bb76eaacfee7472c1a17b310d108759de00f2e34fe09d11e454a9a880797435939cc369ef1018da35a89a80220000021c000000b01dfe7ce6b28a182787a9ca9178b9c74ad3c6392aea2422ba96feddbabe4f3d2d036652648e6a25372daf63608ae875c3826896691854b2bcb886131b432947670d7c6671c4f6c1aedca70c08606e082fcc01b18af3c9347d2dcf6ac449d02a1829c73f26a917067d5b819347576d9e4924c07c676128ada7902114123970cf0b4221cc553e449a12dc7099950c0b055d21d3031de77c48b06e77c81f6330c3d38662aec1f9277a09f5faf50140833aa3000000b01d25544976bc9b9dbdf500c6b1486dbf7b3acffc33796abe2461fa6a6d544b58b2de58514c94b159d3193e8b3163517be0b18c5e9c231d4a245b678aa3b5402750b77c3be577b1ed7bb396f7fd5817dd67ea004cdb45fa321f0f6e2b3cd7a6e4a34b982571311f168ed5b4d4576a733a10b35e61525cc403e9c4bba6440b1c84e14d8404d6e5c01adee35e340530e12b1f38d0890b7ddcfcaa8b10531a9b9eeb1c7a333fca7d998d76a92072eacdc2a0000000b01b9c0176f60970432c3ca5330880baf4f0c974635d3b2156549da294fbf3fdc6e2ddb434fb51c561c2bc065c8f49f57bb5bc90f45ac71c6c342f08ef58a59726505258b8354a1817779b753fa36627344bfbec174ffd97d71f7b42a5fc83b62b320387798a94ae26c3b185b540226f80215733a1f67478432dde3dc2917ee1964770b7c3c45e35022d1e38afab9833da0958ce53a514bd1a6f67be91c1f1a42a01f0fba82d0f1f2ea6f60623aa8f80930000021c000000b0277785bb796161a7c51617e1bd3dd18c46b4e1de913ed3afcc8a84c7959bba4feedf65972afc77d7a080f9655e708403a366f96b385733342e6b186af6dd3623683caec4c667a8510156279f7c2e552b4619e9b0291ceaba651560e44782133c885db32adee4d838e480fa207e3bd97125a851caf46f7f0adae74c85d93557c1e37b22cf07c75362c076248770eb06f424f5018b6d11a465708439c3b746427069106e2b7e8130e43e92f9b0a21a80dd000000b0024eb61442a41adf0f97b2264b0e432c677064d27d4f8cea1942eddf2f59375ee5d5d6fe3b99fd6b7352f43d49cd9e47a7333e03943f6f68c6fdda486995f360138ca14103c157b997cc5f3f3d0a9584afe367300830a0593fea9d4d45d7d7ac94c4131a75ddd47779152ec52218263d0b245eb982a0b80616dc1ab64d2e3789eb484e24113a8a5ab29b6989f46d0b80121318a8bf0fc6e77b6e226852840be92ba83cf68752e122a7293906d65ee850000000b024310fcdacb531986be837cea8c7a7c7599a628f84b51173737b1784c028dcf51fe5255d04d28f44b40d6005f2b522bbcfd56e8f867d8c23db5266a3312feefa0f2dc56d42eddeb39a10944c7f54a5bd341bb0b02042181c24e97c177d2254f2c229b07aaaf6e9dc1d3ac7bb742bcb1c2e5f64bbfcf989e0d0adde4f597a6755cf85bdda2bd19a1f9f5186f82f50f87028d5580ef3f3ec71a5aef0a9fce89930b6a21ee7bc53c80e38c3cc2161ec118500000fa400000168000000b029a8a5e352efceda35bb64fa23398aaba4adc5d1d80b0cc041532f15a2f601063189e65197f166ba617bbc118f926d9421e82ade5e889fbff356d1ea40a1fff1b496263ec2d35d048bf31f39554e27af766d4fa75bdc711410bd302cc6a4d9d4a0c121343c681b2115c1b4f4e2396a642f5f77e1c644e430e843e4077a1c774d0964ab3cd4cce964dafeca02dff27ee424266367e4f8af816dadbc3eede83f125eda5d2cb1725aaa8eb8ec98650cb642000000b019ea407948f88707b1c893929f02b533f8149963edae604da62ca1108f7b9a22cda0be3d56f81b0f6fcabc955fe00ea72d95b44c784cf184a63df57dc92ced5d769988ea74ddac183ff29b3f71f6e9a5f2a7baff5bf657e3e70707a450535ae0ff152e0badc6917cb245030c0c2876301fbe2dd2c168ebe2f97fe79d1103529f9fe011189bb2bb51a36d938458ac7a020b4a05eb9c23cd14209ae55923d53502c536f30acf4f219f95aa3bea8ee07d9b00000168000000b024c57e99f1f47f9cd1bf3540df0b45d53cec8c74b2c0ab74252edc1705b7dc4a051bc039fb40b67832885f471a14ff7c3c11df4de8915eef6d39ed7bb3efa797ce02e07d850201978f6793787845ac1f1e29181852aee5c4fc5aa6b37a01b61d9e55c7cd24a3c09a86474d3e7bc1485a0de300b1073f92984341bb81507ecb113d5e6270b2d7af618e578629b2bdbb542b30726e8268d2359c33cfcab231fbbcf823849958a0389e1292c0f69ea07bca000000b02c091d6d14ee1fa1196464453cc1ef06fa3f173416b98275abe86d05f8645e32cb8421197fbc0f9f763b1a08f557b7dfc95a4c1fc4d47efba0dc97eb9c7dc917008acb4d6ce152393096a8ef2f725ff8a3cddabcce392dd43c1c51431c6e6a39c649cb55a719c6c5e103f9c163956339179dcfacb3fc5a6fb435844e0ee40fffb879a7b770575f3ab5dc80560970983a0626156bfc9b1d7a68d6612176dc964d2e7e040958ca76bb82f120587819836d00000168000000b0040058e3f256296e38dddb3f547411fedaa62980533a7fccd89f20c0bca57f2ad0eb27a82e01590c159a14e68c35c1311a44c35206705b59bd0f200cebbc7ddfbca7aaf8dc0db3604a176882065502d7e340a01a086f0291038d1875f45fea3b2897031cfe598986430e879856c0d8f0229a9c7bc36273212b5ea418789aa376b95da1cd411a8b7b5f52fe91d366885d2564850f0ecc95dfa5e2f888d8c9c2c8569d10f1f5599f87dfbe7be3b5c36181000000b00b8c6324bf4fbc1f29dcb8c7a4bc5bc5aeb3614f92a4a3628f558149b06cc25707a21e23fbf1f712fdb4c169f1f7315ae65f3e1e81cad0abde00833c31bfb71c569008fab1e99a59ad6b0dfc3d608ec788b5f21ac986b013d7f145f6836d7791ba24229ee854f66d1f59c0a92d6d7ff92ca4bcf1454ee54a04b23c5d925bac830c87463f3cc55ba2494446cc8c80e17609799d95fe732856c74065ac985f86cc66a428ff84cf7f93d99e2e36fb7840aa00000168000000b03015e3d996be8d3ad7bb6e4658ee866d0cd54536e40b74957fe8e5b7d28971fffec818718c8844567c0641f7ba677cf1b8d1791639b47c82918c9f63a80b50e823ec6c63835e76b1771b49123eb43bcfd1409cb9746257d8931c5da05b5c5a43f98bed265f7dc74067c81a9d65f43ed3033c9a857f97416683e31d6e946f072641e28759d1e459948f6035051ee27ad81c24ea04cc8f7506dbcbf68e87221e011d7a5b117e32fd5240fdd00a5b602853000000b011d629e39e3c4545ef6af1325a76a8c13fb5419eee406eb0e495fae3e90ceb0b282fa956da209dbe7bd216815f1799877c7b72dc31f52b457b9568ae46058c40100db7bbaed53c6a85f18f908f98dbf85db31fe0cc7924ca044d115ebaf190d7b96e10c490e3519cfaaabf212eb36f60304df9f26f5ae1684d3596c6d742d9c9791bdae9d9c64419db885895ef18fe9702ea9149a0e20d76b8aaf89c921acbcc0a86af6cdcfab8570603db910a3969be00000168000000b0176d6a526f026d71d59bcd767f51ef500b090442f53bd98de56d419ca882cb4d0f8614a3b1756f748977a8941db7c0433e0ab2b7fce9ec715f633a51532ea37c71c4872644ea53e7f465ed0000d2609b61ed5c7ee18bb12f645aca89481eff5104fd5757c34756885b06d3a97dd55f2114c5456a648f51bae034589fc9c9328898f04695ee7fd6772bdce980c9ebcf8c28dd35dbf7463bb637215545cb0989cda41872bfddf5a138bc0032ce987318bb000000b006f90513e32e6daa50a34f9873c7786f052b738ae7fde3a68cd730c0088b8545339db01f894d5419acfe945cc0c571045e39f0ce1d68bc0a8500a6b0a7519641353628c77caed8cb418b5503d94b19a8bde7e970965405a5ae3e12cabfa722e8b8b45848ecd7b4a0d972881d31a3616d207327b54673da2ba934e792ac8c933a446ba690e1458ccd5b93f475446580871b174776e24d5181cbadb96d6459381c2a87f6e2c86959af98804b92742181b200000168000000b007c42ef0e91cedad3984b5beec63a66237afd8d31716ecb98dadd3b0e68d5dda53286d42a811c30a7a83dd2e1739f44bc32ef576ba3fb4d8d41362974abd0ad191aaee0a11a856b035f28987c1351f961968ab86638cbdf3e57ca2652faafe9f1aa44711b902bb8f14a8c03aebea348e1f00f0592531e6dd2547887c96f41eb06830fa187eda838721b679e7dadae73d167f706d68e571ffc4c5a136954e1b9ee353ff9eb6df2c84a9b84b31c184a9f2000000b017bafc1fc6f31cef6ed6dd7a5e2495cff182d7530cc6f7d47fc1664fa519c660b9cee734dcd29cf8284f47e97eb4ed7b9f86a012fc29f74c5ca4c47ed4dc9a64c02b6e900bbc69b3fa101270e2d0ef08fcb190853a42e187d0c96a4136edeb23ffd0b1fc17b3c4399076bbf2f9085ff42e2bd439e374fa6c90ae2d13ad659c91c7b392f55293d518b302c35836e92250015f9c5dd7020feae8a9813ceaebaaa1dcf46000b72a0eb7b1b7b0ee9caf4b0700000168000000b017980b81f71abd837810414a656c8e5bd6e42e8d15582cd71be20324c3471e4223ef65557648a2c310aed207d19aa66aa065a0ab4a53b520a1713a492b4b6a15bde338531dd6a508e75119eccba9df2fc6466631a2224d054d636faf56a636f23590d8d22b32b143224b9b6d09d719ce21f2007c54a074b1549b14b2b6616b7923f2b996eb374a6b7d33dceabec0016f12d7665cfe1d54be8988b9ab8cb6cf9addba8bb7ce8059a6bd8c8d4504496a17000000b023f08210813da5c79f903fa205235155e34c59577962f15f92e4926969a6a8e0e538e19d97f5e620bf86d5705f8cfe0c62f22116ac58d57436470d2c26f7081867e31823128d6828a7eab06947c6882d188447a583b9b8fd3db50205673e774dd3d83061d0dfb85aa839a711cd1538071ada9bdd30b1a6f48ad6707f2cf48f05e6984c6c0647db25edc769eeeb06b517160f321eafce9b83d3f5e1614eec03710ffb47ae33a68a51d0223271560ea87600000168000000b00d9392756f21d6ef53110c18aa9e9ebed92e01be9818d5370024242a2f8780eb8c70628b1eda5bf5fe991a11ae810a6a5a35fe8766ac38dbe42ce339e25227b8db7053770f9da03054b511042ca62cc3d9a767573215d9956207a0ee9b6747e3935a894f3118125c85a712fee4dc9daf0b6f6fbb593e2917d6f695d10c72a2465b0bcee37e22576fd2db6eba526d4dc222e74bbee9c6472a3606daeb4d98eb2d26238e151945e3f74387cae7ba712cd9000000b01c575eef72134886f4bdec5d0e997d754074844363385cac0ebfe55e1bb4ca6ce4ccf10854af9a0d4161040b21539c7c4f6d308c146a4c33d3d980481a174aa62d5ec895e6c3cd1d057593b6f71fde55e15bfa2e5b0d25f2246f59d2479298bb1068075cac8daef2fdc3ada6e6ec530327106aec6e4393ba6df304f4d692aaee0059daf7ea0b0bd4419cdf2e1e0d156c2daa6ad02f5c187a33cbd7069c465f99c3f380b9536acae56ed6e73450d9959700000168000000b001843f8e391a7bd395be524b25dd7cf7d90323d50f8da74759102ed26f170c6100463b2dc7f96d1a767c721aa2aa58837dd46eebbd6c1d732a99090d55e972a3c7273efb41957a608d3fe50c0f61afee191d029f94e0bdc8ba2c7cc44c8a30baad653717cab6a5f1d2fdec30dfeed71406a5dba4660e614ddb704340515bfa3b65976b97f37dbef441fe1fc9c1bb849b0904e899b07c061a7d3d7032e9c242e6515c65084863c2eae5b9464d487afce9000000b000dbcbfe9b9a4e0822e70744639462b2375ef52af7ede2996f3bd708d62a14015ce0082379def0ac88e39fadc121c3518d741b216c2d7f6b84162093ed1461d41057e04a9bbad351158cd763bcdfc2e14c0116f81a8f1c17bb95d71ef3200df0b236f05a7c371b7731f1390ca53c6542287872544ec7e98bd9631e41d5cbd099517a64b525b02b3b1f89046a0da79ec3136fe594b8687a7fd9f5da9ff4e0ee8a5b6e3e96167b514463d3094b55ee2b0e00000168000000b02091959594a6fe435e017d14627875c05d60237a5698de9bde70bdad418c72d83a3ad0d0a09ad22240b228b117302d7ee4453f3cddd92f8184b5da701332743e9089ab6afbb4988293265916f662cec62e5104b0a4a5e24ed65778a1d241f97c4ce2ad9d24da91cb0bf7a5f7f6a8cd491c8d207bdffaa150ab68fcef994911546358ff0aa56c1626eda10bcfb358a118170ab67c2cd70f0ee6c6f754a4759780fecd5562da70e12bf87144eab45f8d7d000000b00c918205b12609cbc72f8d4ce95e3a5083c56cde97aeca16153848052eeadd124fc043e36abdd47691a9d6ad0f7a7bdf1e5e0609a672cddbeab41eaa60a909034e54a5f32eb0620b55923bec293edc5873f79d8d4db02ba65f5c61a21fbffde44b8c218826b8624ad0cccb8d80f951852e29e0bb71833e8ad3701286dd45a1328d71ed8060d11e804b24e389c6fc8b4d1c632c5691674b72bb452187e9792087a9140ec57779cfaf6c3421481f692b8900000168000000b02eada1a909467eeb9eca913dff605dc0cff056eacf37ba89fcb1c7c5eb768d77cff040668c797ac1cf019d01f314dff4f259c3d73f19d82752ab5b0488b0bd33003996e185c199f9d7e83ae21133310b64678326f23fc6a385725a01704e22eab96737a47f0e2e055a05ed01c0921bb8031ce5b1d0132cce25bce1f8e98edb296902352ae5992866f16cbee08d40aeb31c6223156e40861f865393002116692a301b4617b7aaebe24269906473a2cd14000000b01b57e2e264fe3b82399ab36c30fe7a53bed097ac0f92dc84fc88c2e63c614c3b7791a49953835e7d5082c6165ed250bfebbf6b1cffccadae77a8a712e0c8b4f093c5aea43f38b85b57a08bf783b5acd5613691f9d6e002e5f7dfb2c909b4ed9395f1c56de47549149caaf3cb7c6622ea223b60829d20fef24cfa2ce642280c2568dc615b69ce110172c9fff356756b152ab2090ea5ecbb8e833339b6d37ffa3c85b1daeaa90e303addbddd3243cfaa09380000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b7370000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b60200000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000381100000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f0000000000000000000000000000000000000000000000000000000000000599000011000000021c000000b012a3f87c10a7085c68d23808b7aa0151d0f16ddcb0f5f45177d41f9371e0d0fafdd67a5f00654611c564f8a125464dfa3e9bd1e241df1ab3905e8861786377065822bba1140e2e16a2312555c109faa480feb832494a75fbdbe8d621819cd888893b3b20f9f84e7292da05bb98b3d71c0059a97ddbc203a4c634c2336e2d5e62299934b787998463cbe580616c70e79e24f809f09b9945caca2125a7d2eb85a053f4ce81e90f30a7a0b8c4deeafe71b5000000b00da468a1cdf29d9142e48b11723a65686b6428432fc8e076d8b62eeca823f5b3d6222843c81eb5b414567fa96761cafe4f4ff7d5af58fe1d784fc2b50c5e24ef6d378d66b0360f526ef1243982198fa5669f7b83f731282a4e74befb8a70c6eb6228bcb9e1e2e0fbfbd7a556292697b31298aeedd0d734a9e93fdce453ef9a047df1e11dbcf37425da3fc37b8238eecb20eaaaa83498d628552d4c3a3ed1b05a3c3207b74ea84a4944145b3bff4afe90000000b029c93b534d1d50e3c13eaa70996ecc84ce67bac3b4bf16943686970ed0b0b147e859ea3ac36eda74a8c81814546bb2a2f98affd0e43a637d5dd96cbda118739363faef1f3a9f1622ee45196fb95fa5317f9bdcb0a0eef07130a5d0dcd6c575b96f6b5d9f2032f44bdfa395380cdb75cd1595fe8a35d117cb7119cded4737b9072ed89e2ff237d535775750ceb6e8a7dd1b6c59a904096dacb27c219f551aacf31d67c2276f79cd909cb3eb12bb2ffa3b0000021c000000b00d4acc67de53fdc88b4afa37fa3166acb3b0ba1dde8ddc423a7f3642e8a1ea202f87aa56a589f42c461928643b773f8bc4a02ce0366f679c014606d9372e35d4b923b77ef2c7909c2c352ac7f64988264b444b5155814e80721168d01947225f93b090fa72cadf66d46dae8608d400d820257b28fbec8d52fe5831ebc2be47861692475c6e78bb621dfb64a520ec10ab0b2d1f9278f82c607cbb447f9bf6502883c7a76fd7b3ce04e0203b37ff91b98b000000b00d527573d2eab0e2b3ae35d2c49f3bc1b1b60ddb042cfe2583fac62ed7146497099685b8c05e51e131e171113240de9ac8d0b02f82dd4854bef9a288acc7bc184abfcb875e8a09e7103c9d09f69cd5baa0ce999ce1b46011a9396669e7f63c5afa2d34f7e693441bf080c5d20b300b912e05a675f05236326b8ef26408159f7606c70ee3eb0ae94d714e61521dc38204290caa1672acb70851aa2deb8ac496f552230a672ca3e059a9a070c616d7b0cd000000b003d21b9fbfd59a88e7330b52b0019167fb87490b46da878b1d2b786024b1294cb7f12e1748b878b5b07c584358864aaae235ba68ae2f914203a1d2ad37a309b5b329853a59b831eac42881064ecfae61da2677b0a48dc626fc4efb1df94b434cf1e8a9dcac23ee5debbfb17741d561190b823316ff9736a4e3f6514216c445e3143f5aef76e39ce8997a03a2065dfe0706f061c9b32fa932c71760b362825f60e36d2404b5a2aed8d90b38762ccce7980000021c000000b02db2851bfa29c277f368c283652d551e1a5f0d8b9eabc4715b9f50a58f738930989eaba66a8c300c29080d4cd24874c2c67421ab868e9fcce682df982eec8775ae545ae9e8f249031836a59e749c34ddf0d75ca1302995d9569097444d3daa9bbb72934581e9ee5005fc8d09cac021cb2c18702bcf5a34f5134558b37a2866c30690ca3aa3d3b7dbd7da472a35ced6b0067df3516dce4c99423bea87dba218b282ec177ae7229f01141c6faf862e2be0000000b0305d96bbef86cc073eb1a6da98c34f04dd5dada5e60761ae129c2c7cb8034b2fe252bbf2efc0c8661082318758df8986c328d9e35b4a7e793d85c15e839dc8e2ebfbe80499da857a0773aceeae76649a6e58b4f22b98562dcfcef7630a7be298f8878502c3be3d4b7df7263428eae9651497a3acd84e272f258408f58053a7209ea6552863bf08fd83cbffa00cdf383d20e973ff01352c307ebf269bef04ef4133338f8f40639a0cc0391eac6e40445a000000b00e28743d825775e2f982d16eb4174afbff0fa3963bd8449d408d0ef1682f6ea1413438aaebbee85cf7f2af25b8910929ffa415177c2eaa8ccb39eff015a20a1f066e374680ab935ee964b20382852bdf5ee8706188ce8af288464acb0844c021ffcffe9134bbf8edafa2a7c67472a7f52e09058476902388024ee4c949f5f2eba1045cc7d3c074244dca0c80c6a58de71188692df77b0cd39e417d1f2df721fbde067594a92becae923f8e698c64088f0000021c000000b010c2dc102305c2451c4e0c6b16ae6451e931c816003fddfc830e18218ca773c76516e278156f38a60bd2c6804a0816c5e15a70fccafe84cab867051ac6cece1ed2248f77d5b8f2054d5f210d3f621dced0af32be5c8ee32cf931894e4f045987f49ecaee86d1b79da6cce794956f70d40cbc9dc8879a75a3b0978590bd95e37f0b9684c09a543425f841c0608174ec960e055bb395f224000d2096dc544e8932ff5d5e6dd944073e3041692e53714998000000b01d59535bdf054a28238537f889e77a9471ca056015d8e9f0f2d7792e125c214cbcdd91f497d2417a14858d60b5f33528421df56cee41bd9f1970fd80aaa01772d83582cf9af6acf96759c93eef39448589806dce0e5f3bae287a57340825489ba21294ffefb3ce151b9df290d3c14601041f5fa0f3847a19b2842df5e33d1f410cab967035f33490441f0d8b81b30aa11425a6cf0dcff952f41954156541e190ff4ef3fbb07fb2df64f3d841565b8156000000b00ad06d592e336a11ea592c474796ed7876040b566276900b5d087cb515f46ad3aa9cc44376c94c5d0cc2e989f9cb66971e46489df061df16c875b0abf936440095026865dd355537251f842280f3cc50c0a1a990f112e5b90da92a1cdebecd188e22dd0b5c05d6b43c5120688d5914950cea57861aae3a55069efc932c3217aa8c159d5837a3b12bcc28457ae15abb242f364c79c54d9efefb1140dec742dbf851531b5f6c93d656642a1368b9b0d2950000021c000000b020366fc61784ae37844f953a7cb95299dd2a5b1aeee3e34c4a14fa7bed250b98bf7ba10913b22e9c12667884d38ed93bbf3fa8f2804f528112852cf05e84455a5606f47cc5ebc006f592ae0a3791bb14a0a140c7b158f77ac00eb8d7104ad3c4dbbf1256de4b9a422902b2a8517c65ac0984b7c91c9810ecf28d10d75006267e879a61795107748d05c01a85d8417cd40a9d6bf6c449550826b41da00a7ca2cb5a3ff5678ebac13fd217e55412fbd9cc000000b00fab2486ce2a7fa8e9718e6c728a026f1a11137549db145a963d3ed6693daabc207da96dac2232a1cba68a410c869d7895be6042629890bec398b8f864725ed92779a751f121ada409626fdd1194aedc70b9d4599e9668815f0b7fcdea040069ea88e13f64ca258c025c0fe7aead52f62159e81e1479929b331bac1298b86e4f6936fafac7348e7875fe7fc90c6f73402266192233a635bf1d50524f33a996fce3815e87c76981b8bd121f4c76c7e999000000b0068c6b24aa6e74d9802766735d5612e549b547c98f9e6223d49caf11f9782ad0332934acea7674ff93238e797e14f3b4f2cbf42873687b89e63234c5981341e861ee0e6109a02f0ed2056e3f14c5a7c3fb10baed29d55c0f2e6934548322af4676c8e7fb8fc2ad547007ebd00ceb64a424d7c2c0264b272c88b27a6a773ad83ffe5a29110fce7b7488b3a5abb96eeefb302600ae16f70c626a3e1bf4011cdbfa1e1d8b43c48ced52fe4d7e6acdff063b0000021c000000b01eccae51d8df3df22847b6be5c0e93d36064b7518f1141c7d063aa904d2ec94749f817a58b60d01963f517acd1fa58fe2642f2333773c6643ea6de4980a8365c1537d47abcc62d71181d0ce9c373581faa6df7bd080921f1ed04b1776a1d35120dc0421e90409e95faa818ad4ae7fa2310e60bc92304c8ed9a04e4e470cb2ae54a488eef374d302534ff97daa8abd7bd2da3f55930f31388ce59dd429b85feda2cce2861f8ecbe4729cddd0f3179e9fb000000b016ea5b7b0281cc1d443e4e87551ebe5b90f61b73d79bc1e65508b3ad0fdc7f2e544559e9016744225a804bdb3bdc3f1f0ec7c7e7aff017d30fdc3d8e52307752f80edca83ce5d20ee2ddb3622dbac1dcd4920c07999724bd009e92dbb62aa100eb228d6f2cc873848919c7d58def55ca1d58797417534bcd3b5601c2f349a73d1db9f8641698ed126e3703bd5898267a0999d8892957fd565942eb409bf2367b5dd7f102940bbfa4818d25d8e03cf011000000b02769f2363aa7150e757a77b2cc09b8b3ddfdeb80d915e154df2db5bac3c8227363c8919f9c6d102eae3634bc5e1b7361df11ab6df5976b18d9bb5f3b0c96fc2b6d74e675906e76b8dc112cd2afa1f8f3181df9d5c8c9fe6ab3c38e370a76ac08b52925de0fcf5caab567987e5a7ceabd13438e09e6cc091795bf2066b33d4d13e6214bc1431fc72ff5f1fbecf7fbfa6e084f30e3807363448a95458c95c539884bd4e01a43e065b496e0ad798bf988bd0000021c000000b01a00e0fb2a70132791f3f83d7964ac64b14962b42f903b81ffec8bae3a8369df51c28ee179eb937b7e70494b9d000aafdcf25d5fe717f23a7bb262c07e323a409d898d297f187c46962a718b4ce424c2c499a4ef1067be0b71fb3f66a72c6915a75169b75f3fcab2f453021612b5e0d926c089c3ce491623416d469e3e046e019c1c37cef764b3baf276b81d0977638e0c0dbfcf2a029ae75491464759deb7250db22ce58a88c58e8d1f05e8686d591d000000b00a530fce049b064e007695c74c64c8f889ad9c2b8fc4ce028a5b346263e081097b4826e388363d20626a4fe59a6c537e5c66baf984fe37124931b43933c513f20df575388251bbc0a26bfc24879a61aba612851ee3fe699d44440646ccfc37e8856529b85ed4d33c53f56ac903bd99ac2813c01f07d9661f242bb9edf10ad966a5b24d644c8c38bb52f5b8eeee3ecf4002fe1ba26aa2766b358d673eae8a3325f0f5e3f1cfa53945f0447c812f76fa55000000b02bbb7719ff4fcc5a45f2801005153a0c0e921f7a6992ade1a27883b45a763ae75c22edcff1cbb3d0c3a7cf7b0631224e80f250e50627a69b05e0526f822e39499f749591de51681de265fac24c1174f5cade4aa061d6ce0d7b2c6930ac0b25b35c658d65eb6e1d9663cbea6a8cc203fd1d5462c956f72c06bd8a7ace7b6296cab59e8cd6caad3f18c22a90e73af18ac40f05871aa59cc20b9536218704c87de9247ca282ad77ba3cdfe75733576687aa0000021c000000b01450c5e09a47449c430446c00501abd44bc39eb24e7a82c21c30e7451f1161834173a930991b8ec038d6629b00e226e2303f38ca43c2177899409ffa3554ee2faaa71e56abfd2dcad7f49e8b1f25f69582a227e30ea8657032bfc95b8f2574e536d47064ff53e5ede573618b50bb7fac1a14cbf6e8856faf29961e1c9b0abbda7302d94516447398b5fd13c6cbeeb5a81e99e2bca57891761826d51585e3a5525c62a4a4ba789c4e16340a521cff415a000000b03060c76e031e41ffcaa4ca44496eea5be4de4358eb32fa6523fb8ed9a71417c1d43eeb5d988398cb3a298a5c33a182a54dd51b741d1256a76fa7ba9f0da67eb1e6f1e2bd76d4dfad2e92b1e3f5b1e1bd1604251eaa4ea640107411b22614c555654fcb94514471736a9e205c9685de8007e94b57308098218084fea2951d1ac6082fa84233d03ea4a2eb49186eeab7fd2f6452e17bfdd661b25c23df62555eb467806ba64d51cb145fb3dd20ce1f786d000000b01baffaf3041a0e3f5e7c51c972eb0c910d64347aea8f70710ce3ee2627ed94b0fb9a7a06d8f8def76312b18327f69c6cd323246dce323cfdd0ce9c516d8730cea6894fead38ded01abb9457cf78244ff9df7d8da5dc8d1ab21a950e523bbdab94caafa228bb8727f905349bb16ba36a621f74c64379e38e67c1d21b28f4bb62551abc84ee253a9aed45b55f1897f950609d171b9d2fe61d9ab85f9c7a0dae75fb72f8e6587af4d669264ce2edec03ab500000fa400000168000000b00989b064739aaf94d5d372ae71683312cbde5fa0dc4b34fae0475c0209872bce196420edeb3b24fac24054be2109e376157c636cdea02d64de2d4147ce020a27571562eaa57ecb84c665a7a58ff672e8c5bc1dd613669dff6edeabf40cf39b3e64672e4777fc275da2f9df55415099f71d2b8564a1ee5d084c6dac27f63b542bd6f7a5a898d8ec7d3c5a9dc1443336102f7e099fa97a38a9a9ab2e723cdfe8394e7d2f9c50af7b7257a067f314d7a417000000b018454526df46509b536a8fb23666b14130a897e5363e700218bd2286517e71c6298347d2678be8e2b61fd4662fb23a9721601e28216624e9bbdb6d247a187cb994575ef43fdc1128bd3bf1c86f3f7d4165521c40ee6b3f027c1bc3393ef18c6eb2040d34b4f8065734e1b549351fea101577541dc1e2c7581783cbb5ee0848a416da2fb7e9e5298cb64448affd5950ff2bd9ae4efb64336e66e61c2e1028b1573a16d4c07daea8b063928e8891446c6d00000168000000b001011005ced7cad91b09477a598e4d04b3fda6e3737779758c76bd61859d809313f74e58c8988b5d05c8b885a96c4087cae3590f930bc2c2a85abdd8ae508ef55f715e152c0c5a87d4ae195e443ae75f1e8ad56b7ad2b5670b143fd47d8886ff058b20429b3c983355ed1da3b6f103090b1dd15218e59bd6c3fd08d2a25c70b7524fcb258afcdec28b8f98f078d2e6de15ce8dad72904861bcda1a34557aa39095588899a40ae19583b06301656206ef000000b00d5c20276f84de35fdc8a6e8fc208be8fa5a9e53992e72a907d761c83c9e9e35071a7e6d51c7d524f093f4c44879d595ae4b4464867697de912abdcfb00388bb2cb18b3110e64ba8518c412589377425850868b93d8e722d6fe71c159596215b5b99aea874e765406895f3dcaddcb18a262e12cc2dff979bbe8588af41a0981cb3bf748c0c7d64803a2e722087ba16f81e72b2a2838ac79043b5f7645386870f3c4556da99b32c4aaf00b471922bf8cd00000168000000b0184a8a705b4925416181754dd51861893072d7eac9cf8977a20b1881aeb26fa7e448ab0bd9ce69ee031d5ff30d24e9f16a245cfc89018b25d92a9da8d4f8a11c63ede162aec623c45a6f0a7e0b080538f20fe4da1d17e77a5dd3567dc4f1e3445667a33c5269b41165d0b0483d0488a71652d54c54e55ce046f0f6a6fc8d56145ede63219c451d2b6bd81f38e966e4ec181306870310146a103fa789fb08b7240ff83ba85afb94df5bda3f36af4a95e8000000b0035c31e222424d27caacdf6cda15a73055a33872025ea9bafa6795c92fca289bafd8c8b99c776fddbf2542649a1e582df571bf5964e5718355bda2ba38754bc2713c4f6782e6e8633152c1a789169df9bfe0cc4340b3efd4611c951802614400a24567922c36008bfb0b590a751c5a29051b7222ee8257b17c969f36e1fa6b0f93c237d6d80a01c2a7752de1c66bc315134384a4e62ef32124f3123651bc4e8cf89384ddfe25f434755dcf7f6128367c00000168000000b0095a121cc0de8d43fef6082372c5592fd63b7169ceddcf97eb4ecf9e4b7088ddedfff238ce82f8fb87c4a00bb661330c4e1f2cd1c795fbc4de044999d40624954b7e610a3aa4771171b5e2fe1936fec22d942d31f947424950f3301f964779e3002f18f2b970db0525915381c56fb041030896e342d4d48ffff2b9d159e9c6f12dae6a42f40a557f1c0fecd4396a618528b853bf3a4c2deaa4831574774150136960648aeb3473cb31eec4fad88b729a000000b0109af4ed14239937055a96291e07a12ea8a5790a515f68783006409a278be08c55a6971baa3f4e966ce8534488bb2dacfa42171cee8693e3041141d878022edb6db26af90444034405eb72ea66bb5c73a17c5dedf81118d149ad1e909046dddb64cd0465aee8924f7de281b41c29f6f60bfef8e8eef28abe5bb124b400965c582f2d031f7174173e036078f9d0f9761c1d39dcc054cb2725c875b3b9ab9a46e39598c9fd5440dae3721420dacaed26c000000168000000b0118d64419ab2278e315d5280a4a9652f1b4de6ba43666830173118b4a7f54f2f7a0b57f325438f7aed6a66325e59f29c552b1da95ab8226a187206dad190e6a5f95628468970bbd2bcd0989db95c19707614a514b15f8f093440331bca16554ee39966283d52c92859404ebec309ea321fe016ac5b8cd21d4ece1fa8b59420c7bbf719c0b72b41d103c26e7254a8879b0305665afa220ffaab43bf38bf46a0d7dab3f0fbb111d9bc49af21c963631950000000b02254cc0e551e0134c3f95525ad81ba64e9736975ac6ae5ae6ff8c048d6b268c846601fcf2c1b07cda51a82979df5de987668b13b96e83c8d3e8fdd0febff58480f43034a410c3c65063fdccf546e9fa8e586f0849ca0d3bda8a244655b65337467f76d904ab4be0fee01f469c4765e29114b8c02beb037dead44ffa618a8f7750fa5d0cd29e7627ef53200e6fd1a8d30264843d48db9b3714afd5d2350ead23cd7bfeb515934dd8c6678c7f7af4bc86100000168000000b014fe6fcf29d3e25f0c5923b865f798e197b9c86e231b4990c8ef29d381efe488eaf7f293d58e1a4f4224f74352d70f2393d3a4e0d19ed5098d5c901a144ac3841fb2f50f78fabcfaae934ec48bd13b553034a03499bc2c89a5077ec4ab94cb50a72888f39a7faed249e67e03553d9fbb105fd04d032e88b59411ecc137cdd3978fce43314dbfe863d584b42433489123158774fd2100834670bc15d3dd662a11f74d1a594e2062f3fc75a24ba93ac2e2000000b02009451141c2b97cd7a4684196bc7dd1b855c6e353cc37e5beaa00fd7f382ca19378f6d852df1b2e23eb5fa7a704f8ccfa098f9675177ac7d65bfa9b57220c178495c26ee9c498fa6368b277e28d672fc64244c4e5b88792c0d5d3e8b0e06b24477db358c924ce65ba481efc5c582d3813067c009ba4946e078e05d95d717d041fafc0648a49d31ce80c382f30d99e9c070d8da68fed27289d2fdccebd7465dd9ab70bd4c4a1d3077c83d268c30cb47b00000168000000b020cb7a629cb55e93ed0057c25f71bea43cb22fa6a0b9764c2457c975b9924684c2afe317d069cc59e223cb05d190ac5b15bcd93fd7899070d4682442e50e27e259eccbb27da265efa2e1f494f1f4344c9b73594b5761247a4f3d835bce175ff460db37257448c7fe8e0f12a339ea898729152941f8a0cb9e83dc0199a6022dafbf57bbcdd472e5fe45faaadd1b557e9f0b682dd080518ac6ce7f82941fffcaabf9bee4c12c10668bc96db689901b680a000000b0220fb3d8b9ed67296b01972d6d12aa167c6cf635813beb8a68e225bda53eb249acfff52f77dfd375a1ecf988e83d2311d2c64d6806a9c629db4ee062af5657cfd32ae6c25c956cddc360f1de570f11bdb6fa833094acfbdad38935bb0dcad4ecbf9bfc338be0db31c6bff7778b8921602e53a726da76c19d778af0eb9ad83a4bb10cf7ec6d3f43145c88fd611f9a63f824316c0ac5e320356e0ca3ff06c03bcf4167f5e38ce5257886ee8f65b23a726d00000168000000b01a1ab305715f2e086510c5e9cd41213a5140da819b0e038ef82e1eb1f70ae77551a45d91a1dd1af5fab598c0cfe65660ec5bbb88aa31e8042a5a39d410ff938e6232dad82b4d08ee1ec75634b1283861022b0b421d906fec5e0f6c310715ba2331ae0213886f90152966c3a7c99899ad2e23bd5adff4d7e46cae3169f672f61f1b94ad95fe1847512957787b2d9d4b6123e30b0856a9df7cc0e73bd225f965ca76bb354cb19394f3b44144910ed20928000000b012d38ae1091a52eee982d094d7ae9db36cd99b918adbfbcaf212b7d103b20d43686d129eae91ea64bc6ac3a600ec6711bde9ffd93806bc37d7d905251e9f464ccaf2c795227ef0693e721fd8f64a5e98edaa07f02310b6d974abf554e02c1a99307d85f9a74fc6ed9b3b41e8908231b8001993dccf3988798315990ef1530461964f3a0e5162edb7572d0168d538673f0121b0faeec7e927b3acdf22e84107f90066a4393dec07fab506377145be7ba900000168000000b028701208ac1b2a58e07bd56b5b30af2be82e4264e44e60871e52969fbd1b889c4de3f27c5672e65708a248d960493ee8e9c71dd0376784b2f8787930feb12d9409b276cf06384717d4084157f7caae3ddbb8b69c0d609faea7e2163a8906670334fc7a92d67cf038d32561d8f627551020f5e05a1758fcffcadbb47ea5a76933a89e28db89b5928c988b868c1f6b2de22bc4cbbc05743c2ed32e3a53b2fcefb8d54a75d7303fbb8bc5653c2da0ea1cb9000000b0245d99fcd38ba6c8f9060ab1e90dde684934d030cbd9d055cac0b6359b246b1c72413d2017615d23661da391e2097341cdae610c99a2aa512d28ede12be74baec84d5d85db815af0166ac6ead604473afa65bc9bd910160aae6458508e7190b0514f5db5726044ad80538bfde9e158610e32480d2db0324fa487f21349d6d3999df10f27d9ec23a45f25125bcd28b9510932d699e160f223f426ae8cc0a419fc936814c8387ac39b0ffce7d771e0abd700000168000000b01262c923d54e8d22ef2d948e9002e4fde85537fc2942475a63b03600050ba0243193519cedef7523b330cb7343233041d2616a7784ba812ef5332f864ec7192e1e6930ce9a37a4476f61f17dbbf6aad7cf431d9d5135cd99c12ac65ad02905bf012eff5c78dc34f864641b7a3c17ce691001c5e6bc8aba25fb98459de98b6b22a7345a95997cd102c4bbfe4f0c5b2aca2c02e113938c2313acdf5e068006633f012406319d7b05b2ed357ccb8edea790000000b0100535b0e6828087550d03a38b9bcc43931b5d6568a3c3d153376d3d813647c71b0c446394acc02ecf80603e54f18758997f78f000dd0ff06110d237d8bf2e95cbf204f55213fa8cfe232a75b3f36267295166b0bbffc54bf19044678ebd07aad05cb1c407ad308cffc49ba407702b67028628632192b31a2ddca9043f6c6a5f790384405ec06b2c024bd1348cb2fb67253241c5f2c14d4760ce1f97ec64969fb36069ca8463a3d55a151a669f7d719500000168000000b017f75a7483e2720636ddafd22be9015900e18417ae8671907eef28a87fd347a126c977cd13f53c112a9dc87f377a0d26aa0265fb8f219507787fbf1d26aff7e5636e22fa282513727382df172700301befc742654bed65cae59fb57e884fcb6fe0295e0479a77789b6378fff86cb7498277caebc69835f55ea6afdef9dcc9bbd1de2541edc49a48bd1e1ffe1d4fa977505207caa9189410a79d9159d8d1db726ccdfec01e3874b17ce742768285fcb43000000b0098f30ffd2f5058e272539a955ba702865f77113c5a7ab3c81b245ac404cfcf8526d90c2a8ae850b8489a8f57a88e3d5e980e20d13f0982d0d2427ffd3d422f7c5213803163a94fa14b1bfacfee4d4d950ddae0e162db490058175a68f70751f6ac7b4efd4bb5a17012db0f0552d6f880527097f58b629b3bdabbb7419d695ae54a15ad5ee1ab0e6db74e49c3cb46b191dd03740971118f118fc27fa89b1e3d36b8ba81af3703f4d2b1724927c76e79c3800000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f73700000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f60200000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c11000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d9000011000000021c000000b013ab5c2778c7ca7a7b3dbfb7bc1d569d323bea79da7b979ed4a927f2c689585258ce736a9a0ca5001625d02a6be4f35e870b2f491bf552b371c707d4e3dd421666c5b95aef56d631b9a49552d10783dc7fb5f1e200e68acbb255f9ef91735aee20cddaab908331023fa4f8df19f67df3119874f0539d9f9fb2b98c4db3a41a39c8deb35144e9a5a5b3f70cdca098234727ad55af3dcb069dde4690cea492030b285c062af52a63db28c65f437733c329000000b014ea42e70e10b3e80d11dbed267c24e153c76955317cd3c6753d6ba43e8136d519260060bbd4e721c7435fdf3924d598783425dd41d3d5773981df21fa6c5a1aa67777de1b42636c0a003eac4ffd0b7f89dfbbc9b0f3c8140f70ac39e65595303caada3d712e1bce17916cd4edc127ec2188ae3d52183ced6006677c68b84692aa845f81b9976ff961a18238835e6b661ec46329644b654876f4dbc4c4a24f22b82d85c47574210795a5a5a61c3db9f7000000b02f87cdd11c9ededcc00ff4c04352f60ed50998708452044bc440202746ff8391f2814b8cd2eb4dc02d0dd672e87aa2de6f15f14303e995678f55426f67e96c426cbf40cd4656ccc029c0525a0a6e48e38ae8c31c40477b123515957e3d583bbef7e86a38a4ab9abf34b0ee46a32f5580001ab81301303ca99d4b72a0ce50906314a455c36389ebe12be53ca2d8a8e3b10e8ad95bf22f8fa258f6b777f9a0274e0f0c5dff3696e7b2bd5b119f61a09af60000021c000000b03006f3ef3e028220752ae581c9cf555f07906d7578410a8385efdff756722c4b84e7034bbb1feb64eab16e089521bcf0efd5259901851410b6a34618a41b0adb446f424758d91dcd1d68196139d946b2c49b31659e7c589deb914d7960a7a2788643cc179cea6a66e4bff777cda3812b201c795ecbd78c4eaf280059e4881ea0577dc63d41412811356c7613816e9d481e59052e63f4249200f503373930ad5f5ebd16e9c9908e0556dc05cbb2c708ad000000b0149cd3fc07da9a84fba095b389925cbfc16f8bed3d282d1d88b2e6dd213636ffc4fd4b7a09db779c95fbff81c14fc2990c4a7226d3bcdc3ff4b048778425e13050aacf403d1fb990a764051c58799f3c49a6d7e83b4ae769695943d3267d5be96e9eca149e22ad07d4b27ca679ff86791cd16b99f4c5b6707314aaa443f3028c9307e5789a0fe8f6b1e78ff90e5c7bae1bf2e9a15ddc3d6276167d0d4dae3c18655b2aae28077aaf364098cc57e22895000000b0271f93e0a111b067367595f156ae92e2af7daa555714edc283e6fa4419b632d7b81795bfa5ec0e7dd0a456426f7bc4f4850953afa427913355d150ee16e0362c63bdebdfc0b829931add34e6d367bc2969c2efa08236847e71abc5fe9c98dbd6e800c45aac98fb34c781ee869812bcca26c63effa7c3992d18d4b05d9e83870a4b3bf8646f6fcb7213e47b69b62dcd5c2b4a3ed49a0366f9c225247872e781539cf5b178c013c033ec0d35fb206b189c0000021c000000b006e2c1c637884ef909d2fc5cb582a6d49c20da897125b5cacf1918674104b99cb1fa5720c14b98f2d9df077737d818f21948e804268f8c3f69767d8b345a4b01d97da2b7bc3c95315f17eeb91212529bd68fe7db648a56d2b245b3559e9547a8e778742564902b675a779771f9ab520c0df36e4a73d491b97dd25914473264d23ef30df306f0a096ea984dc259993d381c156289f1a72a244701c6b48dfc4ebd0da3f0c3545f1d1c494ab3e004f3fb96000000b00cfbc2aec8e2b17c3b46625eb9b6c2775fb89d270d609fcf9686617b33ce9f3c83c3ef6da6b22444127fa75effe4ae396dc31ecb038d340ead18b08f4b1250d9280b69ab614437f3da1d3402642b224cb833583a1e3832aaa89e7315c2f591d685e320fde57f47a513b727663b6f51322dc648bb5f51c6ef87f76932fb945318c03fd1a02ca52641c0fb6fd65f855c880d868d01aae11dc304d53386c9e5afe99b326968e5f1630f6b3a0cc1321ab494000000b00889da7b7c65ffa75df4eec9dfff353747df40801cdf84bae8bb3a2ea28887042d13d9b99cebb9d09d351797dd15c09a3fe11e77ecb39f13a807e2af33c50884538ef784ef25693db3b38b99802c70a53dc04f097522db19349c3e3c0d6480a44db3d5d47c365de1f4f85a2c33a21ac91dda282f10dc7e9f0f5e471b5ad3f196f12302cf166801fbad84fc42b3b8b09c100da5b6554ba7b57116698d53680e449d4ee966589d66939b2e07bee7c4cf7c0000021c000000b02038bfae08889c2313f6b9583a23f158d8d5645775d5e4a11c6358c7406836b415a789d6a130ef8756a2e0b47e1b5c1aa1ed8ce6f217f1369318fd019f53c3c62a508bf54c09c7f911c55398321942b40405dc8c7543437b1b75dd60898992b93c568e9d8780db4c6388d39aae83083319db423f228eaaab09bac5f1116e00d3daee409b0fc04af0c9586e28e1f02c0c0b13629bf51cf467f3e0f25357801260c13f20934a9b354ceb57c00e29446e05000000b02db929fac21282254aa50b05fef8fffabf180ec589e608c26a11d1b94482e927c9f91dc747e90d938a1665ba3f45a589524af9e34a5b2a03f409f600132eba92dc0f0c21de7925b66ae07baf255c36161c21f2f6c4541891855e5c35ad254d5ad19211c6df036d39ca537c7f340b4fd311d76e2ade53ed1ac7107d38a16e786579239aae09776a61f99983e0fe9bc82e1e7dadf22596c9efb7a85bb6aeb8f16a87fbdf0de40901b6a135dae53bb0e5b2000000b019d9211edf5074403441e55ec69960259ff3e74e401de521291fcf8ab290607c3c113ecc027414fd03cb262a7db883521f261d72cb3b8c0ffa17a913816fdeb1ba2a937387a75a4b6a990a7761ed16fb5b265decefa9d9fb27daeabd79ef91b87bb93f517540964fff31043f00e4500c06790c70c73b15a2fd0c685bbb451408ab14c03fe5e82daf2693798fc618b11211d94ebb4dfc4e274e2af46028fd7747cff0b48111356b9b891cce731d61ab4d0000021c000000b00f04b1b37491bc0eefe2f022af7e9b55843ce4bebf9d08efc42ac49f67410387bb8899e0f60ab0783ffc9858e107d0653255ad6f7180af3e8d7da2ac6e4edada6f8fa3c801b5f4fa09d244b48ef6af9972480561133e78641340e5ab3cb7f939acda7e07919103fa60c8132d757176582ab781d91288aa3a1a61d6abd4eb110b5899dc8509d8b64328c0fca13765ce1f2bd0988a1f974e2d808f5f51da72d15e6ecb5fe08482afb002c6c30c209fbb5e000000b02fe8d2ea9d6dc45cdc3a74b2c69b7c0e86c8cb376da89e079ad58787cbcea184bb068235a10feb9203923c50ab2f69ba2fa3b995dfa9c975c744fe31e50609de2b8a70d056d00e1da48cc7d951dd9bd77424648f4eba819a21ca77d19d83ce8e29623ad8bbbbdcf0d6e20f98f9698f6019d337e7ec539860549e7067cec91ea01e3f9a5c210dc456f20377be262b0fa80b904910d69d1f39c70c26e3784a3617293aeb3dc790d9c2ba519d17fd812386000000b00347657189e836595bc74ca7010f5ea2e62ab4b15fe71ab1aafddb3407e1b8ef531266964ff4b5e7c160058c18d7c2fd2b2964a00b8e68d9eb5b5e8bfa23cdac3d025954794257d0c51b1bdeeb401f023a565a133cdd7cbb97f58dec2f9e86bc17c78669b5c62e4c7f9fd81a3d60cfbc1f5ae6a00007b59c59b4f28687fb6fd87eb873e8bfa133bbfc0a1c2316ccaad82b35b97ed3854da7640cab45709a600c53cc639b7f6b1e69eeff36655fe68a620000021c000000b027e66182ad7ba06bebeefd74b9826074f77422dbc0bd480152bce15312000340b474b176cd1fd2f2f690811f322d469eb41d40ba325cf3e6286b8cb3be873a427505e2f0868fa8f370945b4d5a98fefaa396d627f8c8964028c47ce2472cad137413e3726e02af50a7286ee2d9c213b3296d016e8f4eadab5466761daacf82e1f76b68bccd566521ea9c1df731716e530437a2d0d7a3f4c2760e8e70f80246b12d3c6998c5722d8ebfe57f3cc4ca8d01000000b00239a40fc769c8bb5fccd6f08e97bbac03dc655456a06baf219eba3228a607f82d3e85a99f2be2038a6a94b3367210f4c6787d359964923d42806673a67350af8cc10ac22e666647e3afb7e8da2f342cbd430c368f724fdfcd53e75ab35ddbe84e14ccd7f453294bb4f0f661d750d0ab26f6b1c4dcd497864d219cd9d43ba44e229561ef50ee5578bfb8d57df91e73cc0bbd1398378221fc51836de6b551f139ca6be360ac4d80b29a1881a1675ea862000000b01f60d75c036c2e228c9f93eae0696a60f683b90a0cc8507cf8faefffa6fe4439478a1dc6730a07a728dd6f72ed08a6683998554cd77ea5bdc32a7abc159bd3e3d15457bdf77cf87afe70bc091855a3775a805520bbdbb88e4438e82c8e1134af41251604d5c858216b90b2ce1728fd991ac1496ea8e42da531d6a6f34c9a0b9e1dbf1953bb57fbdb47641dc61fdabe7c0866bec6cddcd5f269531c1dc8c575e97975569a2dc8856236e0b85050409c8a0000021c000000b02773acf5db5c64f285581c9f9338a7f4b56fb7a84000df95539c79a7e1dfa7e7b9744240f6401d77ce1b5e080d883829c750086e87d31ddf91493d610ece440dd57eac0ed104ba5b8c482773857ba8559a6595dfed494516acb440a790a15f08ff8b387d1b16637c4e386d09a86ae7221a92b7a0c3b15e11f2b96807009c32e64c940b4f805ded3df520a2704cd7a6820e3ddde553b42d52a9d089aaeefaa6995d6af6a445c49323157d200db83615f8000000b002900c5aaba7f2030cbb53bbb438c375da6e64fda36e929a55c4820ac2b848bb077048e516a4c63b90579223d6e9617822e9724dd284bb55d7919bad02667e9a208fd426b148d7b474f0d8d48dbd0c642a4f48f584245ffbc89efc815ba6c096fb5a3ff51452b70dda458dbf2c62997503a624b5b81893c8421c0028fc8fad3199f7f9452edb8eb0023073730d626379057c8958c90487cc49409c63df8e3657d50f250fb8917c92182366918391ed21000000b007eba9e332441b9b6fd57c138d1a52a1290f4dd4e823974e4174931559e7a90d134cf49e391642294da2dbcb23811775bc8cd5df400eb9f23546582b8b0853f2806e875de7ba19d4bcc81e6747282cde0bf0197e84ae1d3c7d18dd54e6c1da851e457428a3fcaf3b3c0c38a4493f39191a2ff9c76339f11e3f8ae575ca6c16d4919768595753f8df5142e3282426b39b1306b5041ceebe13ce47ceffa09aba57db2607090cf0dbcfb1661e958dcd731e0000021c000000b028854bc7c947ece43b5826965b80e87110ceda6eece2e9b97a972745af64acd3287a6da08f043dd69043bf1ac6514a9da7dc842510600a6b8dcf6db7b03aeadf8bd2d6f55ae74985ca30ed6727d4fd7fbf2c3a3ccd62221effd4a88004b60c81e87cf639622448d4177522ab9b0faa310c4b27f44480dff929aa00517d30b645b1428f4d8a0e3435aa7bb02484c4367b090442223dc4bd14490a4a421863351023ee1b835233fd5b45b0e4f508a6921f000000b01d289673d72956641a8810addf1d76825cc9a76f8ded8fc440838534dab43c7b1285c39b630822a4b27dc027deb8bbd9b0424e0406eb083981c0b4299f836039e40fbcf9d82916474df5165f875acdcc22e73b2d881bf313260da7ab1177b524ee86df5095578f4c688005406aacfa1a01ab301e25aab9b407e821e11d84a90d286362a5787b7912a4546a8573aef62a1825f5452122bc0069856a7f6a7a83bc9e018d7609a7f35e0d4b449655047f8e000000b00c86b2e04c827c1f40af92aedd3890fed59bc53ebc6beaafb24da022d06eb8ebc067bfe724b573dc107eb79e01358618cafa1fe5724a2b9c108a1a3d55c88bad1ef345e6e3c44fed1070e416f58830d6c3050ad44a67042553ba761049ae9f0b10804f119cb28bc08acb5078370e6f7428a92204841674d4b0a30895ceadc5115749d4bf7f8f200c4425e0b50e8edde01eabbd8829576bfbde0226b608a71de7536d7ab9c292f0ccd1f77102bb6394a100000fa400000168000000b004a58010e4a9c895545099329a3b9c8476fcd5d51476a997c4cd0fd8ac5a883e2cdf75d217ae486db3699b6b926565bf1cb24ee3c898303be400bea8bd7fbfda6415e5662c1171c2fd6fb7931be1bb26eed30a43524155ff85a281750cdebc17b8b2ec848a4dc5cc340f46f21f1a0bd400fd16c3c44856820ce3d028b2d11cbad640096ec6e7e049178a0fe15c8ab8660bc4aaa188a47b2330263cd4fff122e53bde2d0d7ad623a8ca8ed98520bda017000000b0130829b3be71be10eb6942f2c61bffb1b0cb0a3fc08df95633255c39550f8d8a880377d559f24bfb973c4e638b9ccc4540850d3043f202aceb21d05cdd27d5808fe7a8d60789bf328b5b41630f831492236e1f8b3584a305183eed615d57f41915710c23e6633b9b5a3452fbb821e91524c18425348848739dbf261d59dcf8c22c8cccfa6b7a91c0f88fc6608c8c156c05ceee202e23c0e9b91c6681011c690791b6c5701a03cdf71c2c53ad7928643400000168000000b0143d4a0673588953b5a3234068f17fe317ce34ff574481eb586645ede4fd0a1df1a8c91f39275ebe57054f6bb83a0669c0cc56705bd905ef77fd475e44f4ae7c27b9e4192517b46a8d68b282e5b2379b17d09cd5bee00b2c1f3e7823a0cf3d8ba7798d9a5262b7d8d9c53f46afb4824808c8739ef9b1057ee0e19c06f0cf1bdd15423e2da726a94959cf5722054773db0b6fca123605cc984b63df7528fca9a2bc0bf2938eaf14c83dcc6154dfd1cf1c000000b0109896d77097bbfe7fe016db0e314524ec31814eb76bac2483a759b9c3fa753f8d7761a1ddfd476db2946b92ef3e02b43b56ea19b803ebd59c5b19c8d2c91aaa6378a95be226e049386398b4426f92319858fdbef18a3c3787bd13c68ac19e3ccc1539eeffc60452935062e4f60667e514d2f38cfc194bcde9531a706e8b19cc6d104d0e9facf03704319e9ec523e0d710fee0cf3681f3bc62ea93721479d7a77007e9c3dd959388359fb1eb8b5c5c9500000168000000b006120e5cceb39e219c320896babbeff32d67b5176d1dd49e03e07652e716d4ee4d3ca2a8b3eba96aeb35d5be4edf7424abdf912ff7b634c8566404e53790f3b770e52a932b4edfae70820536f314b7f9b5db0fa4e61fe310db3e922666d087273ee86ac95121bf22ed2719b307eb17c72c38d6a4a44718e55f162351ed5aa075e0e03a2a1542dad1eba0472b1309ceb527003679f242e2e84ec4bf7118a3015fbba017003e1dce0ecd6a1e86a4e49078000000b02202e8dbc3ec209cfacb74348c631e2b18dfe4532a5068d6bb169c34129c56ba46a53102ef6b476e932d7072289bc21db57a1d1596b0d704ca4fe809cd27dcdd3746d16eb828e19ae40d847804282fc3fa4e39e147bac06fbf6d9a07670e613ee833516e6a5832834a1e45f18bb3a1e32a79fae69cf7c721413bf0c519577156ad8f88ffaac98f612d11164d3a3b24500687a73e92256f6d814bc30e75c8bd3b1e906eb6ba74cc99e9379b60d292832200000168000000b00b5ac8d74cbc940a82aeb181034352c6ded256e0a627ae0a2130f8c133e685d31cfae28643f9b42c92097b4a07afd9119005796396f5e7af55fe37f941f14a260ae596686a28d72e49902dd36642c3440f6c19d99ac4371d25bfd40d28a68c230eca92cb2bb9d67cfcca540c822ab8c5116805d71114ec69d77089d8bf6172a2a1cbd4f0e38602fcc33d4d71abb8bbff1fe1980800011495525260d11dec1959b18e749ee9370e44145d8e0f2bc4642f000000b0082502dcd86ba86f14e86cac47610305c78146ba45b7fd2dc4b732243a2d78f7ad9824a69fb37b768c1b079f7a22dcdebc78ea020597d3fde2e4937a5fb5a3d83c0f4720abb7bed891e2f5d3e92f6e3b1d867d0df9e4d9a932fc8591e8752c50a03c3d992c58c86e5e275417413ea6a72b8584039cb4e2083257579bd2b19850dc2c01998b4d5fcf8897e0e4f0fac17b2705240fabd4bedb3447f0996d797952ba06efc2a2dfb0f1448dedc5eed3c02000000168000000b006c8762ef60d5a13d7a23b41566ace258c08dcab4fe9697188533d31da2050e092c8899e969072d40c339e9f43c3d9be608330ee516bb6d46b34bc858e3761df558eb0b289c9b0e456fdefe0bfd92805b8268c3e42df1866ae26c45157759b6aaafc7a59ebfdd12b1368e79e8213bd2c14825ead864e4c258d7a5b7d632ade94ba1244b7272f06045654f4647a7671041b59e9e159b3895aa6d362dfa104e3247c95fda3955aeeb31a900a1ccfdb096a000000b01c11347469543444dda7f55d3ae0266438ba1582deb533f0cde1993b30c3d38928fc7bcda4834632f4ac5e127f81e0d2301fa9baae913037c64d1e45b18cc659f1257c26eb02ec639836bace4c742b28b8ddd589ca8f94959cbf7240a01bf46d2fc8a2a5a4e6a89f552437ea317d70b922c0e1629bfa84b0f5021539c298389765e87e8260bc07842e0d286ca86b962f085a0416b3ecda7b35703840b03ea2591aa75e97baa5fe69abff13a6f532f93200000168000000b02210472cc6ed4160412013a51cff729e804156efe2f751dc7ed17db930807e5dbc4dbfabf178344d4853695659544f504e0f05cd9330dbdd6df7b0dce109f438c18cf79a3c9843466d7d3ab9eae596f53452bb565c0eee23a092dcff54ae48c069120991de177362b420442045b5f4902e33d24d44e65580b99ff30ff975e264682bb0ef344c4d05f0b53979966a1ec7098a319738c263ca6c4058761daf65a83dee06fde5ef3c2cd94d581d51239a49000000b02697d6e0e76125dbbcc891508207d9a188f1d51f3369ab8686beeab0745b77006a045f66f36a0362a70a2c96096390f96baa6830d23524b857dd4b4e761d446810da54647dd363f5d66501c34ec0d7fd0da50934785d219766747e66f4ccd928e28f152653cb9e69a80eff375de3edec040db5b4dcc36bc0b4bea870cfaacc72e7f212e29d1d79f24a4c69b791fe4b9d14d5848b15d8010b9b49ab1b732e3a6f8b857efe892776fa95d6a3057a76a46500000168000000b00f2a12e340eb2bbe6f97461220bbf5119f830351e61cf12b17fd0b00391aacdedd9dd17a4e87447261cf9f0378138a89e2f6ef3ee7a4e32f741822304556554cca2db48651ed7f092a4b00606c5114a1e92e195c927c4f71509c610517b0fca61d963abe8642c4240d5a16d4eee5917a02785c28bdaca56816c413619492752ffb2930e553f96b81f645ea78fb910a99138cf0164fd1a13bee23127e420f20d260f388bc36f09b1a7b88839a15b2950d000000b003d8e3db7e1cbb67c8b60dbf90eec442ccef888d337a58601c6d8009879c37b10a0664b1c023b4cd5cac3473306e2cc19a6e34696ffa7ebb1498cc8c3e6b438e2692c45af154d8d1c4a0c8c0a8f5808c97f579b91afa5ac860b7a2803b2581090176ddd3b47cf8d5eea4ccc3064d50f91e0adf3c60de9af0cc86196e9262c7e937901d43a9146c436744878e2f8dcc50197be3290b465600280481bb56b2c6a5359e12c9322caa87ee1cbc2635f52ee100000168000000b0010c5d5146573bc8b8821de0c0a7eb0a31e49bbff679126b271ca35ccfed3618055a5f23112b3706526f172c7fd6f597079b8f4b3d088abbb72c4bbd091964b04360bb8dedcb3e91f75db4833aa9277f6794b7a4b084ba82de05ee6303dfc10e4f924e771151f41c25ae0cab55454cf525c4fe38894f2633eb1314311eab5c4f7f120509032df3b46dd47cbf0c55b9a4011a839d024d83e895ca8dbcd0056a52202ec9c477bafa378a7f7eee293583aa000000b02732698e7342a864b0f38eea3a2570e64db4daa68bab0e8114b52a4785984e468ac79add7dbb82520629114658d8cf0576642fe2ee0f8ed70f0578c25a7075f7978e44bc565fe69eae22e65713e20c4940bef76c945cfd24e1bdc2cb1cc2484ebf8151a3256f003247394ccd1fa3630d1136c0e323304f35a14589baf05b04a8e994346672ac207c6cdf0d0341df06500a51b384c3118673c03c3f321f36fcb36333de813b88647b221e4e332e928ac200000168000000b02e2b48b77e43e4633f59f05527731cabe7330dd36fb11e102826e8ff0213e88da0e0b3a315e19407167bb25a391a30b4ddc4332fd8f3a549be710a2790469785364a1cb7eb0d34766ad968879d3d85ac4325e25cbcacebe6e0897a7bdfb3e8460009ba3bec53ba84704b1fb418d434131320ee1c2fbc07bb171aa02f5d50190887a9d492c74420f1549d7b3c065f7cf61cc33d3f2bae369550f7a143a87b6470fcdee5755c8383d7dfed7f4620a13420000000b00d2cd99691695b7c0c005684f89cdb45d09f31a5297987df92da3247718f6fdcdfc575700f78a08724043548aaecdb3926ec2b0529fc5e47020ab857754c833f9e6e2bd69f73ec164368c1081a21ebe8b03518251aa7c42963ff565a9b83e33d948044c5d47855480b48c334d4bea9a815c84f78376aa59fdc19eae7aa76cb70929c51b99bcd08ccb4dde63da30d790a06e2c2aa4336f4d01dcbfe174ceb0fa0c73c1131edb7ef3a75d118f45d8051d800000168000000b0035ac97a3c6b9b126df9f9990098c2a33cbae168f5077e19e0aa70a1f8db9b4945779d24a8c240471a87fe7b9c7f183af904fd429be713b70becffd3205fb6ea562078545b7ca842b9f2f9ecff5d0c6c45fbb6134df98f9138639687a57dcbdf5e0981f5ecfcb1e7e83498dfc810a229092e8e4c4b2751c905661ed1ddd6549cdb69c1dd5d16b14988c39e9f453a89292f956bc328b6db1b9f76218532d64c48c7f0059a2feb88cba473f78f888aa14c000000b01dcf6c414cf4960a64ad7239e42ab58d339714500a6c2f4e7e2c9a0315a43ee41d6d667da600995bfb6a2340bd3bf33108d0fb8dbfb60b58ffbd6f570f1984c83174c7d51199aa0f10889bdee590f7ebc3d43ab25e4f98044f9f80f111c32255f85547c22c142c0b3f558c43c889ff1e0d0db4025527d6def35cbe1eff9fccb827f28a3035ee2241cdd568167d837bb9157be0ec642fbbbea76bad13dc8f8f0d4ec0845f2990f72b01cc71a72dadc7d200000168000000b00740ddc37add5b565fe35fa39c3ab05628b0fe7b57bdf943ea94a47071c9af0efea2e018fd8afec9c389cd6c7bee368a9acaa1b1be75ecfb929bed5511a352e4009a9f72a91eb7f430136ab601aa96234081e07517d15b15ca63dd4a194e9adc25c7fa71366f065d1938cd6036ccab0f1cdd036807f226cddc03190bb50b1f9c089c2bbfa69b3a6e8c88f8f68200b38023510b8896eefbf0079862f1e4647c6768bd0a4d81c564ea3492fc56d1fe1008000000b02683df584c5b959fd910966414adbd00b499ea3d08772f19c877a937e487d2e8bce521c5ca40de064d9205a3154e24583e4ffb7e6b9a0ddedc20a60382fb401ea49f26705761200461ca7dbe84176b9099dc58c4a7f10054abc9e7411b0efeeb4f2feafbfc3812c5c7a29948f1c00cdc068e3823aa7652fd2a7aac2102e3a937f7723fc6d768784aaa7b9b68323a25e72a0f9e866898ce028dbfee842f900c5968e27e5d0c1ebad62b48c54fded64e6f380000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f00000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000000000231000000000000000000000000000000000000000000000000000000000000023200000000000000000000000000000000000000000000000000000000000002330000000000000000000000000000000000000000000000000000000000000234000000000000000000000000000000000000000000000000000000000000023500000000000000000000000000000000000000000000000000000000000002360000000000000000000000000000000000000000000000000000000000000237370000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f00000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000331000000000000000000000000000000000000000000000000000000000000033200000000000000000000000000000000000000000000000000000000000003330000000000000000000000000000000000000000000000000000000000000334000000000000000000000000000000000000000000000000000000000000033500000000000000000000000000000000000000000000000000000000000003360200000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000401100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f0000000000000000000000000000000000000000000000000000000000000619000011000000021c000000b018cb2223bf954f5fb43f08dd1f904dd028e015e2232a7f777b02eb8c19bbef0fe551b5968053b93ac2c7226e607aadc162d1e4b9c49a3efffd71c8e90eba8472c357f5fd909597a150c4ecf1057f03da54f0db275c51863bfd08a7d316b5b2100c4e5e0c698f8d22dac3910ef60643b826132594bc742bdf92d0ba96435c3bd3e056990b095811e9599fb6ea7c80c2e5009a29e37cd42477bd61b9c6bf957bae4ba07a3be97f5170a79148afc21a918d000000b0246e6ceae3c85a1b12873d34b83b83aaf3504b59b82467b17f2ef31a170f7324c6afbbd727b6dec49fa1416da5cdcacb4fe1da65a630dd78d475e7f97516c07074651de0016fe70bd8306252335b93dbb6910e2f821b528768a0cebb9b5ed7b2e2124ab7f744308e3e2a135af0039d9f00820842fd64204faa8158bfe9b43da338d5efac914b1c69feef915f65a3b9841048bd3b277fb7d6ddeafddb7ae9d767fbfacb48ea435cb7e89002ae75028e8d000000b01ffaf982c3d708547d293f9ef43dd039ba968ae7cac6eed815489548fcc19c21a7a8aa1e5792ae5d6e0cf729f6c715137bb407b4eaea60a757eff18237f06a911b1b2f08d4dc9ddf5c6eec38072c5e529421286b2aaa8740cffbacec15b75df4c8df25ff72d696bfee3f0250622da08a243ea19136eca37f92397b43d102dbdaaa2b31876d4cd273853b0a4e9914b3e11d023bc06780cb6f35ba4409f26e146e8f201c18b61de70366fdef667879068a0000021c000000b00514d2664b8023eb6ad419a84f90bebb848821277ea40a5d1110a3df419a6746e23f782c2a30c93fbf8bfe9325a61d944c193ddd916a6c4cd9c9adf393ae99ce9916e3850607c4c476ad0a69c5b4309308756cf40ca98dc8389df11733e096cdae8b1ddc02e680916a726f8e9c3b85d2128f787a6a0fbd787b123231b9b2fb863906d1dd11edf761d68467358740647c07158a00d8c0c31a265e38544a863576105df2c19f06b13f2785a5231e23a928000000b026d773b8b85ac98b71428586b2c6ebd5d5d0734d494aaba1fdf7419f2b29db4e6c93406e719c649be711474f8e8a0af0f744b8e21453efdd2e06bd72b65b4e6a6d96463a68ae115ffcd18ae63428fedb2052b359cfb578d7184fca79486cf0ed26148172fc7ec4995806e1672a37933416894a2e2bd1e7f7de9a10546d38e3d714b042f846ce05adce6268a5bb47c97318d0702d5c8695d5a8053ffabed4a4182cd06903d23ce1ec5bd335f3240ef919000000b02d3a82a076eb1c7f35330b33c39c485b585e3ed57464db422cfc5fb0593baa24ef9807aaea9ce3480e2c807be7a4e9e5bfad94de9eda4e0fd0a5a6069ee3df4f636bebf3b6ac651b59b2c0b2f48b78f736f129f4434b4eb9f0fd49e34c3dfee198b05b83d4ce2f27532b6eb16ec6387401902271deab418cf25835c064554dce3081d961a5ce9469c4221e105137bc081ff27f7e8f42255b1abffdfed854225cb27058eb8935e1a2b59e450f810583620000021c000000b015aaf00921cf4d8c793fc91222623a66cc5d7dfed1bd03b496b71a51cf80ee401ec6201b1a3714e2bb05b2490c78fd5d87279500364c0720bef720a2c3636c24ddb81644dd67d015619c7eaf242797202068942396f0c152358fb33e3206faf31d0d010889e624069f44dc7472cdd0eb2f69e9fa519859f5a4991a9bfb421c2f06ecccb5846cffa20ec14648ccea08260f532b13abc1d8bc54bd1adccfd6838502acd79aa9a46dd7b4007a5f4d594d1c000000b0253f3b69e62dd4e020eccf12d703a47b2a150d63c5f52f2d7fcde20f5497d95f11f296979a8fb26009cf3c664d7dac6c8a5ec2bb6f9e34f5160e752992ad65c56e8e4a484df9217baa33fb7e48f468a0887b39336d5a58ad81c138cdedca05a127459c07c91418cdda0aa520b50f20f3257f01ec0917b5af7ead0e991b514ad6b1b7d98e6da22af7d4756d0e03d5fe071b0c4934487ea4307c3e526f8f703ba2db1343ca0c7c7ea3f90a5687f2fcff78000000b0265673c6ba5f6bad445d6d8b84c1acc1cad648e52afe2eae8a752b4de52fff139922cbe50e97b3d4f63780ee82bfbf73bd873342e714835a117f7ebed5d0f53b9cbd963d3c8407163375dabe73af98c1f5afc4afedfa998f7a614336892e072a5ede85f783c8daf7f0ae6b9317a6abf1006ae478c360c9c863b4a314e4a134292a6355ed49267df7e8f9dcbf76a793e722a861911d66c5916d2e29c5871c346be0630b394e98a58a760f5735811647bf0000021c000000b01d1ddbf1ea99f7b3eacea22f084ceba4ec7c9e960f8d1ee9acbbae9247a41db0907683a172391b4f68c04a3679dbd55da2c1fd4c45830f42049a7fdd385860c4c1c65493980415340cec8ca81915a82cf2dcc3019911c18ff7c2335bc01d660dceb057949ac4a8afdf805d1f0c4da055226a14e024336583c31d94601fbee6b596745a0f694c65317d287a1534b1d1bd04b35bff57a5886369eb7fd8a25b78f387636bf6df988dfa21012727def0ff97000000b01c0052ba02016d51b7879d428fc699510305ce4ae854116c4afb30ae7b39586c1fd87db1b342d101b5845de935627f661c6d6de78d012326630538ccbea8cf845bab55a55b381d159b753a8e4ac549b4a8feadf77de8691de79de34426d628561bb0d7a708964cc44a3f18051a11000f131cb1f9b08a087f80b9509e2dd79a85c1b28d102a9e43673d4ef10c2d9505d0094ca691d27c0bce7e3842ade277a1c77a7f76717d03d124f6230085a76f0477000000b019c0b0f86a213bb87d83e925294d30f84f8351e20ba894c8a38dee26fd9800e29163ca9cc73aa77a19c2eb2cfa420a214dfada08200e958591965fa3eb48963829a0d18f7a9b816eb0fd53668963bab5a1dec6e8caa94c2a5c7b678962d5f788bffbf6642a382e714d8a6eaa90747d352777d39ca621fb066b1d82bb5e1fd58a99d7db07a9790505f5b1d0bf3951170a0890e92ccf162bba0deeae6f73f85bc5909586bba79913f17e9bcf91a40d5d080000021c000000b01f20a4c619ab6c8390b2377eb0f0f98a15ef412792201c2f86fc1510da4c8613d97f3df84068654a297f3932675db828c2711b21930c2c90055f07045b99a4b9de153318831c3677ea7b46cb4cc12a44dcdceecc64a452261a72da733c8298b885fb01b231e42c7e9b497f6a51e80dcf302040a11afc419cf0942b51fbacb8421b85886f0de9730fed7fd6e055dc6e5920ca2aca0a000c2634bf551189cad3f9f59307c7b18d74beb3370dc7afe7f5a5000000b00ce7018bfc8b4fc7c3cb1a79b8f993bcdcbc09a36e7e61fdc9e0d46a004f6dac86e4b7e3598f7f791d3d6d6cbae1967c3a193f617d5472452eaba9196d9b84599e29428ff9dda567e2dbff05ed3616585ab74f0e9d3046dc4d488bbef73d05f7f4f45b4deb087ebb29830dc6871d585e25227434e6802b5f3ead0f090758a40c643db0d9c3f7e5830205ba15293e30250ebd1473a390faa200969313c88241b8957a6b399fdd7e24e0675097404d76cd000000b00330608b25b661de93ac42a971472e703df90f58664eb1cf4967af5b5ca18dd89fffb2d5e44666d831e53bb24d9c6a2498859ffef3e4694646ef05c8e678161b9a16f10550d6119acf7555a98f1165cf4f5f69106f7c992617da23cba4f6f3a064212b2ae660cecf34783a7af7e2026d03b6afee17d3ec0dcfd032627027ad2cdaefd920a6d5882fe5a918d4c865be650133cfee9b99bec73dded7fb84753c76c3c9db0e42599dd9dc37ee499ed5f5520000021c000000b002e98064abaae5b13f41f29386b0e87215cf28213584503061fee470fe51022ed5688b1a7c0dd8d094e1b4fbfa4f21ef64d6cc75e6fe1cc2ab8b875cc3534633686eb40a02464daf77f1fd75a24a6697ea95887ade3ccc73b7cd36fa6bfa9055ba5573b618623286fbf24e5befc009b5076a538afb1c6f0ec0485622fb2a2bf7bb26b590c1a750bc39b9c051ba4535572e6af042e0cfc41c450c6ef9818cfa8d188cd4f422b2dedacd4720a2f0a9a750000000b02c5d031173a33372fd74d234b11491a66567f798cde203a87ede23d097a21e63fb061ad898f21e7919f04201ae67988492d31956668ac9e12b244ec536c2a8f52fdb1affcc75506169ede51ecaf8cfded348a6e8a069c2f0aff3c5e0d5e1e5e483bcdca2c23bc1f1417a0738fc804d65002cc0c5cb02724232867257e032709f7f468313ac6ab1d892fe5f0ecd6e55232e7d4cfa048c6589debd9417a2d9cfc63825b87e67bd786ec37dd90045941d9d000000b02a1c141081288239334a22d2ba81b3e30dbf589a46618b942752dcff501b39b7093df4133447f9bc8fe5a012b7f98e1418ebdb34c35865daf1b8c0d305ca9e0c5117d4316757607432ae4e5b6d10961a990b9363f7d51afaaef8e2b0b13facfb1bd0a1dd33ef5355341eb46b44524fc3160f918dfb776a536603c20d7cfd6c59a6d1ab3fa4ea8c53cb448642bd756a872b88e3c66f112012a43fddfb27561764894bb421671b772f289f4ba13fcfafce0000021c000000b01f59ee7c1cffd30a284ae7160395aab5b87f842354d69e2a58e5831b32130d3f84e3e2458d5b2f524cc9275e187c1a34908fa0aee74a95d4f1fd78f733c830e980059697bcca3c58f2c9ae8aac347e11482aba061fef572e1acf7c6bd7c512610c3fbea68cebc558a1daff4fc8bd95140c9dd8b967374ac7a10a1c6ac36a5c91adec4fdb65cd298ede79ef00e9960c202fff5c45e3254091000155cc9f5b3adc3e0de45a4b64866b03828f98292dc632000000b00a287d29c244fbd415091725e39ad91efdb4b5ab4adc18f1eb70bb2d3f5cbb2fd26d3aab5af4fabab8aa5ae19f1c83e862562cfdb8cb7472130e82e63eb2486ea4a877e2822f76f0952d960364eaa09a0ae0261353a61e408f3f29322b7bc682f3680f70aa3642d17ab845fc3d3441a22552ff2d37e612421e139f922790e58fac60ef012098370754ffe1860a54bd292f5bae18e5bad9700cdb5fb1c612825fb09b1ec0bc6063f958b176017dde7a5f000000b01e66ba2061415337ee25703ce7df84399284abe1d4c7f57a1131ff7fb61213a06285b87ee4619d4509eea1b2dcbb1344cbfe4d67ef2eeb56e84744b7c5648b3c6dc6733548547edd6c9e922d2924734d65e1ce305bacf329f49ec1bd2b246d88ed29b81859289c2fbbb5fa3614f395fd03299a039b41333813e473d8e7d58a565b137c5d450c7d6d6bebeb927424facc145a00474fd48cc0bfa5e39f62b469bba80f702b1591424cf11b27958308c4500000021c000000b01ea5131d14abdfbcc676350b0a62faf9978eaf51ec93cf3550785ad0303b25c7e70e5b882d561c9da74a4ae8465c9cdfd779b85a3dcf94ab9cb6f6fa37ca216e24b0a0e08c6f15048775e076d45baa4a4afe82b2e3015989122d13a2d82922838f6601837196605a6a0287d840bad6b22fa4ab48e5e6d4ed92e6ed373cbcc2c7e955eb927eeb19fda35951a122f882ce27b5ae743d696ba92ee42ab9f92028c24e16b3c45066aa270c73e35a2dec36c0000000b008da97564fcf8d2f015c1cdf4e92f380e0f08c38e2e0cd3781d9321880eaa37bf76053ca689d7e8202e5806fb8e6c10c748fd5e77e15b1e46ddfb0f2b9a346bf553132b75b442b3eea14a6db8927417cff2cacf7fef923f0864cbae168ca388d13efe956e2314474a7ba64676c7431e90165a8c133f53e5054b4a9790dffcf40ef338bcd93a7df229579ea7c47dd0ba8013493d4fc6af16d44aabcad9a7fb82c56baab4ec2e0f17e5d4ecb2e82c5ed49000000b00582467968f62ec79a27bad1964812d15d84a1d7807fbc5dcf1b148fbc179fef2ea200c369455b6a61405bb1be5935a217b09afaa04a5581e9f9b5c192e67ce859ed6ec7c1658ef4d6f3bbd601c5b3eb468a589b53b87cd2b124fef9b995fb5e175c72dd8da3f5f79caa4e46297b19d0078e8e8558c14cdd996f11ca48204b5b265a4b52d832018f0e62d6651a43db34187ab10c07f10be47951b2cb1a508e88fd28b8d0f7b92e495cbae1b721089c8a00000fa400000168000000b00cc32951c32e5cf9552227ef453952d5949cbb95935c992884aeb251e31a71162281c9ce3a1dc11c41a16c445e9fb9235dea1258c08ee8ee8aef0e5e533b82c937ab69c03d771e97555ade247cfd41c7babfef91b73af96d7bcefbc722cb5931d63068b1e101d25b811464fe000392261efecea4bcef266289374e9077956066e4c91507484e9d722a8b2a207d05c2f32ac91bf524e386258a3dd923218e9298472dc4c6120b70f78755414a45d14386000000b00088c715008e371cab96f7c6a7f67857b7a679664ed8f6f7d5a5e5be3e756ef8b35b3c0ec3c8bd60a9ee62f6ef0ff6d4b0b27d0872b9736921604ffc37b1c4f058151b9dc759b075b839e1fb7acb58b5ffaa2afd14fb3075a066499ce8408e3913dab8fdb1d3319cf0fb165d132bd8b91a339de1d291a2dadbda940f5d7b4219aea8c4090dc76137ae5a825f9c9fccfd21d03f731c3957a444ee72448a5caeee5276ab19181a39a5465e035b448ca0d600000168000000b0186b8606ec3c01d8afee739cce53da6685108a7d2a1e874129d23a7d97988cf910b89f169f0697d3223a665286235f7706f9e5d5cb8b4ccd96ea6ffd506925a4cfaebb8b4a1ceb080b4f9bf22f8d03b7dfa3a1621a9f1a885df5976744ab01c1a834b27117c5488e36e81870b63e542005d8590b659fc8d09e4af6823d957dbaa83cc410516e1bdec74a092b461ec0d71dbb1ae5ec73974fad1c2e7fe4183ed38a42f1ebdf027735f96cef7372a02c4c000000b00100c2d540e0ac203b805ea007de8db5c85fdfc82ef0f01be21275a162401852d3691581cc0317b3d3ea5238cb2488a4f5ada800d9d2944f8d970b90a7314dd705aa77aa43b7a3b8e09566284df4ce0bfce4933cd66202d1d512d8279fc0383825485cebe60ee14ba21c239105de8b260f59a31fec9e38b66527e7191b9695edf837d91628b768dd82e80e53ff5e4be322d19fb7a928e16df3e6cf38ceae4c9b05653c0330047d71897c07cfa84506d100000168000000b003c56c7bb2f83bd49be265b99bdab600441b9f44f32a87050910cfa03e00cc537e10cee604019697942c14103e1add6c56d8d09bae04b98105c4085e5f3ff923ab836997986efb9cf26f4c96e343f136ec8f57e41022b06649d153e4a44bebb545459f207c813810b32c09a54e44051c17b6f0453005c35e104a975a2958fa28123983155818feab981804bf9719d40e17b465eb9471fff333292000a6db5953ba7894eb648c183cf1efb9e10e0a234d000000b011770288ab4863bd2d16588b1031a06d572919c06a32b2c819d1e7185ee78e7dcf94d0171b5ae7b10cc9b272e9db2fa4266c7d0156f52584dc4e4dc9a2de1203ed3e19b32b4f121c93ecc53c7968e04ead92d19e3bdef7b0fafcefcf6e3326b58bd0b87b53ce1715c44e953dfac6b25f2b43ee2985df988e3c6a6a98e89cd552209e6f73613cdb026c24aef5e19ed3d70e21ec97ebf3dcd621ae192294aa731201ab08ca070e8a3f3d41d6b17681a2e500000168000000b02a9781585f03297dce8b744f2e5fc7b64ae9ba4578a18c69ff6f7cf099913c3870ca790afe08ac14d9181da0617440a5f45494368ec8454c54590fb0d34d5802d9fd799e588782e2f3d3e5048f33dbb6ad29725e3c52d7ea16a1101a8d014adf01289c19ce0c7f06424cf70ecea9df1610424e1f7149b1ee6b5e8f805fbac6e1b7521080b8e14769dba67a150637b2081f26d0315037cf471a6556adf31edcc4805e01cc9ab33fd957d2bab60f3445e0000000b0288757f8b8cca6f0b3c83806831c69dffa09244df4739b6fb2455a8fa7ac1710331b3fd8f94aaa1d1a0e24b4decd9c9d788c1589c1457f67ee38669ada6f392d202dac33fb821a867c3f63ecf1192518bfbaa4a1cc2285220082eeafe76211f93ef1d2d81ac83819e9aee7e7036fdf3d0be0c035f6d9ca4b52072cb58ee28e8aa40bc4f8be2df52b06a2c9045e92d47c14e55f069df3a3d7c561d3c0e4362c23b3caba995ad91b358da292b7c8b56c2000000168000000b0065359ecd042c1f3b5144bdc38431857fb338b2261a637129684f9468e5a86aa690fbfa4b39041070947b1c2c402d9815e6d3dca605ecbe361d38f7254d3143dcc3bbd9f00bf27ed9d00f30ddcf1743dcf526bf9c26a4d9837518312b5a321faf4a7b9e76ad6a2e33c0fa9fe838d8926211d5994fbb39b157f4edc2aa85cb2a0cf047043a3741b21157794e37a4ebd050f2610baeb6576ace5be9d96a85a1b30073208e9cc3507ca37d0f2db37f202c4000000b01935713f0fab6fd62ec364d077d4116a850634bedaa2b78d362e818b726026e4f2198da0cd2fa6ee8b3c37c96920ef4edabe71e75689bec4babcf74242759f981af4f983704d81d62f3743ae4fa307e7ef3fafec62cee5f85f488fdf739c9f1a1f9d0cd59173f37136ee017e036e92a500078f55ee03f332797277234cbd096dd4220d97fbaf425932be462893c9dc282ef45b8abc509e919c400c3d64fd305e79e814dfeeaa30261b0e56f3435ae76e00000168000000b001e73025a2bb24e78269f10cdb93aa5c3db17ddb53a0e05855d7df4f74229683db90719d4b3d6742e277d7686b2e71688397aaf1b9f33a54719f2831581c5a61285d5c0e49b15f4dc0b9deabb09e6bac7a52a70e60a3d156f1d4733707495626343b22fc51a397b5790bc0a91a2e2c2420163775e761d5fd0c11f4c2837fbe1f869732939036aac6aa2d7717ef373d2606b935a4fff47ca96c1fa4392e849b144cff4b5e78bfe861b1adbc0c30eee352000000b0146e7384bec12a88ab1134a3b07777d6516f0123dca817450c86dc2548c07080b0c18f3a7b5e728e51d01635c2df0a0d62cd5d6bf06bbf4719b89f60ad58efe29b90f10e7f32624dc0c493a82d94f3609fa919b0b2d48b1d0ebb751ee912c51591f13b0481bb78f92a65167ccb205dbe1b6687b21a0a884eaaa00fd2fedb86089495127e9bce26d3f1e57a329a980ec82529f55f5bfbd921b8374b49ccdf541d2f9cb3fe4a358b37ccd2a21f6f3ff1ef00000168000000b02c8e44ab4c19b9d45a5276689ff992bdbaee58d81dcf33f7d9935e6030214434758ff625eed85961c991476fa994453845ad95d854feecdd2a90b131b5ec304298178ebb4e4f3714c009a5de4f956635e8afc09ec28945e80357900e58cba59a40e9f45b817b393deeffd44b2570b54c06b73879117a3d835059bed656415ec644a6bad07c02ecaa4390a45e0f0dad63029087b6545c80d7a7d764041bca7abc6510c732c96978e3d22c645bd56ae318000000b00c12d3b85ed54363fd6109bc63a7af2f9e5fb640c909a0e2fad176397097e376c318cb5ac6034372f35b3cb44d0bfa633c000494a096bd50cda713111195f4a4d1ea732eb87b99541232d1117b81857e004e0186f5801e27d0fe32c795b4d4a648658fa7c8b00088675fa8315de9399d02e622518122c75f4e8f0f1bee258cd94a1a935dd347806586b473aa2b78ac940423ce8abc1344f4c145243c65f85c6a74d0c2e7f90c592fe6e7fb3b8fc3e3ac00000168000000b02f8e1ed74128566fe2477292aac9af8180558b2ea63bcf36d8a5418bccc4e44b65ec151f972d5b27f21ae377e3e0550c018723b401d5d71d29f7ad5cf893dca60f7b953fa86f9e9e0b7468e956a62c6c19f29ec66f22f3615d55a6fa9bc4ef27bb6e61d5239a66d129080428d2b779ba08e6c14e1916222d938d654b81a607ecb56f062ef1b13e303044e61e175eeec70e577b2564218e82313cdacac0ed39da42e7130f8b58b3a37a3f1d548e1990b3000000b0148e0f8d994dba069f604cf54f9c1278514b27b319106c02a744f64fba5c71826d713919d67985f09c631812ff1e1db4d3b77d32b152414d0c8fab82511c2a8ec26abeda02133c79b59ed4b1e5fb339b9a2c83cec53e50b1cd6808cd4b77e31fa6c91d4975fd3c82b411f59d998da93021012802c335be7e5c1f8370015749a8db11a18bd2775d1f3b96f9e93d6e95f71052218c97a59b29a4980264a3215523423a55ff435ba6ffeba608ecb34c135900000168000000b023fccff1472477e6e0d5be51e4bd71d0ad1c967a41832088add7fa421aa6b3c53b91df52bbbd88f1ad07463002490f647974c04769e7fc0960c3e63845e121fc3dd8b54cb2101341efd1856253fe4bed4f226c06edb927b479c4744f285f8e879f79dfbee5a11f80e4ea159e6b60209a24a37c69b337cb296a8d566850c0ed5af15c8a15bd1aa6efc102271b7e48e0f21a949ded5f747ed70d7a1449a132f4a79ed9f698e3d9fa811454b0919dfe0d89000000b004bdae4eca7b4970e29be85a626b061a75b9b0a9045129c4b8882033d25c878da8e867363d0b843fa6e36610acf3f01ffaaf0ad9255ebbfb3cf8459b4a64184eab73a7d4aedf08275cb4658eec2c616f77cac54ff6fd3142589780c767035791858c34bfd1d5b5b43f2ba2ddadf7714c2367f618d96d0f5ece8553b2eb8d190ba2e8bb887e93e64ac5f39e15f113748e07c61a059af10ca0158132993e416ca09b3db10fc1123687d69c36c9da4d0c1e00000168000000b0068e86301f4582af17b6db20312a669e0cba844da4ec67c283d775026a57311b8d485d62d8a1401c75aeec6378aecfad0a661eaf2482931420ba578f4eae79bcc7f24bd807e1585edfeeb52baef285c9f196d493772bf6f49b6b1601b9a1bbb60e00261eb48400911851013be88406fa0ac08b74e05e4fb4bf75e95c67f59c238fdd98927915ba496c19ccafdfcad32c0f66b24303e18431d2b40b279c55867e769bc5cf06f901ff10edd7682ae6dead000000b00bfe52b0afc38bea53c2ff7e69adf229050bc6fe771a1abda4c620a8e872b516cc075a2bb85613486fc19ab3e568ef164a20743aa094f11240985376af267fa25c0003d934f3388385eeeb6b8e7479079fef994e6735d4f73ed5ff53134762a0827ce9448f810e204c451fa94c6a6dfb24be20289ef5b2bd1c312212274904e6c91343e3cb5c6459b4d544d8bd9a88631830c79ab2b436a728ec6b127b2b1f1a0483cd47786065caca28e47a1b9eb80200000168000000b01776d13a3609f22999d9527ec0722a1ff96c59610374d5ee3063f696782948f4f26350f8a96d406fd531f6a629577a0cd9de97890322a974bc15a7e8345d23fb5066054a97fab498d418fbc46604bba0a8df7cb0ba2391b17df804de2ad203c494a53f8c2abcc21701bafc233c66695e208c1c980f2d3740a6a675ea577ff4e3e5a5ea6774e5a2d4767842e7112083ee088f5402e9deb940a6597b0995d17761d023190abac508e1ec7178bc5a4f19af000000b0299862262b08b127f9d65d5fce6a98f4167631d0a7fc23842bdc4f150920685a977f4aeefc5a47f85f22aa40e06e806aa97660cfad6c8b39655286ceb0db64b3bf5b9867f4f0d82cf20610feb20ec1de81d1a9954dcf242afd183431dba4b65b367e3c8b6a9532d5f4d27cd4c72c0a1e29e83d1fe084c239f992e4852745c00f6fc8a5b5624a3034a1f71628feb955f801d494e760943ce8941122af322a14cc9891950959e8f8bedb247cf932bbb804", + "txsEffectsHash": "0x03f253bb6987212f264c5616928f66c956c0f948d84017b68e1dddf871942a41", "decodedHeader": { "contentCommitment": { "inHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "outHash": "0xc2db86162c987f9328539ebf11947c30e3846f8bdb7a820aed2bbabd9544b9dc", "txTreeHeight": 2, - "txsEffectsHash": "0x96d6dd6caa42f221143e36451601ea093b69d59d2cf21ef49822ed185f9b8e9e" + "txsEffectsHash": "0x03f253bb6987212f264c5616928f66c956c0f948d84017b68e1dddf871942a41" }, "globalVariables": { "blockNumber": 1, "chainId": 31337, "timestamp": 0, "version": 1, - "coinbase": "0x2c4ed998adb9ea58602c2f521338d85e796983c2", - "feeRecipient": "0x08e3c9234b16ba719d1fa970253ee4631f0204c4dc25b86b46eef390ab581e80" + "coinbase": "0x3763c27097c7679fde3c516b87d7a57fbff2b401", + "feeRecipient": "0x12f0936cd74975821fef2537b6501306af902a7084887216691bce9ac330b88c" }, "lastArchive": { "nextAvailableLeafIndex": 1, - "root": "0x0f045bd8180c4de901e18a10e9393ae42d9ef7928fe6b68568cb48b91d1355a7" + "root": "0x012a86560737adb075e12af8253fb09abf17aa841fb56d180bc89f0d2d473c7f" }, "stateReference": { "l1ToL2MessageTree": { @@ -80,10 +80,6 @@ "root": "0x0a241c83a063083fad29b6c333afcd968f71f8a875544ff1f1f08cae7f770f51" }, "partialStateReference": { - "contractTree": { - "nextAvailableLeafIndex": 4, - "root": "0x0135cf87b15a9f4b3deb2fde9d2c6f75620ae779c6b62f677c42aa70af9a50fd" - }, "noteHashTree": { "nextAvailableLeafIndex": 256, "root": "0x02c672a4d7bd90c4b6ba35bbc9906598862f626554be3cba05de19265a8ece71" @@ -99,8 +95,8 @@ } } }, - "header": "0x0f045bd8180c4de901e18a10e9393ae42d9ef7928fe6b68568cb48b91d1355a700000001000000000000000000000000000000000000000000000000000000000000000296d6dd6caa42f221143e36451601ea093b69d59d2cf21ef49822ed185f9b8e9e0000000000000000000000000000000000000000000000000000000000000000c2db86162c987f9328539ebf11947c30e3846f8bdb7a820aed2bbabd9544b9dc0a241c83a063083fad29b6c333afcd968f71f8a875544ff1f1f08cae7f770f510000001002c672a4d7bd90c4b6ba35bbc9906598862f626554be3cba05de19265a8ece71000001000ed22b14764d5756c4e97521b31e93e21192b98b3bc2e2559e07b1263ce7b1be000001800135cf87b15a9f4b3deb2fde9d2c6f75620ae779c6b62f677c42aa70af9a50fd000000041faf8e36b0fb8fb337acc1c32316e1fcbd0465d53c47a2dd73ebb031042566cb000000c00000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002c4ed998adb9ea58602c2f521338d85e796983c208e3c9234b16ba719d1fa970253ee4631f0204c4dc25b86b46eef390ab581e80", + "header": "0x012a86560737adb075e12af8253fb09abf17aa841fb56d180bc89f0d2d473c7f00000001000000000000000000000000000000000000000000000000000000000000000203f253bb6987212f264c5616928f66c956c0f948d84017b68e1dddf871942a410000000000000000000000000000000000000000000000000000000000000000c2db86162c987f9328539ebf11947c30e3846f8bdb7a820aed2bbabd9544b9dc0a241c83a063083fad29b6c333afcd968f71f8a875544ff1f1f08cae7f770f510000001002c672a4d7bd90c4b6ba35bbc9906598862f626554be3cba05de19265a8ece71000001000ed22b14764d5756c4e97521b31e93e21192b98b3bc2e2559e07b1263ce7b1be000001801faf8e36b0fb8fb337acc1c32316e1fcbd0465d53c47a2dd73ebb031042566cb000000c00000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000003763c27097c7679fde3c516b87d7a57fbff2b40112f0936cd74975821fef2537b6501306af902a7084887216691bce9ac330b88c", "l1ToL2MessagesHash": "0xb213c9c543fce2a66720d26a913fe0d018f72a47ccfe698baafcf4cced343cfd", - "publicInputsHash": "0x286d86eedc3f2ca84f8b763c6aefb535d85a9abc4c623407598493a4f0d7b513" + "publicInputsHash": "0x2b8b852fcab7e9954ad7186123b6e7be38f1d492d618926c7c0fd50ae69a19ca" } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_1.json b/l1-contracts/test/fixtures/mixed_block_1.json index 194eb1d1b89..7d4e34b1f20 100644 --- a/l1-contracts/test/fixtures/mixed_block_1.json +++ b/l1-contracts/test/fixtures/mixed_block_1.json @@ -52,27 +52,27 @@ ] }, "block": { - "archive": "0x17487022538c3227b4b891777c671e7011b13202dd570a112ec43e79eeab3607", - "body": "0x0000001012e5643e26da426570dd999e0e044e5f83d60f3cd813c55059bc0ea0f4a7c9d413b2d2cea949fa0876265cd8eee3a4dce1e243783562ea07e2de537f469f7bf627abb3d4560e786bafd52f77ac52dea36c50419f32386567bd969b0c38e1bd7405d339cecb99fa74bfd631917f965357f0341d8c4dfe6a8f4b621d8df54c82941d560ac24523012499eeca2594f20ce238b7d21b98ad5c638767d70ee05532c2183e6d64e69b005709dfc4771c7ca5981adc54f3e8bd1b00222461ae90e44eda2f1d4572fe0b0b23100a7ea6d4780b25e826e41ca9e71897e010bcb218887b3d036d44eb30a430b5cfc6660270eb5fb7f274689ac73dfa53ba9d0739fe38637f01f7130af8c5888d4c65ea68109a1d58fe8d7d1ae62098857b0a3a3dcd393ef80ed8bcba6eb5e3b4887a32c51c5853b97a5eb59c87c520f36423c6d7be06071821ca1719330de5e3c51a521778b49cbbc1d53f8ed42e0562bf21ed72e8cb9a410b0e82ef5f7276df41353faef675fb408aeb246b6e2f704cab99bf28d1427e7b0fec7b9929c6effdcd045d3fdcec1d1b73faed495444699fab936630d69b519f0bf4f1453db36439419dbfba703b849d1aa5774fe9a5325e5bf3e7cdda9d1f7f2a9c2a035c72fd4a3e383306aff03448f9accc08a2c665837560cec8675fe2512bfaef35a8fb7df08a81001a7fd4903849c0371dedd87f31295f46269c5205dd00000004380000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f00000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000027200000000000000000000000000000000000000000000000000000000000002730000000000000000000000000000000000000000000000000000000000000274000000000000000000000000000000000000000000000000000000000000027500000000000000000000000000000000000000000000000000000000000002760000000000000000000000000000000000000000000000000000000000000277370000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f00000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000371000000000000000000000000000000000000000000000000000000000000037200000000000000000000000000000000000000000000000000000000000003730000000000000000000000000000000000000000000000000000000000000374000000000000000000000000000000000000000000000000000000000000037500000000000000000000000000000000000000000000000000000000000003760200000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000441100000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f0000000000000000000000000000000000000000000000000000000000000659010f3ce73a84170550a89b6327549f153857338cb67690d2d45e2208483cfd1b6f00000000000000000000000000000000000000000000000000000000000011400000000000000000000000000000000000001141000011000000021c000000b0156ef7e198d0ac477bd251338e3d1634241fa3f690038e7ba3ce71035969de15f3d565f48735eaafde8315a1fdef211f897fd579e26ab0a9ec1d67dae90dcea5e87977b0cacf9de21c0eee5e0de9c15ddba33b72908db0cf856c713606172ac30d7377c98c52f8d0d78153b9f0fd194b0b95b922e0d6e7f05784ac2b32b0cc0be8c925b114ed0e1cc1889a8de7fefad22b19c69aef9e37f7313cf1b7f85e8ebca9af757113c660c4401c8871feac4222000000b02e703de97d89a6d9de0e2e52db3a5f6655640bc1deafa21642ec1d09710b73cf9fb49f8a209bd1bcc83eeac46daac9289bb7cd4f11338620842352f30ee229340444a500d9cd1b7fea0b1a9e3e8cebeab7f8793b4588047d0617386effd575f1f0b27876aeb574f41fe8464e927a36380c6adbaee86efa34150dc8516cadf73971b7e8319fdb12472e116952c4a01f8809fa0f212a69bc7a59aecb31785446fdb6c717dbc798daf16ac27651f0dae349000000b005bad2516e877d9654cfc0e50ce0124b390a6e40919025dfb46fe8617645573e11d3cff4e17a0849320fd94b5ffb27e96cf49592933f818c4d8a1177bc14c7c8e4d8e2700678c8149c7605f6e4379b1fab1c4148429f25bf7aae4b28d8524a5238a5c2a95a2f8ec334b39e718f7257061caea22d109fe88e9f4380e22d2576f3420f0478e70dd692957030e005644d5514bd8f489ed3442395388afdea102f3696bcbead48a96c5288c31e21bdb2439a0000021c000000b02a098a1245c2cb63e4b1a6f2b572e1a276f496e73eb7334e720ce401bb06a791370e85ef1b02e4d9ed0b73cc638d3e4d08e158d694ed455adb56cd3b6ff08488c4092a9e3d2b6c9e9e390f97db697b152b23c74d7ebdca2387869d8fe3437f8eced36547cd5d5bf49fa18b24d00848a622aca6082ac01609f08da7885bd619face410d8582c2b0283b61ebce6454c4f70236b9904aec5aace24c756bb35860be5f0382f76bdf70bd983d5b1308c231ab000000b0141cb1b960426793619075b6e91af2c748970fc5d3e5e808f646cd25ea2a4d017b4b92d59f4bd0d07e882d2d271f6c74b4672eb7e62cd93a064d5aaf4195facbfbe04e1042580ac295af97eeda514d84714f03d0d203d3d012c7ecd595d6badf52f37ac3aca11d962711fe36b72118501fd881522cc110ef2637125af9c22b43db6e18ea6ecdf6dba4ffdb4e1f6e7e5e2f5fe346bedc236dce26542ceac8dfee8e88a71b5a0f5c1a4876bf2c2a401a72000000b00a150237add5af3ab0bd6cca6ed8b9d5b1a1b0e5968c6a0d9b7034afa6ac6f0cb79206339ffc5fa1034d93af473f0ca82326c78081a7dd5ecfcd87ef339e25e6cfe29d563ddef39b4da619262682b2bc5c7f3182d22395362d825035c9ba6082d79cd5c1b936d91a27af6d49552990651601a780a8766ec2d2b89466bd90c6199f1adc915746c533acbb85356100f18614fe4951b37a9e985cff9a4b5c89a7a5b06649ababff6754f9f6e2ac45facf760000021c000000b03054c2ab469fbf54b80831f917dfd88530ad4b3f3ea1c75b8a920d57fa488d7a2966c1a3ee24eae0db1576548a399ae5897fe4383fd636e113428802009be90b4919e2efe0313f53b1d41c69597b97424ece1b20e32a5972ad1071bf98c9a54e6efe071ba9754425d533589c8194454b23367fc0a4218bb711cd47a50a9fc52630d12256fcfd47248deee1778d622c801705056d1221d63f87268b54128c178aeada6ae10fa0959123d87fb90b79de8b000000b00ff16f4604021522f335fb332062f35b70a8915973051bd555ff0fe941972917488878918810d93d3209672e0d18f40f85b221d16b49ed0950075829590155993dcceff1ec0d9adc7880b84a49c35b425dd5835819cfdc358904cad92ba3d58282a40ebc164af2c73efb488318dfc92e2dc0fe1e6b815df02d194fe7338ea1eb28e11be885c94a0077163b8cfa811cc92b2c85fd24afc90d46c68980456e2dd5a5f308f8013718fc10315ba71376d022000000b000a1c5230cba8f1c4701369226bd894986d88bd65b73355d169ceee9f8792de5bd9107eb31313b24bfc68d5d3d7d7e2ac9a33d8413400bafacc31caa0d81e5bc4b3bdec30e64de90aebc511336c1e8c2096ddde0b1bca9851d3fa3b9a88109d081d39edcbdd876a7d4a6cbe7b1f045ec2a8d85b84e501ec0ed229f4a15dcfaa7d0c24d5ab7778b3209e4e68183cf726404555aa228f57121ac347fdd38f360c93840d4f279d30df6696bc632643438980000021c000000b0138da2e8a932143b7e2bad1843542c7cc7852225c6a324e855b27ece168bc36363b59cccdad0516cb62225f6cec064616ed6fd17d2b01e2529f9785788e67ab3565e4e89f173b2bcedf0913a878df28ea42c9f55413b41d8ec59232abd2b670c6e268358d449aabc4a6146a16d761b622d20885b5e90efeb5b61a50c7b31297b7598ec7c9cf546c719f2cc9c29a1151607a86267e9803d699e2d400891d13b9379a06ee51dba6d2be23710dce9c29232000000b00d3d54fc1772907cb9f1e4ec4376fa4f2724b53688758e5f2de099a85fd5978c63124ea6cf812bbb27e0d2d84355c49d8e6fe9cac7c8904163a7a33bc0d454b32d1967835b9565f1754444464e414dea4d7861add8c459ff644769a944429f4aafb448d989a5e05f95685dda98cb99c20e2437d8ffc8be1f9cab84f25902a187f45f7956310cb38cc4bc70551b326f472f93fc1cffcf777c1135304f4087071b68a52a3536a20c2b33bddda7424c89e6000000b0122070dd44dde48857057e6d37a997d57b8a6bfad519c8050d82acda690cd343ff197d6d6ce2c312f035a1fb40e99031b8804ea22ffce74a7af0bdc9fa31c86863c37a96e3bc39787740818a9d02f5b3d0a194f705169054f22c51272fd148492e1f3cff435299b4321324d4e7e3c84a1f4f1c8dd13ffcd5821f9998eecfa91c8959020a04b137589004d7e499164e8c0885f312cc427615bc02178eadb10efad58b1f5776c75c507cc32723667b08a90000021c000000b007c59b02039ae1f92477d3fc490e02477c4c49b17fcbbaecff7005df61e5caf5ffa55882f866b69046094c03ea4382b59fc34c2f33d9eefa8fc11d77b6928819a6b769468101b0d4a7751e08bce7b1d2da2598dabc5d17967ff9b1f7851abc7959daae09a84e9b78cb1e57633644c1341412de7b82b4bc12d68f7a3c0cb9621e2602803c8d6f7214f55c4e9c920500ff16fb48e92f887758cd2f9d68b5bc6844a625e110495470bcf8fff2bae8ac150e000000b0195ff628eb3f5dcd4421c7675a06b63fd5064285ad3d7186be6064eb0f093b3a7542624ad788e4318c5b219a26494c75e230ae0c0ecd340c2f1e379f692319c7f2bb030973386cd6e6a9dd5797cd199722735f1eaccf75898bcd8f04a1ce5444b6131d9b86c4d2ec3930fb34c829ecdf14b5ab6531174f6accd033cad6229a03ad9c28c851a318abd3d2bd52488b2ab12892e76f493e9b9fe5b53bd3a9b9735321becf5cb4397baa145eadb64497ef7d000000b0255165d66fab68885e340c460c86f5f7c706a9b1b3c5200996e32177a2f7cba279b12f1afce13d7097190a4cd436a83c2e3b6ca66dcc4e769f4f3c609ae9a9f5eb079db237d4ba937b23a43032293a4208dd58371fe606799ba3a3833fd664162707a4876688d2d7c838f07c632b7de1136e582d36186c7807c47f315b4bc61a74eca26a1fa8523cccbbf6c3bc5bf67117857a5c71c916ed62ebea426b072cef0588e9eae02142a1511e782d1544fd880000021c000000b02f40cbb4d14a3539dc1107c5afa180adaa7cd56cf452f9a1b35ca0696eb5f99e1e179cf46581bda23d61429a902c8805c15150de59f0210c12ecb3521f0719fca8af2b595c65c4748460ef121a3bd4abe22d0b6f0767a3821c2a77eb9bbfb6782c290b370e5efd59c46105d98a20c1ab1d5dca8ac4d99d01486d15e17c44224009b3fb7b4ee07e6ccd3e190da8400b7222d55e395ea7f6618618aa7e350d01c3bff8810ddc32050124df004561bb6eba000000b00b11de15af1d1750f0f6dd8375a7adffb365edb5184e1a312e5238a2954b598ee62e4a2a017c5ed85a72d6ee6d1ac9723f3fd8521e12d8c866f1b017b5cab84469a1c724cd69caca5aedd849f331afbc06c72628cd534b7b9de1fbd5462fc0e851868987a91683eab59c8337f981c8fe1506c94d3c47146f2979815591027b48bb7e15725a1aac43fd25069c92c42a451e66f855514f153d7f4b4afdcba42875245449fe3c2da7cb30c42eb7fe00b0e8000000b00997c7750644ec07ed6e7a355e0be515461aec2fc6ed7c3f39a92201fe35af673e1acc9931ca538e264b0605d8f19a785ed54f767c7ffdaca59ca7c950a781f0e620f2158310e309d2bb73bcee00269f9c29adaa4d61486a51d7dbaa95538bf0db47107e4da3a253ca30919d5278d8d0179db4ef28a11fca4837557b7e02ceca85bceee33e8c2b0a7b339bdb2649eee70cc81edfe7bb26575b2ead15c82ed7692a8658425226f2e5147a00fb598142b50000021c000000b0243d77d255022d810e154a33c440cc3dec3bbc65957995f132aef376435c5a46f04d520cf8a3f86bbf2f7988dd52049792a0373d842be6eb380c5c943cf915ad7d942a9a80abf56bcf5e9145fa89773121d5f800d3bb2e1f75546cbe89c84596ba0e8169ed6e4b10e3a908376714c6710d3b989a2c7098ade3252d9a4d8172a965bc5bb27dfe54fa6a467c7e2034701c0b2ffafe6b32ce22f220fb72cd425e2a0bc1e52a9e70842fce1ec95ee79b8e91000000b00a30e3e8eccf8d738606796e3eb72f8a92398655a6a72a9a4935639db0512fe8ee4bfc0a5ba980ef9fef4cdc48df4e14dcbee08909afef6fc48b399651559395f797b2a0d4841448fe8cc4410a2e315def3f1b2de4f42eb7656c2429b737cb2fdacc7155499a49e139ec1b726f12621b0f33c365d0e22438b15351adf84a65d6d1069bbe06a245818cb06b4f1a4cbc242a08cd05b2a96aa313b924b32d04a8df0e6f3bcb1004ca0909acd4220c9a00cc000000b02a1241423788f9b1b192b6f56174a0381c8b4fb839790dbd6513eb8bc2413319e5e1e6585d3d2a5db2812a666b310a62d4bb5d55d53948d26702f4287c606ad6f0c330dabe6f685979b578c49322d5eb6511b37b0b21cca812deb17eabb7eee865cdd2cae8f0791aa2ef199213d02a3002ebc46bb3b489f705a5599db0a49d64c83b84bb033aee1e684a4be427570028097cd135abaded10be9051c616224ab0fb383abcaf00e8ed7c705e86cce900840000021c000000b01f5f3e839df2a20b7debe1a19c4bf7edf5f8984ab05e19878ce1935e3876347be08405e1bcc18fcc1d99ccee6dbb19fb3b121b2042e570a432828c99afacad517439e7b44b20ad521ef4ff1474c395da07e3b4ceab373ba6d61ebc3d2192ff5e1b57ba4be6fab396388b39a81917cf9708a9d21f89ee3862e5ed3be64ed6229937cc10477f4bd21c5c7efbb117cef3a52bc2f4784c1d4a17a341a1dd93f6b8ff577bda2e1f1a0487fe8253950296754f000000b01a5652f8224e3e326b00f2a28a57befa267be3b85d5956357e6c580085f95db681bc8f67632dd8b4eb13b05bddd97ad7840613c72f31ea6984141fac0399d67c863c6137f998b9ede5ad5bae79eb1d0572778789b054c85b72090d7913288f39004bc67e6876f8288a921c314f6803ad1cb0a45f57adb8ff3fa54666f4e660d8243270b8ff24da60543f8d06184060b80986dc8fb54746756219532800f98a4ebbeec381666db6cdb9a76b78b069656c000000b02274ab167bc88b1b6c0a5b1c188558b59a40ca6d512e581f31488f1fef0df8657a8943b662605ab8ca2c0d2e635c3219ac8f2eae05e7ff83b263776c54447cf6313222aac59ae21f9929158bf93bd66747492b3f660d6196b0d73e353168f44cc20df5750ce4607d8fc9b31d9800678b2b9ce7ce4f08b822e696ec9a6d19627f7bc3943f95e8392a4c9dd85cebe3eb231855809a595bf9b06c671f08a3fc46ffdade54d36a6caefed7264a03da9d7d2600000fa400000168000000b02e74f55e874ae4075e437344895cd0e94daec8abd33ed6135c466291c2565da09a30eb596bbb8f33f03a1c02a3e2b8205e2647c784c5c8a9da7aaa0aff93ae470586b13de0a7b9a5474cb3cd37895111b2d42e7450c12a4fad724c546d11e884ad57aa918de78812394226072d40a27e262841146355b97c3e7f7947862d8e411288499beaa62102ff98807c7be9e21e2bc91cd7b03b09ec8565893f4a7b7ef726b2bc2b07a30d0703b456b6a06b909b000000b02f457eb53b46b6d62f456ef317edc4aecbd810725a0cc7a2f8fa614a8b0876e713a5a413ac3ea084c50a537b8d12e295fe4bd31522dc53ba2f19d43facad322aa5b39de43da06392bd1777c6c4b4b798adadb3d887d40b83c0dd86f3cae8c6ecf7132cb069e5c90343ada011d93942ff11af24164d24fb281fd879857fba926486549e0229c9da56d91d0ec4d66c12c815afc04f7b9502c8d7b8f3f4c066d426a9f63d1c1795dfb1bc341272f1769c4c00000168000000b01821c345f41e2ce547b3fe924cda82b069f4e8753639c9f74deb2e3d1066115ec5da118dddceb18a83a16cd784695198aafa7149acc7919b7a313e8c8a1037bdc44004e6895e478440ad03905e21e313a494fa46824de03884015bb691bd9abe0588e33cb4d644ded82b68613b1b5f1523ad547e0aa1d3f0316da99c8b2e82c9e0eb345780719718568ed29f2dff8389199af5e00d6770c90028b30b07bd516d51c1126411a4ace099e5a079f872b0fc000000b006e7d861cc676559b5d26f8855ffe0ff43d81c1ec01266fa326d325ad7effc99d83d2f5e090ce57068c0d7b1cde209c67398c63c490396792d41450888ccb187e0712658243adbf60cd9261cf1b17620ae95ed1f2dac2c8c0e1cdc7c481c5a4a7f209251790c6eaafb8c57f0b2085d5c296fa9ace7b0d44af429492d369dcbd8763cb28ae32341040c99702fb58fee30110544b56ef9146d33c29f5576fa288477075f5de4ebf0e908aa012a6d30bcdb00000168000000b0165da5d25963676b228b717ff4300e33c9fb4aeadd81424057cfaa5cc35adcff3631d678e81a10283b78d4c77e9976852c716fa8526e1b390a084fd6ebbcddea9a25f8eaccfad22ffd99289889eafb47ec11f90355727e737dd33d21cc08c651753e184d22b903e1998aa7313890e79d09c66d498ddc74bafdc153dbb06d5f1b420566118acbac40829a202082d86f7e24918b5efa8959c809271379f56ef72e96a0a7b480a2b5038ec71b6d511f3e86000000b00d67de64657b7705c01c36b506e634d0b96d7e8b5738285c13989dc0eea95ba32b7a5606bb934a751ab9442c6ce05a220b69843b7e9782df7a9db0f733e511573ad2c3b095139cf7b722f6fc9890391ae45487ad4dd44a9114f2b02f7750afa568c966c70f2ff3b4cd09dccaf3c56dc81a79f6d8c6fd8e04dcdae61a26a5b82e136c3dda2e1fdcaf244678bc253c9525131e7995cbab494daafa8427d9995d0bf3f98203dd77bb9c9b9fadffd38464be00000168000000b02502f8875593060d23ff8226a4c3a7ce3ea947dee20c3658dedb6b45d75d3588a231aeb8fdf8c307c653497bb28a157ac33082a1fe6ffa2acbe30192c68888d716e8e2e4d3ee5deb0ab183e290f3cf58930e5f54dfcafc33edd92b49b44d97cce55516550d7c2acd2c45c4815d062f27290bd0cbd8ab6ee6d2a13cf4471e16127c3271c5a9d8ef296d4015a17cb4ecdc29f49bc7b5ac1eae69b6970f938cbe05e9a519df9c0e001731e6dba6038c0291000000b0222840c7fc5fcb864ae6065c4c2f515770b4de93143d94b64a8b21fc52f149d54d5f571cba43943a78e8e2b8abf5f97728a368af0a9120fef8db064850d664b28d9d0d4840974550570faaf83f0d5e63684913a3024e1aae2051c9cd063320ae08cd12b943751929b3284921f585465c13043395c9f140e10172d1400525aa30780a4f9e1d44ddd2064e285e25f0d1da169843ec0bc3c3d985caced5387b49027456454fd78fb6bbe9a215031271934900000168000000b02504cbab85ecbe5e44cdf35db50d2dba847c16a403c266e91ce91db5c82fe4c625acee63a3d293936036bebf6b3a48c1586e312d66b659058d94896203aae6151e7f2cdaa9e15925388bf3ed502765d277d7f103d965dd4f8b07704960449f94491a8955f2c3e1a2544b4e2de8330b4713a142bfd030c12b02f07050770905df5a4a1aa2f446de70f635dd799aa6689714f3e71b46c33c6313445a2978ef8b3d5a170412ccb4c15451cc23bb30274cc5000000b01e0a9e1557f7e038f14869926e33f5833b7d90a004eeb4767083b86cc77a0c5a1df1cb458c2863f5495aca4c98d5ab4357cac4e5c495463374b6b82e86249aa048c8eba9ad5924f8afc61aadf6ac82b860539969f09ca62613696aa91c96b5eaf60e2c3480704f0d5f90102d02b050681776825a14e2d61360e6b900c09ad40e92a91f0e08c240b4f7c964d0afdede5825c6caecb09b85a02bdf95e0a7d044670bbf5b541becc0ff6853485fc87cd98a00000168000000b02dd505c110f248420061bf547f7d52cea42a32d87ee06a66242b0a5ae8faf7ff21d204045af4b66ba68a4518d9f764cc56c791a61232bc02a877c5a7e828376a0d74c06210e6ca7fd319820b6ce4d0ff4fdc539564611d08f724ef0c9b805c81fff0e8222c62f2f2aeb6e95aa94259d5016d774721281af0abe1287ed12f6e6b46918ca734a590a6074d8180e506ac9d28638cc01807e32d84d2b30a98322597de8f3a6c770c23283c9fb58ddab17f4d000000b00894f45367c6d343c4835bec6a3cd0473357bdd1e9fe8231c4b1ca507cdae4f4d60f1c15dc15b3c9401cbf72d1d22956d332e92b074a151f7c2417b403bed3e7d85f757e7eeb73e82a22b12ef55abc5ea2e3e59c745e655a55a1c564a7d85dc039d86c88d37cb6d81a613a4c880cb4762ceddda1c322ea035006bbe564c0607b8fd49ba03cd431fef3f19677e543756f1dcb164b61e764ef59bba18d6092d077f6acedbe73c3f5c6c7477023aa0fc51900000168000000b0166666f36b9cb2fbca469145de80814dae532156feaba766db94daf7f4e8da61adef57d2bfd66c96e427f156d80c68c05ce28aa06a96de7be34cbbbe6e1523104070121266de0b7f829dac814aa551f0f883e26feb0cd1acfb3e118eea2f2590c3e51c887f60db4a8dca0d5beb8bd4a52d114d9eaf57e1405c7d9ac5f56bad50a6bca38b70e64b25296b077d044647a20301b7fec717e3f43266ff992ed6ed119ef789daeda6561bea8ed6f78c8bf56c000000b02ab7c3c1df06867e99c47ab2fa5b6602bb455b47fc1f81c48fa2fff893218e6f40d3a0edb2a628a3954f17b4de96998f4cad763ed128a390d9d21b5176cb8f2b4d6330306d682ac775915fd90eac34cf76f17222ea41b9d86ae2b4c0a76d102c9993919bfbf0cb2e4de72af62b828c720ab8e1bbac62b15f07f0556ba3f28310ca2b3013d4b5a89fc81bfaa5a0dda311074aafa6940fbebb18eb8d4f146ad2bf726e606afc0db4cdf68711abc5e6504900000168000000b00459843125fd5cfb60ca6cc90d7f1fc63629074092fd168d44861a03647d40034f94caa19cac1ac545dd3ef685731b194d6a7db884ad03407cbc0f901875eb60ba74d49ef453bf31944482f7b40f8135d983937cf4f779d0d193dba883e2b7cd7abd7aa040947735f2aa5a84d5320d930bd7b150151940a8159c35dba72885af12884547f30c13f2e5728bb6c24a94970fd7347547d50235353266aa9c135d1057f3e3251bad7c49aea391dc131367b2000000b01793788d2ddc6dcfc81ac915e375d776aae3cd91d206fc9fe778ce6966515fcb6a86f75e175c018a3130ef9b9d96c46f0467e4677ab43c5c378d8be49d71dac34678c766b115c9e226233caeb6d4ab0550458931616ce65bb423e4ac7099bc7a81265149efca0e15cc69108ffdef7ef60987867b92ecd973c122c4f24297698bf45a8d1da3635b521e240fbe5aedd37a14d8929ce23e523a63885a90e979407d0b0dbb6d7c765f3889a11126f849a0c600000168000000b0025d153ac41a0a16c3a4e29ffd0529df94c3ad34a84fddfde15330c5ac4a4ddc7870f4498af6e8bc395edb697684bf9b2207f69b79e5eabe21acec4280434687e1a76cbdd4944a86092f6b620567d6f95df525309eb7eaf7eed747c57da7f9a3f8526c9e0c88edeb5df4db1b7f16522a0bc69f651ea7ecb50fa05830e05fdbb66dc8f28f5fe6af80e541a0ae98d80370073740c0061e4b504c7fd50423412ba8fbc65a66c0f80da0e6a49703514a013f000000b022f57e3739dc3e1128f672ea0dda488689e4f0ed80f697efefae6160f60be8ca87eac6dc1129d63825b37cec171de19d0223925da0a7dbbd8facb44256aa58fa614de68481a3a83ee1d6128d4c24f3c616fb40618df35f5d876d6d5c4537dea41fd7829445eb1cc90cffd0078ae068ea10327400757411fd6bde433f63f75ef849facbf62e1e8d36674713eb2a50ce7d06996890e9492f396e89a494d195cf0fc1a6d89ee123e1eec90c667b81e4671800000168000000b0109b416055d26f395833d8632f165395055ecbf7b9b17a3c994fb7a9c6a321cbdbcad2781e91e2069d1bf855db15047b579c3fac68b8847ed99ef991b47d044e53e0991ea77d0fb18a3f67fc7893958780f8c3cace4a31e6b7df74198703dced6b6b189e2bf9bce6a01811644b51bca0258ee94a47d5e6beab595673898168b30735f4ac8adcb387baefd80c68a29719138e4a764e1c77f6bbe8fbc50a667049327f3028561f7e797552db6d951bf2b6000000b021f927f8cbcc2545aa5baa84e1383d03492298871cc18f3fff2750decc1ad9665b981ebc48d4d811b7c3b13dafa74acf5b015115597b5a19fc94e8cdc10a7cfa979d1fd5908c548362636597d292ac7a4deb73edc35da2185de4876935e42a9d0a977d1188703045a37866263ad62aac2f8402dc4581d5df0fcd46acb53a10605f8e5a9f54811cfd9e46c77f0ababd3a0c0b332b6ef5dcea6bb1d4b914304f3e52645380de052f396e2ca92ddbcc593d00000168000000b005bee4a31ad70291c4b5aee56ee6758db8478b3add450d3fd66877f24e4ac6aee38d1a76e986f4a8fa71bd96db122ca250f0740a2d367ca055ea1db9c37a7a1ac06bb2af58737cc6db647b564b635ad261be2335a7f6b70caad5bf03dfe055660a6d5a927de4fe40f9ad8feee7f7b7e9202b6ba74d0dcd7c6a7580cd5736559f61ce5e3461c6badd7cc71622ddde6109091200abaf30b6cde42b592d6a5045dc9b0622006736cc5156c756a980a2c6aa000000b022d9dbf23914d39b3d11d0d9a1d31075ba1404ff5b7ae90ed00e769243c1b674c1a31a060a82b963019199565d25d7feaa0294caa54f60bd3ec945a601a3b6e4d1a10e5b1a022199ffbdc341e4c4f7af0dad791bb1ca5101b6808eb3835e77981f681c47b24ddcf63939c44b497fe201070c3f28db60f4aff78fb3c65557fc7afd65c1a82bb266e906442456a217de280d7b82074e23ba294cbbfc0b51ae12e3f2bbd21a73672432e3a708e308db9dab380000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b7370000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b60200000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000481100000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006990129168fcfe5274f558a5417b7d6529443729da9a806ebe13e3875a1325062ba4c00000000000000000000000000000000000000000000000000000000000011800000000000000000000000000000000000001181000011000000021c000000b029ff470af339a233c01b75d57b8afb9fdfceaf8325aeb470c4f78b5243427c64025f61e7d698834f71708aa4affe80c7cc193288708803823cb2e4e82d702e22f699c374c54fa5edfa1689b43e6b1d75657945328068e99869a31f7f53f6b5c58b124d8d1fff86dd573374a74e087f8a2bfa55924d3dacb1e0e308c377846484f31727db942214c6c4cc3c3cce02e77f18b947e5b497375da280356ae193de7fc8492d5c655ab05f617fbcab89b511c8000000b01530a457af4010eb96775c49f55e42258b00e3a4a7ec4707112d5662d6a8c45afa0f1b03bfa54fbbe75fbff201b404a8e5a7f2c2ce9eed5740f55dc65e3d0de6b5950738b5c818c982ef079a6c51c1dd6b8a609f52134fd9c5f1e2a785e5881c4d4b1ee551302dfe442734db7851dec02166a62f1f3473e0e222b01a47aa69f9aebe3490d1947d09c78f361683c5e5be2cd5088c01d1db34e3c4f21654924b13539c9a41cd279092073be04068f8d5e3000000b0210fbde139cee973acdc441a63ff155c06ca0653e1e86ec57b1981e954cef5bde85fd648912020634b8b505f55295668ecb9a109286786a3e6ba39946b7a8601b1cffd236c172628fcc38054cb193f668e7fd53a5a7cf2781fad752b40da7d7786870487dd93d7e0b2284eb1362972a21b13ca64f4586722c1398878c63645dd86b58face22d26bcac38ede43f05ff95254c560666a36a932d653035745e8149885f58adee3f5714098d974f2ac555660000021c000000b00bb94894ce04b7e73c57d4fdf581f0ff23e146c649c6f813b758f88bb13fcee4bbf1eaa450c554d61d28266bb5f1e5a0270243efafc5b586938a0f9fa442183c10b3d3ac6a67b9dcda97d46a78a55d6e8ef84e81a2bffe4b467cfe28640be9d9a4a2c93c0a5cbad2fbd2f51c1700f0cd1b837a35cb4ab414b643809e609496f5b829a4c7831b331536c8ee8d760e610d016c541568c97de2e7e981236d7c51539245886d3e4a71b93ad56d979845360f000000b0197fb0299157d50c0b265659d56301cc979b30aa121ea487645636acf97295a93bdcff70a14a604acc7430d69c2743c67bd8c8bf1473048de2eff215cb23ece82e7321608397792a835b310862b6f5e55c8b17014338832daf5872631fbf7991d8df9c04b9042971f89ea05369ec4f7d00eae8bb2141ccdd8c1d63780b5ddef4e0582d7b11fa932d7c2ba7d7ebdcd64026202d16acbce6650e80547037750c4905ec8b6ac91017a40cfc348c1b6b7155000000b01bc8ba525c7413d8fa2b83be84d4cd993f1665901321abb6c3445091b5050be0a6a7a1e4767bc7faa874d7c93472b9d7a6e8493d8c38c5cac460e5467431c20b9aa3cc6e60ddaed8c208bc285211dbc4d187e2cdd227ebb6f5373355ab6766fadf286a2f8cb06851d5add346bcce3668292c8910ff2a0651db149e4db522c03fa4eaa558139382cd5880046ada8fca3929f7707cfaea5620f0f024ed745f1cd9cd19eea017e2d64169188592f775b1310000021c000000b02debab64aed9bb6cfd92542f2d16adc28408790534c5ff3d64dd4a6e5b98bf7155721b84512f4e40819d2d41b3c0c91e38d0770bc7878d5c291f3c4eac83c166e86d13436f96c8540d2cc150ec6bbf840a3b26baf8abf40ee5b8b2f7e3705860206956d28ea7d399b820400d1fc55aa33004c5dc5a8f3c23f68d42c8c9704637013ad30777ba867b7fd74758fabf90ff1220e5e6a99e001652497ce3356a970ca7441aa90045001fb3adf760a80f5517000000b0304578a608199de21aaf531b242df2b9f775aac0dd0964aea0224460bcaa00ea17db449f729a2af6524e888baf99de07fd2e01da07d3e6508414385f0b94f88021fc4ddc323c605997ec0d51b5fdd02585df7c13a5a08f5f2da7fab3855ec1904b9e836510788fdc8ad1629493a5730d270d35b1dbfcc1114f5d31163a902c546fbaa258852d03886862c963d446d1562a247e48d4981047c2bcfc62fbcafe341f000f2ec8922535dbc2028a11e69050000000b013c9e8c54b0062b9397346f485146eca129b683d3e29ee6878a52c12fdfe9e44e86e612a217d95d555c0b46e1e4280491642022305c773f881b0a5522451f82ce684b49fe335862fba67543cd44dd26276d8be419c9bc65b4e447617bd2b3689cb8865d32853b322b18b604583f9f90022881629007cd9d4b90c980eeae4badb7888d2a244267be0597d15ff2c8a51f124b3e8bbadf0b24ff2c0ce6c99209bb3a1a614a61b4fa0e86804a3c1cf15f43a0000021c000000b00d2df21ebd9585fb6e9e948f21255f3ef0df7572c02056596450f68cba9f4275d319524a1beef6105354464568c0734836197302e1f27821bea3144318e233dcc51cd4d1403250a2eedb994517e2d07c9b716006fe64e0bfafb5f9d186a57b7fd3fa6fa048839c9522b55c4c1adb1b2e0699a27380ff6ee736e1c1af2881b8113dc11a5f7c9ba97d5f6e7091d148e5e619ec39228eb80bebeda894450d7747805e2784439c968b13695d217a37100a83000000b02c352f794edde6d62de27f27649694ab259760478ffd61a002be7afed4d38ddc99222fb69541b1b0c5beffbc111f7aa8195b7bb7964b2e87a4d648c4852b2cb743ba7762d1bbf49cdf71c3dd685c676839353e9a86a57390bffe1262a66ace1f3a98a1570b94f0339048b8b7a7cf67d906b3fdcc226021bc4577b3a1d14c01d8bb4054fe05ab5f1f314ab367572675232e53434aeefe9a37de1112e259ed0c482976e4a93163d6dad256001c2c8870f5000000b016631cc31a7d12a09395b6ef087faa26bf0b83e5feede71a6dfd8e15cb06eb8338b9aa211e0f6c6ff158b2c098419ac38f8db7cb747636dab269c12ea5555417548cb3c88befb21b4a8f36da387da86231363904fd844bb8a4e08ea7fa864b59620c2114dbc563a4e008e45b7908abe5044d542268fc23bc7ec3d3f8b4e60564b0bbfd29dbc8b35d8c13e9d639614a7d0096216b27dda5d804135938806666e1da059c41596ff8614f5000c61451046a0000021c000000b01df5e505d8291947966dab52e0d6f3e473916e89cbf1e22d52cd40daf9b0961ab18e629435706a7eed130b4f26b8b79fe7033f4335f0db4a94d0ec88312255e8b57e395edf17757683b5db13bfef62dcb7d108e4151ce00d7cbf1eaa518c61a4f559a0a3ac52b3ab649ab56670fe292d0c0b8ae558457f0123eff9553d7de4afd2711c4f6e570f5410ce6e39b938afc82c6fea153c9063960989e7b9672eaff7521aab804df88e3ccd8fda0ebb3e21e4000000b029f5623f6e8134afe1a3b8c07fb671891d40f9c21614ff8d74c39175621924b85216498e5c50a38b16a74fb61473d485048cfc271a377977a3344a1acd30dd7757eaa1cce0ca690a17cfedfa89b2e2382054dfb6230b6d4007aef5d9a1ebad7a2b5be893af6f9e62781446124b2b5b7319a659824690e300223c8d26cc5c0e58c00a1082fb970a20e7859d5985da1ef32a6dce14d33ee532c0c6ae8f3cfffb0310e4d6f9c7a5d561b2d3e506b97cf0a0000000b029485bdb314bdb1d50f8b85725d29f8fc6fb9dc1873080dc060de95f1de664832cd32ded07a26a07ebe0da2657adc9219f7e3b1f64ee3d056e678f3b3d51c40ffc9443f4ee47e992bc91ccbd47b19bf1b70e54c0f10d34a611046dbdb919312e47070839c71a752d3c634510151932922bbfa653fdb33e982e3c8f132c4f1f781a81af432e94fdb80b0e161789d13cde175ba1a91212c8e90388e4d166095e6b92594862144f8143f678918082fe155d0000021c000000b002d2e86c27e308f08704cf1f9f67e0dc32bc060dddb9a594945b6995d8c158844d135e3fadd4ffde05364d09de9008ca3e88a69cd2d066810d7a4810160f0574e444de2195f6034fffb6b04ab13f2da9b4802a4974be0ea65a76bdd88669836aad80a0c79b5f5ac594d9db4f996398920894cf79662fd0d674bd7f662dba48a19d4e23a88c2653a8229752c524594cb828acfd1613e8e49591178036a3c44aa57325e05c0b862a292314c36b5e50813b000000b0125a4d33ee508a9f46579af5b50d6f6dd0da28aeef00636f7330dedd1c6d41db3093166b2acdcb53fa3f37646269868355f2f17b3ee531b6adda4fae42e64930ef9f1d0dc07ca336694b23f9b22612aa6e6a494c9d559799d1e08d144360625c93d35dbfbb789c2729fd53110677131625547e0f26e3333d378a39918711d7f94081a1875b90a354f07cf683f47ae8571114eb5245a364e19501fcbdba6fb566329fcaca7a4f3ce138eb1c5cd678b5fe000000b0248a01f28cc2749eab9188da0eca7ea55af5a7dc27bef95a13dc92a7e89d70071075e8d7887f9958c6a0591bbc336e786304dc840a19944ecd3a69a8ccc19b2a8fb71fa0a82bc3ba6c638ece5343e0b0c5079aa3b3c058833a52afc36ecf44b7b8e7d3a037108853865eaac498a30ea225b6a3d7d2fcfd3cfdd45d1bf01b86ebf67acc168b7c81fe4c7e0d1ab176407302156ccec310512a7e6c69ef6de0a921d4997fd15df8c234d5c6ad1d3923c8430000021c000000b005ee93a8b015a2009541e2381f032c7eb258884dd514cb7876b51e9412eae82d68067990b35b0c35bace49206a3dec25a5a5cffff938a0eba6ec3e3b5484e4bc5f971b79d1bb2fe68ddf63c5e91cf79455e255ca050dae380ab321a4ef1ff7124b262ac4825fa16e4f342b540ca9d5ac00dec75469cfc35ab5e71dba98618906401bffb0f5f446018c566efb6a12673d152552ebfbe55594929a75966b5af8be794a659292ce736dcc4ad51d15d45521000000b018c10bfd3645b65f838c8575859f3d1b127026031670685a06287a76e45477bd5debef359bd902e736fba47b3994209cca028f63ab42e6ccbb721c37972fff9b17c7331c52725ec4a299688084fe5896cde3a39397a15b9d1ffd3ee637d3f79b0f534acb68cb32dc35e9708064b108e5152a282137ab64c57f7e7d127f5689a5ae91ddaf6ebd6828bef866fdfe6fa65e0e065ae60c2907bfc687fc5819338628a83aa81ffef0313621abf1c4d66113fd000000b002f554f6a03300afebf14434a268df25a58322b279ad53863561784a2b6458c2894c91a598a119ac00f8dc5c7915a7326e2ee021b2f3bc78f13527aa9d677c3126d6c8f663a268377d7de99d7484f69a64a11b7c8db7c0f60cb8c36239c886486e7c6aba47f76177a01659345f97a26417f6e0dd52a1767d985a965fc97bd83e8e3f50c302f45aa0707324653deadea00a7cb8f79bb1f44d54e8621be33aca2aa5356049de600963b6a7c69bafbf17190000021c000000b0300d819b74a8a2e66be7edea16f40b7c02ec694dcf7f2d8ca28fab351d3bd7edacb8d0da97a556421f7b2d2bc0991b71413d3e38534cc0ae2dedabb2cf78952a88561c0e6a089ffb126cb60d2d4aedd7c4c43311c3e1cc223d6f88d95562eef376a5321dc3102a584f38373d80eff2040694fdd54ee93fd9a6b274fb83c3c49ae5634a8d79f01292a18631d046e043f42a7a4ee9b84018eccb2cfa75b2bd2c1ef4009c4545ff0cb737fdff55e49dd99a000000b02abafa40e07c1ca19300c6f89cf6fa5b96c9fa603e2c3d197f9b0496c1100b9d52ed3958b1c087291684015c2dbe75c05338bd6bbb550f03b882b6d8d592e8dc5d91858fb653e948aba26d1ac7f8879e8c25670c3851501abb2e1d52eccc3c5770c90f25ae659aaaed6c49ee1865d3d1233a68bf786fa5f617303eb551b7d784c4d3f39fb2b3b71858e82d2689ce0907053489b48b19b9e25dbc51dbd2ced7f784f25fff3dce3c14a9025efc0ebe4639000000b02b2d9d78aa1656235f67eac8362c8112711fa3b6052907895c901af7d140ec61a68b2981f78c37e65fda8ec784724459e34b6fff2f9043c819b96888fd0c574fe3e2f185dbde5154adde36981252db53f8117ab264628cfc77f41be2959548ab87680bc9b6a1973baf528f63d3cde1a1236b63e71199d197906cbea9a758959e4d5da3b73d8cabe1ac579e71b508a36c1eac8c835fdd2dbe720282cac8d4989edf59b28314c131ff4fb4750871ffa11900000fa400000168000000b0060745ed826f680a97c26937e257670a4b019c2bd39d85c964f81972c5ac3e1c986cfd7565e290e6f2250ad1ad2669659749d9753c12f1595bd1396002663c58499492fb16268ad49529cb59447f7cf6f560e4bea83463937597be747572a5b9650f0cff64bd6a2a32b05324b565c5272a9d1d2a65a41b27f68f73804a47bff87396924775b8c08aab10020e8d9b4fb82c267c4db3104c914189395eca2fd4a62efc4dbfe3dd11313911ccfe869502ca000000b01f6d2bc8df0708d18fe874969421c41d4cd60236e78f6621919ee15a11596e579b5906110923e949cdee8446121f1f2ac6d731f3b0cae22da83b7eeffda4b41d70fb166dc475ce9060b61b41805b0ed787f9f8e6d97ae720d8a37042527c9793e3de02bd163489234e943b496ef7876f2b0b208320ac57354102b9040346d049399d23ba6b27795126da6cf56564f4b22a1e4eb4f3e49faa22f6b56c94ba9472c4044d73a6d85efdbab694ecafe465e100000168000000b00dd7f62c3dc151db7e8bf7e877a46dab2943ce59eef04d284aadb6b7b84f7a2c5ebaa85ace43a27dc6bcbc8c8edab517de6fc7e78bb40deb3c366cad092d40457ab2dad3184835e4d1c2f36f2b7c1444418f799391a94e4ec1673b92d5329491b5d90e2122b64e7eece7a77264c302ba20031995ab485665de8e37ecd4f93d8b80f400a590857af18fe0ada5444e0cb30b67c8d23b2542d54c96359f1d2279d8b61679fb1f7dbcaf69551b4c38c4752a000000b008bd6297050a8755d008302ceaf4b59c435c0d1bdb61f185868bf8f3e9ebe7969f31a67dd97f25107ef6ccbea0e4db671559126e9aca2aa205ce0c95315812b140eb750871338d47a604b00c7b69e6e6c9431a6474e6768b713b2ac7c43c632fd5c35de5cf22d5972e9f6afe477dd09f1a0e1984881baa1a8816124c9ac38dc9fe04851ef52fbb1c95a3425eb8802834240d0f2bb41625de05c69173ec5f03952a8b549c7f30beca6b50fcb7358fca5900000168000000b02f79d55e4626bace308344b7573bbbc07d0a35202336c3057bf48aeafdebcf6d75ea2ee7006b1ae1829f636f1e2c7cdb45ea912f7e8afea8987266463b26335070bef5fdbafae7efc21df2dd66152be7cae26c8699cf277b3421081f757e2e686b9b357e6b6bdff9d80a61641f419a140e4960adff16175afde9150633baa3950e9bb35567bb69d57ed5694f3ec1ec9510128fee1da364d154d5900579a470459a349f4d70f9c09fab0a19683a0548cb000000b0297a77160c3c322aaccba3c10aa4cbaf985fd823e99170d22294f172cb8024dd11f430434521db5f4e860af23711c4be315fd853822f1e7e4da42faa94399d63f60600fb8e8b494606d201bc24cd95b67cf63bf5ed7fe17292058b6ac635fce749379397ddda177f9bff32a569796ef6225f9639a41b0991d6d9408cd6ab3ddc9b082eff65b0300efcc20fc513cd96b303ef9fa262bbee7fb48eccd349a809c978e28c0ca1c44899cbbc8cfd7f6924a800000168000000b00c6fd167e6b96cf240958d753fc6022c1bfec6b5129565260d1ffa9712579e0a4245344a8274e9098836d65c049a70ca6a594f84fd3e7eb68a0671189481d0d591f6d8bbfa9af725f1bb12ad6d36aaa46db2094ef4a08f0705d066c78a372875862e2a863603db442a7b8378e960bd0c04fe4a0edabd483672df8e1baf11397ec04b7eb73159c5c38e6d19b65398de262839e30c50285ee367328788504a1daad79c84787af94377ee214313aaf48208000000b01650270a0bf39922ca13530465e145bc633e253c5bd91e625b95441a60e8033439637a73be41b239d4678d90bbb9d902781659d131c8910255adf858b0b5d8d3ca679f6c327758ba29e8ab525d61be761cd1d6cefa7452ec810e0a5feeed9916f7d4eb0460282f1abcd41af6e0bc05241b4c6d2db20de209063c7d2179bdb7f68749d999a643ab56fac780ce130d6dca2ace93c66a7e407652a337349f8ff66112d8c9f6c28bac5a0e2dc2d2cf2f399d00000168000000b0243bce4f21427524e188a88055c5520a545689d13aa33b01c05704d933879f7b26925d60b594a7e2a4d9d9eed0370fde137c11aaaf82a7811750ea4f477ccd4befa74025c9bb262ea1933d52ef1b0def63200b0d3d81bd56e0c86dc16964d63686b3020e2b60e06800dad04ddbcafc0c2c0a630f600059c1a6e961e4cb5be9c5b65e3623e7e4b64f8fc592ef14236706122f44ef066de3f1bb4234f98090c735ddf679401091c6f313f462a2728143b0000000b02070ee8df59f226517c736101cf8c5478d45f9fad435df2c477c2ef55c4061734fc99a117db2badea1939fed8c066c37054e196e63d06e289b7002019f061c8bad57dde2645046514e476b96c4dc80adec24aa6d85ed336afb7329558e55d6902cf3432ee37d4337d186e0f4a5b350ce29a6d0718529d7f524e001fd6c51ef611ccc59b2b0ac89b675c3574cdc85f4fc27cbd57ee4e6e2cbd4efbde6f1c6144ec501d6f101e220909b028d1819c2fe4900000168000000b02d24237dbbd3eb5fae97b87c806a44a8341567cf954810420cd8c5258effb6d6d947f2c06b3540dcbedd4f265e7a3040ddbcdf9f35bf6ae21e1645961a1fe16d34f795d4832d266e06220bee1dc986ad08f9bf938d3899c26e9270bdb72f471f149a509eaec6ac4310db29417643972312a5c50ed09ba30980f51a6534829bcde1e48b150f4d3f282ae1de4034a8270d2ff72fceecd56606f0c5cae7fe5de8e0ec594ddd392def05ac06074fc6edff79000000b0140909916933e594806340bc054c548dc5545ad41d6335c4ac6fd4664ac14865d08cbcccd7020ce9a66937d6f24b5e585188939b4180e2787f2d0d40067ad98aeb034bc324a64bb01f17c0e9109bcf72659220fd9078e464b271da8cb3397081d37db31d9e5e503ac78104acbe13483b2b7e7b82ff6a47db09c5f73435cc142f5211b7c6d3baf55cb72d2c69e8296cad128fc7ff2dfa616907ff5c10e2bd4c397bd1b9b7eca93bf772fb1a318ce3097700000168000000b0294f28b4b6b64f55d5fe494fa287a85049198ffb5781160dccbc2e7dd9f0a7d027e9a361b5ff701b832a6fd1bde0ec070314508bf26b33bff84a7858267117a9f4eb302c454fc515a0c2f36b84b77ea13426fd8fb387c300c1535ef0a4addc4c5b92c6d3f8e77d29e854293be86cd4221adcf0face66dfdb6c33c2d4417ec9617472705a8fdfb424cfe5f08b831657bf1775e410007349207701607dff9de9b7afc94e907c0a9d3a574e6ec5f2061ed9000000b02e126113e2cbc987779f3ac444186d7356c0cd6a353a129105f7ff2f1e43f6382a9d73a2a5b9470ed0187d4b6f63deb355402f750ff39dc8682110e6782b838cb32d357cafaf77b7dbd8c89a4a9c2661156c9be1562dde56910627d109b44fd32af868308e3440be216bc8e4fb979a5414898660aba6082429981567194accec5e161aed52741c868257779b047e4e7f29d52b0c146125288f14d46891a71af0bf1c98d87012044d3ebde6ac4dca3d9000000168000000b01afa44dfa813c728c605e1fb71205b342ac6f0fb83f2def879e539ce4671395b9689c716d798550130fe59a04761672ece0a2504a685a8deaabb469a11a94e5518f85092e86086bf3422c8850ec191e075991af558f0e317ffed54d6ea924ca6f09cb002c18cb67f8c0e6bc13699a5611a59c55662336b3e01f1179d36b76b248662448dae259d7fdcace1b2dba53f052d3dba5aac532145296ac23e5d5dadd783448868f3a5d19b5158a51a2c9ebd93000000b0234f544a78c83defd972bb218cd0f7ab375fcbbfd3e83da6cdfaa2a830ab5833f4e7f3fc5a387be6b7f1b7e1cca7e564f1cbaf2fd5875b90f4635d3648dd4fcfde8f1cc33fa757356a3df63c1a0c6a3f6b857cafe28a93b3463b41de290709595b48ab261f64ffb2772bb3bf28ec068809bdf95962ba88374e80e25d89ae72187d58f0ec393874d03f8e3b147539bfec1ebcf7531c7525badf073e8092089a8022d231492b75b1adc4da5ace41e8a54100000168000000b02030f99c664d14900c82bee750d0221aa0d463ff0193b4372d99c96ec920f82aaba3224548b8c18b7a6e4ab66a90c3deccc67725c20542e332b5677a671580120b6e3a153211fa41b85c9e18df75329538599305d65ad150ea3c40a485bffde52e0a90f74030d3a5097fafa74ce462d9003c2cbfcb541c7080b432f8ef40caaca62ee990217541f528a359ef51d7714a180778c9b6222b561fde976037f03adf0e426fdc509fa1912dc36162e339edd4000000b02e59d3fe7a1040da857889373b427265c1a00adcbe30ac30568844310843ddc8efc67eab5f6ab2ed5dc94a5a4cb29718edd26ec7eb8224e3fd23c26cbbac2f84db4506bbe4df6d78b180106cfbdf21f645d44604b75c6b0caab38175a0b686a12859f827e1b03988ccad52e1d292d53e300929b34a6f7983eb73b2c0747fdc1b19c837b249a3a23d3f08725cb718a53d275beb3234686c09084a3a5e332c46686d226fef5e3e2cfe84aafc91835e9b4f00000168000000b01ab6a45727c1d3f09d58707aafa7f18a7ff8d6715687a6e9cbc96af586ed9dde19b8226cb99ca41997352bead500873caaccd9165ca7c87d7ff9bac937f94b79549b6ca1dab5d1beae116968b50b5d5958eca947a0e7e12a7cc5a6ac9cb116f38990f0a2d3a2befaeadebd8d6078de812cd3174f1013c01af484947938e8e3779781fd8e6933821736dd5650a872946613202face0ff87088534c535d4772e7767432055836b73f3e9ff61a84c55eef8000000b03023242a91c9d5fcc63f1af813b82c8c0148eeca01b10ad98f1938d23eb504cb2e7864e139469a01f83ee62e3ba10cb09fe1ceda38e0ebe7d6e5ba207093dbae3a35a20fccca6d42ac5dd335a9f84218a6f0f436a63181131d8550e624819a5fb51fb738126e5179a8fe71e0c0350fea081bdbaf2f54f27d8606e22cbba3dba5f2a4550cd3735651e535a1493afd395e095e8e93e661a0dd83b3c096c8daeaaef428d9a5409b393d173a3c8d5e06a6c200000168000000b00d4b11b777cf7cbe2958e28aa229241335124176a837c4d0e60a9b657e485e97d6a34e274bcee69017bb1b2effbdc44840d274ca9e4a93316990e747d98f17199c8ea7154f5371a6797fbb9629816f70ecf7d0320cff4d19a88215e2c6db908a3dfb5dca9d426a6712f150223428a5f71a7e052adea11254923c41d4329c494378301b984746d21c6d964d5236a7a7210b1fb647368cc9cec10d96ed2d4592ad662cbc3d9b68cd280e88202c711a4e0f000000b01d554ae932464ff3a1058572abe7e6911468e7c1f5554b68f89d3ef13e74f5420cd3c33c1b2a226c997170257fe15b5a946b0175668ea211761c45f652250c0e6bc6823138fe82da4f46ab7762d951428792ede670aeb2f3351a207899b3cbc2b6c4021fb96b8281598c2953b6b35ed71cf9282807f79cc09c6c23068c0ef1dc7e7928969a9e7aaf4ffa724ebdb9ec49276bd340359f269ba8b0ec09aeaee4a72c6d70d430b744cbadeeb257d69c646f3800000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f73700000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f60200000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c11000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d901052f4f7d40d5985bc4bf36583cd2403eca7c9073a6c3b904d5532d6d7253f7b300000000000000000000000000000000000000000000000000000000000011c000000000000000000000000000000000000011c1000011000000021c000000b002026457c3c1372a36033e11c1ddc0a6f9c377824ee0ece6c4a96788c566c65fc67c514ff1548f3f8c1f1fbf73742604dfd0ac82bd358047c97f5ecbe8cec79ddf97a664fb4e42dbf0eeb87ec5ec7a8a0157b8aa5b8c80edf069b606ea16424ba5d5e3d54289756b3fffc62ebea5305f25a538f5dd8eb2ac4cff3eaf614aeed5d73c3efbfc071a9f0ac2b2a904d598e301069eececd576cccba937b213617fe9c6d570f0cf10907462b0187fc5664fd1000000b008ac45da22dd17f11470160bc063ba9cf0a866c77ab5b8b606e3381d63125da3ef141804ccfb4244eae0b60b34d37ca3d8fe6c7dc3cff7acf6ccb9cd3dc1a26dd3b7a59223439dfdb9134d745964bf9b2397722fd1bbe46a4b148a3b1924c0d56ede8443ca21492a9062b70572c3d4d315ef06e40e7d1a61c2bade241e8aa457f5e56bc27e904f9ec5048d3607ccd92e22cb9f61a828d16add7998ec408f7496eff283b744b4394f2d2defd0f11ce35b000000b0186c31498c6ec2cd77f030d4b688eda3aa628c605d5e769bc72505040c1467bf78da1a5bdf4e3ff3f9303b0f8527b6645838cc46b6a952cfa7120df1fd84709852506dbfcdfcff4af7736687af0b9b178e074f11402be212d2ec02540b079393f440b777983b4b7863ee73c3ba719fb706f7b71aea2eb7c3fef46548f7cca6998056361d67bea856943bed590f46fdbe135a30914e7dfcbe56731c423f3cd6e786ae6abe4dd01938181a976f9b0ab9d80000021c000000b003d2adc633f6941b38c7be0eb5fa81605b7689a31834c3624f64f59e30a655ec1c185aa76917d8db8f56985e5223eebcfa8374cd9766eb19b5fac6fa02163fcc5a74df921ba892440a0e25fb2cf51799b59f3a61de4f7d5f7da333d0e3abc2dee2e1cc954df4a59e5bbe7ebe52ea6e6802b92e10aff1ffd80379342713f9816bae3569465bad3bb664136a6e99f974d21aecf8956ca4ad5a88d4f16f7407b609d221002a635c57857256314ba47857bc000000b02229f00bbfc33a665077e4702b66a1b4d57963400c3db31142104564bccf7c84fd14437d4556d5d87fe8c362201ee562a4bc4bd990cd81badf08626a5d225601161c9fb021800610c8f8f6145bc01a7a8c800125afe43dc8055eba1de51e31cf0eb432ce147b2f2a0e493ec4051ac7041c7da677cf43cb11216be87d2501b73403b3ee8d541dcf414e684743c900faa6004bd920ea1d5d0d2a6a5f0277a18363a07e5b5898cd319d35bb4aebda8b8cb1000000b0293de40cd671f24764214eb8bb23fe75c223c991c2ddac3f71afd05d2fd98eb1cf0c50c5691db381e6f0998dd7124890399fe632aa9379e64b4550e8801cd57f28164f088d9f50cd405e4331bca9823b05a4ae8ec4044c4b27bd3d25438b0339458cd0a9e950ed4fbb53b7b08838472812cdf00b9afd106bac6d1eb4f7f377f37eb4a46b82fd98effd5f68b483e08ffe02e488544923006b03d20ce207bc5315715980adba505608f81f1eb4d4d783600000021c000000b00df7099b50cfaa4eda6001ebd9eb465ea6dd094a5746ad86c8f3b3577a04d0ed20a608d3505e58dfac9a9d6487ca6f2923b423c9d6dd9ab504e1365513e6b8159a16603acdecee72b7bf03672a279cf31e23cc95db478659714db913497a820a7d1a797cc4f3064bb53b4481ba28a29d04725e26bba39f58c366627f3cb42496f1948f679c2278b722d4701716566f771dd81369371cb9f636d16de505d4d1f54b5ccaf7604065fe4431379937d9b6ba000000b02aacd0e1800ac6abe2d49e6467f4a8ca74aec93471e64662220d48700f835e6a73ec360261c343cc6b289d8a61eeab90bc70fff878359a21bf6e2a49a897448045a21bced30f11c856734cce75ce6d44952b72a075864436780a809a89f92881391afc301ae9b08488141cb0982cf65022063605c8d4959bf47afd8376329f3426b18a2a6706e61b78bc20f7c2098de51939aa0d966ed75ee58d4188c5be6051fc71d4739fd727209eaec202dcfc6953000000b011aa043857f8913a9016d092c50d20af04cab429f2a5e8a6fefe93a0bc60b0ab4c1b739df959b1f43dcab433b923663870966713eb9ad2259b08f12a2582ef1f1ebec261d2529f7697ce552e93fefc36a52116d753bcd4888addef503b13c28232f4434065743ca69fa927ba1a81fe2825f4a1ab5c35c9c26a4706d8d6e8b6ca139ff7092aba6e384ef09342e6509ca111244ccd5e2bab8e5f889be332a56fd6c3bb266597381dfd0e0a2026e57109230000021c000000b02b32f89fd0d0d2c99de724ab00783d796d73b4f4068055c3a6c4bfc9f4151093660fb545ef5e710edd953db75dc9e60e1d6d17f69581ece6bb7612414ce3a4925e319665a933ddcdc29cc3666a83b4febac3bd77d6f8af72504f498ddde2af7d00e394d4063a0b778758d59c57889ed8205ede8df36f0149b21aee3990ea1444c4a5156cedd82cc3f031fffc2317f7f120d72d09cce01e98dcb27a2e69bf920f9271eb68927a06d611969853487ce2a4000000b015e7e4f62c93bab8be77887abe447420435440f6f0a6971f44d6693579068a623107995ee9eebe2d1d1d671074848a2fb5a1334a7dd13cd7abbf4d9ef75dca7e890e7194510b9e69f490b7c55e156d53e2a0ea6ca203bc8b25480df12313dfd95b93be5e4dda8efbfacb378db6acb3da0d8fb244a4bf3893ad6bf5e641166530114e6e95cdfdd56e84423ef43516c6d72d5adce3cdd9add761394d034c2b6b36623967de6ec45f8750114cd88cf4c420000000b02a9231477517009d33ad2a1196b17d71fb2fbf646901243f0a5d51f9129f332bb5789461d5a26305d676d2293e12750dadeeb44ec5bac804751e8fa757f676d70e09d208133ea929c683c07c419023ca65e3882fc1a9b7e4cc090a543f6b5504c286e58b43344b3bbda63cbecf98b3aa01703f2b5d47b5788bfdcbba8bc7c5bb812eaf7b9b278141d45ab1b87f28c36b0aa98b4f4307de9133b640d1b6cd7cf5cebb8f3d8996c251f8ece26d3bc2467f0000021c000000b0027f2aafeb81b9ede1af3d8c205e21308580c8a93068715b935c117cd4b800fe13423c860992c091c4f1fdd3a616a9c8cc2425f660e4f39bede422819115185d23880c3d6a700204535b89c266c34c1638ec4460f82786e3112bf9bbbf2f9629ac75469d747b30bad037f271a26e853500f6058de2e860b145811a49e75c0efd7a6a638b016f00b90a70f9409c2f47e024b484958daff0b28cfeff3ce4f16afc80daee3b028ed004c5cc114c4e3c1b62000000b009e7e9d9647b8331078f368201f6ebc36c46f533eb7932096c66be9b35bd0b4db48863c7d663023e5765f79a94c82d6409dc0e683cd617fd8cbcb9862141ec5c9947058699f7de84d12bde0aaea217a9b317d3ffeac91be8f76aa43aa9b13585a36b8a8ed362c6dac04051fbe530f8431c397f3e09a3d7e7b84ab0d1403679cdc966cdc85867a39126662800e10160f315c7607b8f042f83f0ae9442f9c4a5508abfb0e296724b071d9b755228a55c04000000b0040fc6cd6be8686b2c2ae2bc5360524cdd2eabca1d8bca004f699459933a9189134868ad4f56d8ff4ca73bff01245c187bb5068ff33145afd85adbd300e6245275a19e5aeafcbbed68a7b176e418eec9a70fde0962af0294196724257e8933ad407ee9739fac336ee762e67fe3915b16121a88e26807be2264eebdbd9c08be8ee4f2c4d5f8a02cff6500b2a4b09ec59b10ba9581fc3a753a5cd4ab1b1e6449339e6d21b3226e5d1a30dc342145c92ade0000021c000000b0096fca2236db4a4d779d051fe77a9a0c0bee14cedc168888adf2f649558e4e07e07c9f44c8adcb5f01b6618f2986a7ffb72249716465f3694c4b7323961909a9daefcc5cdc11ede4d060322606940ce221e224dab2143e57279659751122cbf5ecc31b05aafc278a57e098869c6002e10d1ffc623ca2e01efe2f4ecf376f99c33fc5245124a870cb16e5ff6cee3d8742177a9d7728c8308903ea39d7cc228670a8448bf84547841df98328979289dd72000000b02e2a3389944fa6bcb2455cd8582f8d2a5cbeffea6c195b198d4eceb6e1b068c627c2b81953473b383cb789bda7effbaa4756fe560bb323557ed355c4cc2408944dbfb80d804b641b39e939e6caec70a04d71a9e5d86fcfee53471d886327bbaa561bb6ca01e6c26412ef7bfaf14cd2052a4522537310569cd7390ba2bdf738b83ed06ddb4bb9d87d28cfee9e6fd6a8ce0fa8b9d3cbc6ee000eca76e3a840f843de6085f7a330fef98fdd03064ed26ceb000000b02cd9f63f0040f72d509ad6682aea5e9ed09c336b6f7445b9e6b9e94fb047aa70eedde5b3e450371ecb1209ebbebd6c1c64ef33adf2e8f6f7997db2eb7073638196ae32cbabc04faf5ac26d79109deb7e0d1aec5587984a44f1f811e9c433408c0dffecbec32cd03368941673866f0b1f175427bda5406ca7c291be00d6e626562387e7def45cd235f044bdd3f7871cbe1444013b26d41773aa5b3633d94926378f1499ecaa8d2327f050c2391a0cb0d40000021c000000b00a688d2486efe81c1cb379f2ed744c912a17a6d9d013adb8c7f573956843f0e2eb6f11f8325a5efa60888d15bc47a5a4ddc9034d2844fec6cdec914b0d1039b26399cce3670d70f06bc1f94dbc02fd11bbcd84d204b58590b217164dec1857361a57796e77f4237826972d5d5015a59d1e60107eabe092164bef48cd281dbbd24464600115a1433df09ec70602f263f006430703f94f9c498bd5d1472b723ce9fbedd4bbfaa3c5cb26dfa2f4079e3842000000b02b8c2dd52facdc49b17158d81e6b190561a8167a13cccc5fd991cb141241f64d3bd24529d17140fd9bd3b2222a9daf62c939614a5362204b585e5d6ba8b3692be23836a0a1b5afccca5063dfd6463cffaf3b3c4ca949a01d6b9c6624656d81abecc3e131839b5d119807154a3c7e4f781ebae7d4c8a903d6664df3a62d59fd9bdbd789aba6c5dae05f17ed9e964d14dc2db5386e26c919ffc736a06576d9eea5cc62a8f9658297a2f4c346a64b102099000000b01f43eeafeec20db45f78579ccdac95338d6a1b3bed7c0866edf19f345e6ac9b8e4e5fe5d1cdf5653a869982fbddd63d695452d34742fa606258966cab72251ad914e35927206affaeb386f15ea39a5ae6ff30a399bead0c3cd6fdaa51adb595a97de28202b6bed30f075b491e111c3d729323b14db9caf38912b9eaf89bd65c2991927c0285e9263c732141776ee41761211ddfae0f82557b23fb9bdec7f49ebcac1aaf0a7e7e76a1c2b199e277332f00000021c000000b02a42a996804ffaf76b7b8101020211d9a64d50b0890de6cdc21af2428b32c6d775f5a7a14bc35245794a6abc3b47577d075f44bb49bb04b9ade5010bb1a0a3edbad3b14d61ba1c0392cb9ea7ba65da28fa4b6b5c42e1a965f971c8536ccd59c90774085d052c40f8d4632a8f94ddc80b2e0d0f492a3cfb6ea3f52055d1d5133b131c2a34ceb05d0f81636025c933e1f311d91b9893734bb6aa77bfd7e3b903c42ece3dbee72c7da9fcf11738bd6b6c6f000000b0235a7700a786361103bf74fec6ec6cf705a5f06c0324c61a753cab7d99be9e95c92e530fe0fc022ad49551c1ccbbb6eec9773e2b3fc382080287b0e9627ebaf1184ab1029debd9fd612b63adaca59a931702d380ec37cfd8892a7ab9f3d9861c4eb08f953924a19a737c427f490d6e5e0e21984c896abb4b063056c71891d3db30a68fa46538243ae6c9c13c1d29021020c3b8d22070f7e7ee3c1b3e51c9cfd465db63697a13dc307c953367dbd2f1e2000000b00ad84b23d81f681722f42ed27a55e66e743c98b6d24c6cfff1ddde321241cba3b73e124adfcd422931b23756e92ce3e4f09ed09949ae12566a9993e9c738eb20cd373f07adec61bcd9d92270356c5fd360cd24374da9cf781742ff0c24327582196b7663d8eb1c992d0ea58f55d25b100f146f7eb115bde84ec76ccc90965e4944f1bed4e38a33ed6227b7936346a7801ec7cad52d556160a35ec406c760ecc6a3d4b13ebf369f0383e2eae46c2812a900000fa400000168000000b009be2e5499142d4fca414be527855c4fc5a97ef0b3f6892e36cb295c42b532eddca6e9055018726054dc799c381dafd525e275d48a9aac97980c6846f4eb1031cd31112b93aeed54f46a361033bb250e2a2235f73bac9819e8400eae8c7d763b49f6d69d470c50ec5f8aa1f871cc69e8190180374ec0e1aa07a3504f19c1f77050a86f160a55abf9ff3180678b6bc4c42da63127ebba1918dfc6bd9359474e1b66ff457b88e8d43e3a75e3a2ee82beba000000b00e8438d85c245fec782641a8a41b46614189fcf07abb651f121f515cb760ab160f32174b8d27a9ef30968bb4ec5381ffc89015345bb7d52abdff35bef8ddabef24f374533ba508de8a2322df836ee8ea26618329057ea29820f73f983141bdd8e9b812ee0fc7c6eedc35eac838e6d01a2d171f152ef0ca5514b7b2ffc55247758a8c18d6ee54936652ef6a8a326b6d1103ae2ec3c4beb024ab007343e85d304b23560cebd84e10c9adf5c27e19a0cc3300000168000000b00a5112d62522f07cb57bda6fe73215e3fb6e65fe2b1f219da1c975ed0397b599041a6f774b4897e56f520901241538c974142c6f1124382d371088dffe12b840fd22f04922c8481c2288232fa15a96147bf9a9f987d1af0bad1ff1e271835d624c0ba6e7af7def9014c3741ea1b4bbe1298336e9c9169ac59feda8925e45fc7f695522145546fff93e95bc1ad6a5b4a313e0c366208d50f312b8d09e22773ee11eff239fc0cef7f40bfc39af59ae86fe000000b01d252e811e1d2319db11e44a415dc95fbdd2a2cc922237e89f89539e108286ecd97b4bddde52fee5b3242e7d50729e847f58d31943d04a3db85d40c335ea94999c171b1ad95c76784b5e9d41cc5943acae7eabfe3ba68a3bc058e658848c7611b5707c05ac3195458fcc6e352b636ce806cee79100ed5d60997c8570a14f293fde1c2ed156fe02897c062e918b5a26411922a5c09778b6a105a4c3608819da6aab09ff2c37963223ea63c56c7f573f5300000168000000b013bb67893a9a38717dc6e85ec20b99a0860da1449a39c859e0e0078ed7ba838241c90759470fae00c43b5070b84d48dbc19f4016a7f7fe2b6edb19e50585f009082ec7bd0971b5bbc0c4ac93dd9422f8d8c6fe913eae46f1d47b79028a4fe3a642faa3c3e62623bcd873dab2b323d58a050f303c0c93a8f696a9467c1d17fc21660dd93d70792b14188701e66b99ae100c3af8415bbb49486073605232ca872f5d2b7e25252d2a18de2de9be5a560afd000000b024e7081b5718edf7c075d43b7351863efd82e5ed5aba61793e7a4fa189a2661a4fe63f7dfd6bb76fbce019938506515f2c6bfe2c4c6240773bc72a2ae07a1bdddbab15bf1d51830bf131bf5749030d7bfa1bd0fcd39f2750c3185def8a7da707b226169c9a310afa4b2e27acc507e08d123abb7dc899941caa7396efdd43d306cbd2cf2377d359840bef9ec610ff41052f64113427604d4dde3a726ad8809b89795a9d632d2bc70408b0c3cad9b8e05b00000168000000b02ba9fb4f380a624ec77e2e19706906e3a028b368de3374a618fc6ae779efc80505510a68c28e189f315404436ec00f7b74d155c46494004abe0cb85992b7c44b9dcaecea5b78e9af5b28c2c252eeba431af8e9499a94534f26490f9d14d2b83ea17213c5879a98f48813f23d98bac2c42a384b324cc9c9fd9feb131f179d87d5c1d4bc6edda103a07d051d48aa45058912562ab0a4f560cdd29e6e1e70573e2ea5118d18fccdf2660994eed4499f1f93000000b01d2e2ac9e040fbeaddcfa0e451f6bedf9afe4190220eff30674d9937c95517a9f150365e339be7317edc3fccd4ebfb91983ba5a827087013ab43805e4efa2d4a5759e58604b31dae04ca20d78734218cd298f6cb3b0b7c045f40e55ab6da56e0ef6349a6aed0aee67a327da2a0e303841f90f2c4cd59023d4d5ad39688a0154e50198e7d937fb72ece7324606207ea8c00e6ba257cc86bf49b228304ee6284d7456d78eee12158da71973c53f9cf1b7a00000168000000b02990e66dc377d27a467405b666c9e957a5726be7a9e08d2a86f60b5b2a3f6e3f2a59189b047add3c17926a87a4b3de6ca6cd5610f9929be2551f2e145353be892caf499aeee96b9f8a28ead4b7ccc8b0c18c111ef95845caaf8e42cd1c6eeef1c8d0b089ad723e939c6bae47a18ce91a013868691d995f9532a7b0d45b3e283d502da0c1c5091db2216d05cfb973db25137cfa1c755383c0ce3cc86d703eb91421a148a6dab3911e5e8ec24298a59708000000b014d1d6d25acca05790cf2e689ad54a4357403244cf6f93adb44daa4b147cc59fac5d6f50dbacb12e4a71ebf35b77b50749bebae22a65ffa9bc0efcc52a3429bf1c947e16877de8b8f5e2373b884fc7a927d2946d5d26c7cc8045ef6e236565a9831e5b7e2ebaa4305bcaac709bbf5a982b39acd52fcaafaab9504445b9f9cf2719646242f560bb23c178db4e05a773af24f8ec201dfaeefb229a4a028bf9ce36d8d11226754f66f59441a1b37131f75b00000168000000b029dd0ee8e4c12cb3611ffa96454fd082750f274d9c34279a4d3da04071ebbc2cf52067ef67432be70f96058a3d2a01575277c5f955f0951cb84bb2be8b86bf9ca9de2463f1fa5dd5041572afef124c9253e4850866c4afd96c0b8660ed11c6b9131698ec4db3bae4bacd52e1bff981c516d7041c4101a21544036c62311058fd7ebeacec11b17c8316332ffb27d03bb024d2a6c727bd0c7ac75c95ce417cba483143dbb8ae93ad86e45550e2ef9edb32000000b002410db7d8737b105bf11b8de773d48e91c229e305af4c31626c4065457db2f44f320c6b568a1d115ca0325619fd5bd0d14d72cd355c6cfc9c3bd435a1dee8e7481e3250740ce975ae98e39828a063496ea54444455678bbeab1f3f297e1ab58b68b0edddbc26632ea38600a186d8d3111d5f62b20a394edb6c468080d34fff5e04bc0ed2a404eff80ad08bcc3df209500c9877e01ddea6941e9abe79f13ee528651db9af3895cd7eb68d8f5932aba7800000168000000b01159aae8fd1c6208c67c2fad7fb984a3b8e47a70c6d42861bb2e405b6ff4e686f07428defa294846705685b9d8d6b7a7c8959fd8f56e913a2b48f442dcec55a9a3ec569021ebe3bfbc09384be2e54e6360dfbe9013c917c08c37fd55196cbf0205475118c2603b2d25e51fe69fa3a7711a2f2419873e0be35b06321c9c08e1a4d9dcd3655c4d692697297e7c7ed1e40b0c11cde0cde7f82d2e7b6463cf5217dbe4d1ac8be27b7270da3974eafaae8837000000b01e9eaf12887ccf57d6666c94b23803a67a8df7fef73048021d83ebed271047e2c47ab8b2447290a602967ce34270a10dd45c20beaec45753bdf95fdb407f09e3932afa25a450f5445d74d4b7d3100b28fb93a18db2063b29babd1928c41c91a87314b461936a778ef9ea23751916e71102a75ae7b3b22c6d661c7773f9e9463ca59f26ac336be7d55516cbc6905e1a470d2ab4ad240dd8f5696c2da168fbb20b6bccd8cdb8fe1620ea21ef7cf40c61e400000168000000b008dd889a261affe3e169e621fbf61f461ce1ba11963d93c264887ffab0fd155d8744436ca3dfbbf2c6ebf539c6a4e1d7a53547ea73649b2a329770025b91733df937101126b8c203b9b80bc415e667ae5f9d84236b5a30d14d2d5244d7cfd9f122a09fadabb2da96d94a2a49426dfed60c39fee7037a7acc7bdb572912434ad24f26c1ff571c6bd2fabb6f5c03738d55202bbc178a84267c48590efd86711a162d2fe16812b595e2061e717642a02f05000000b028148e4958f95384ffc3f1fdef8a8d388b09d298f317d14c27b05fa8f9b52c2df656a924287dfda9eb18f1bfd6307d5e56fc90d2470944f3ca31df5589372b380f68d1a076d326dd16420ab7c232995711fdb251753cc66ce608ea1cfe39c90cdd1be4d428bd27b210662561afc98677259a6fbb209fe972d6da4d6f791972b04f97c007c8bd0dcc7b61ad05c0ea43242437055e5596582ca3ea2242206f7e37ffcd55cb1fe44e9dd8162c4889478b9a00000168000000b0193ff9fc02d479b09786ea9d59c9f5f43e744e7b11b26c3b423223ca049f6b5e5230dd2c15a551c7a3263dfd18dd691a81487db67806c52a17ce3d0c58b387e1a49003d52546a02ec226f10663651a7833cef03e0c6e9a801b4085e30932601f6a52819943e86d0bdab482844393d4c20cf2fa502e5036fc55419704f22ea2523d84e1db9c314fefd0459ccb1b7a90782359ee51c493e966ffed23e582a686846ec9f5045bd359c260caa1923564cc6c000000b017ab8e622a4218c95719ed08dd6b0266413074bafc000ac146d95fd982e804ec4cb3307da970930511e3221ad29b374df2e94bcf32f57065d6ac1d161617d6532840038e08403a3285497d1876fe1fe2171afad9662f2c3d9e8ecfd34e917a64ff02a6fe0281b4faeb8f854742a17f0018010a8bdbf32d92058600a8244e70847c2fde2640b0298815188312d95b80bd08103f90e98234a3e3b5a53a7e7cc78efb6e2c6346880049b2c1e0bcfd21ae3300000168000000b01948988fb9b87b4f1f8609020cf1c36f1bab937a5a2219b45c4d4038a2666b87667b66806359f262cab68ff53edb6d84f25f1601f641ddf2a868d9fd7e37d9d62e80d3704f2676f6423931717c406d9605aedcdd32bf5db0818a3658511a372464482ba76e116124babd184d1ef8b8e518ffae8d202795b898550b28eabeaeae43f0995ef9f173b4ea5abeb88c2720721ebeb0abd56364d0dbb758c20c50d8e607433fdd302368fab6b99a0e8a407afb000000b00afcca13564ab1e2bae806dd3b249c8b8cdaf2cdddee80bc7ba212ab76744cf2d8796f678b3b73e68567dbd8bbd9352387866ebdff99537821d98190d8117adc15b67c333e14a14a340f883efe1bacd5628d10673f16c706929838d040d7675c04061cd5ebb2fbd360cf6e3599fc48ff15839ac9798fb5a7e588f62c4316dfb770a562308c672619d257ebd8dff80c571317663f59a6620cfdfd25c33ec3aaf6ce7f6b3f3cf159fe4465010d364f70bd00000168000000b008f5b7f88a369a0edb78824463502097a31c37241914c29cb3d39a362be37f6a5d88a77a5692ca94494b2072200528ccc0e0b1c742251e0669d585eb73ac5b2665d476828abd237ebc3041769949dbac08279118c8a78a9a12faea40e6c2c3bf251c70f348c9493b55472f0242533a681e0bbce8497fecbf20db7a410535f71f54f5e651ceb3496da40eb6d17e53294b2fd22ff47f0fa660705f454c8976412b06a48b4b5f22441fc0aa3434bd797e50000000b01a32878d134a7bdf7178eda37664979432d8ea62dcf4ca828ad952b6f5a3adc45f568b113e4432b78826d55c25c6ac65011197a7c5499e0e4f7a86bcf5b87c843a565db02cd0749cc6a1b01b2d0d5facef12ec079bfdd2729b3d4c61c6a9e669342bab5bd68900aba107fd475c152cd404cdb3ef402d386bbb31ccd46a4442e241bf28e682b34f5b5c3eecc9b293ad3f08382fd7efd0b91555de64ae18df4921682f5a84bcb1428cfefbc12537da8fe5380000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f00000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000331000000000000000000000000000000000000000000000000000000000000033200000000000000000000000000000000000000000000000000000000000003330000000000000000000000000000000000000000000000000000000000000334000000000000000000000000000000000000000000000000000000000000033500000000000000000000000000000000000000000000000000000000000003360000000000000000000000000000000000000000000000000000000000000337370000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f00000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000431000000000000000000000000000000000000000000000000000000000000043200000000000000000000000000000000000000000000000000000000000004330000000000000000000000000000000000000000000000000000000000000434000000000000000000000000000000000000000000000000000000000000043500000000000000000000000000000000000000000000000000000000000004360200000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000501100000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007190118ed29009967db1af193f6fc8620824c8bc6022956acd33bfacbf6df3445226400000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000001201000011000000021c000000b023075b75e16b5ef19ff7f1570175cf7ea5ad5342a9690073bdad113c53a85a373283317e54423625761919fcf19f36a8c5d294ef5a289f6d1402355e301f446b89405da6aa5e2383b52103aed60940e7cbb8b29530e2e9c1279d9522f4eaf7da858f842609ec97666ababe5fbef942a02f50553bc087cfe41ca97b27bff3f820aeff48fbf6bc47adb074be5aeff523ac2ea79d0c891791679da6a3de3173ae0fa5cfb06a5a14748d9b7e283b6cdd271f000000b0004eaa1c71d991e62ecb815f1853d04df3f8dcd50cee831db1dbd7fad0f0238df6d2187cddce56924d8c6bf9675884b4d27c5238bfcc1ced1a4971be5501bd70de34cc1954ec5669c7c5d5a0350c5b6e59612980c3af3a1b7e448b864fca7ae9faaa3999105ccce803c1c6991bb0bdd7239bda12bbb669836588a8b3ad68e12c8bda4182292b859f7a05790b85a525361bf395b5dced9d9dacb40fcb34d37613460c4ff48111afa7b7290ef5b8ec99b9000000b022c41bff66543b1ba36328c8137add29c277bcd62fa95654640440256335731666ff61ef49e479d74295860efc358724d085cbb839b3fb97b3d40a383aa977129f35fac7cbe26dd81a1b9ce7fae9765e1b0b8fb1284a5778a71e6afc90e40936ef0dfbd3675386d339950f3fc3bf0e591c8cff9cafd37650266f3acd9a75ebcd9f615f5b39a41e70e6e7d4fa4b39dff00653cdd3449eaf11a2700281e06f8173d55ea5dc34d5cce5339a3101f623e2650000021c000000b022bd15a2375aca3a58e841d5df60ba11b7d39a11674422caa296e4c59e290983f9008b4f4dc79f450d3111724d604186fe769daf2cd9f91757dcc9f91eba1ff84edbf06d0ccaa9b2ef0153e8bcf2968e67653b106ab0c7636019adcba5ccda098354f9701146c8491aa4656673a2b3eb1ba69381af5b5aafdc0c1f06e245a53c4227d9d22e42646fb0e31835898f519b1d9c047d8d3c092b597e40b206343f872b47be0313fc08d7d9bbfd05c3334977000000b01d13155720e6080de5fb3d1c84962080923ab33f07e1c5db6208c3f29988e471a6bb24361b36ae49198dea79d467e5a4f70b5fb5ea11a824b06c36c5b4463f02bad39efae4d2d28efe8cf541886d511fa3106a144a013358459e755334cf34a8c682d5523aa5d941be32d365488717da20e4d58b4bdd57a32f300f87ed5cf7597ed0da94fc3579c2ab19700d6bdc752414d7d440eae8a301279de3778ca1610b5cbd284396968c7586c3e504f2c37742000000b022da6b6248874b32b886bffbdfb8feb1b7ed62ea3da734636a110dacbb0a006b81c61864de1c1201893bf70ff174a7b59694b263f278bdecf86d8add6adaaae9969542216985327124850775e9c5a425a3173df7959555cc7c26d7eb756d4372a9485eea18de2bedcb0a066011c6b1f60ee42bbe96268ec39a9280f16908c869206927d66287c612a53dfc16ea3b72e80dd4f813dab60f2ec1e5166801419c35b643bf53f453164febcc1e38b15c9b120000021c000000b004c6f3c0e6c2365f15d0ad4b3e943403bb7d71436c5d681bfb27ef80435c8679433a0ccc0b7c1723c70571288452e2cffc0b7a7a98919a6fa6e18e86b82e50821a907a06a116c8bfe9e2bb040e9bed15f322ddf88d210c966a592be689be0dcb35782fade01e8269d47d95ddfe7298fa1742b17a18bfd1de0c6b60c3c6bb3b213ff9defbb88e31a2c2e6ab606df391bd0b7d86058d41934f72eccf5ac87b87a9cd4c580b2465356540ddcb1673564085000000b004060208bb47bdb23d28e8b3505ec08de41f32e4305011af643b89e8642fb97a6ca2e9fcfe8245c2aea19cb7c47fd6113dee06ba0b0e6f320d9cfccae3aaca4db3d61e671970aa31e63996c924cc7f72ec9083b7210ccec3cbf80bb94d82701ffc68fe620b1bbd914d5d4dbac9925b2f285c1b68d8ed3d98e7e83d9df1a432700779839100052df048cd159a09b8fbdd2be3be7dcbef32c8e4ea45ea454efb1db0f163bb7c93fdb6cc21d7cc3b50ab77000000b02ac90edd38b53b50ae6a17b5e066c96e430b06607f277a1e8d131fcc0d624569b3bd8e2d1e016f299e388ad556f7f5a62d9b42d32cf27a3f4c48e9df58915f42e1ee98f2709d616701a0fb736bab728f6a2499510df5ad6f62c679e918d022e97ace20b6e586ff0f83cb27b2c268756310b6f6da84ef1e30b2ebef928f3b3ce16f84a2f58c5c617b746da8800281adb313d542e2aa1aa8ab89fefa785a65c769b75bca77bc296aada6257e6fba5d8cba0000021c000000b0210d26e1d8fa484fdf271b1d827980c1cf6c5eb57d44689906473d943831cae1173f0eb120c094b65c313393e84d1b4136ea5ffdfd8f9f9e55362c8945a1f576490c2b94fb9b0f6ea91fccb050bd3e062c234d6eb408beabdb9937e5209ad9cb3e967c2c6d9f550583e410b7e4ee12830d8d7042c4794ff3359a6c3e2bd595f2c695a993d0e920598f44ee657165ee752a178e37436d60b10f6538e430ec0b71fa5ed2659525e12f3c1b8a5c944a70f2000000b0095f944e3fce7701799409fe8b76ed07558ca79f7eaec68a08a0829d1b84b0ec75d52f8825696a4bf08d825ddff6e43336612090d1191781737e25bc72dfa86b1a369046db3eab346c6f0a49a1cdee44d53174c2217f58b21b4849db245f44dbe4d02aa7df4fc9903827aea33e6e40be23c3eeee2c6b9b9ce644a3b856e1b0cebac13d78f289c728f908d7cda5ae2b232629df6320271698e96a937197596ae3ce96d745bf89d7fa70381d3ffcd8d035000000b0211c974520e0a431f6264d011cb800d5b9e4e08636b244f2210f9601e19e3f9c3eb72b9e959d0bf590b58456bdcbc5b9d3ccf20935dda7b5d66399e07413d1fdfb62d7f822c89767d1f818f99e4fe66a2d08ad18d886bed7ecb4de5185afc479b5eef92758c224d679d13ef7cea736230e9b6cfc578424a34b897a2c1cbe3ee61958548c7343e87a8f776de4f2f7e1f811826120dd0ad8f2d4063fd3b08329827b62ccccc1ca48b199dc08585619fadd0000021c000000b018b8b2ccb20a32b16ae0d08e6f7f970eccbf63bcb95cd1d410c29fb7032263956a2809c379fd147b0e8c66ca90d468d920903fb0db2711793e7f4f628a81abd0873c857c092e0ec78c060668366ced1b74573aa1b5b2a23134d267980235e762e8ac5d398cc1b47105e309935ea6e43d180ad93049a6a1056ebabdb1e9bd8c8a35e993495f25d5281be61f2b68bbb03e099107f4060c4702ba27885c5b06f43d309875e15507bd50f45647eb62b11e1f000000b017f264dc8cf5019511f16ea700c877c08445152d6285e326dd1cdaaa612c35f5e585e2601d7ed9e5bfc958dfe2f978a78c9fdc6b1aa6ba8614861986a4b9b259ef834c3114a50ce12a053c370664fd81f1a112bf16c1f362bea3b60925181761a9699e006fee3fe88564a8dce9a647fb0f84fd427ef7501727494b38b72d179498fb198a0b6d735767a2c235e92b317e225c68889d32962f61196892e84c5753b4b2ca996cfbb2b1a117869f25c07d54000000b019bc923f9e78ad19d8f1348b2cbe9079ee44987ba5d504aa97c6432d2fdc11d9df883a36bc15ef0a5538aebd0185bd8b5bda268080e8729f9a64b9ef723670e5fade19155c5a3ce2414b450b673a746a524753b0990a645fca32cd197b7cfebb696097967cc915008a3ab35430a439082cb9ab012c910376602709c51c8aab418fe90377f4197bd9dc4a7b3045b706c11421b4206871293b2b4e6d4e04a4dff385d3974dc2f603587d8e7606a2387db90000021c000000b029e175aefb82d4deb081f4e31e8aa2bc9531afb5c56097f7c62534ad1ec57c7078ffb6c097f3d4255d5e5b00ec93470d97a208821628aa634b1fb555ef68e111386a4fd6f8eed5fb1b7dc6397f33623b80ab320ffd4a59179ad5c3d31ee437a9100a26246a597b28ad0e028f67f375871a4172b7e96b8e1bf1a1d813269f6c32e1a05c7220cb254c0fcbc85b4173962c0ce6ec7b875d9e20090532defc79ea005d46090e4e7dc3d186c1160cd091e74b000000b02f91757bb58d172d48f9bfa581fad83f0c43f0b4eb58fb95d89e6bb0992c1bcf3af56351c93cc6d73e360c8700c8d9ed4a8fca78365301e71a9d82af89e5f9ec7ec390406748856cf9a3c8be24f0c2cc70f127ffccc21f82e7bfc4726efadd82c185445fcb26f7a636ddb32720aa164115e708582c9b0addccd6919c9b6c7f03bc784ec7cb3c31582c3dfb7c1d02027b02eedfad95c751a69df243c1fe4e055c8de9c2fd0693d4176c4930f14e0133f1000000b028e8a8fdf116f463e15389649ef388b92042fb88999aba018492ef6cfee2eabae28cdda37224aeb3d1b94c74c04e14a79d83489e2c4d204bd9ad28eb21064fbba56698f5739a18798b054da7491bc1ca8c9f7adfb824ec9324d8ddee98b55d8313d6dd681b31fc953ae3cfa1cc4f60c615cdb54faeea3636fb41352092e6ab1f2a0c2fbfb33ecad9f78b1a4d02dface71091d367de7e0f7153b87a195ff971d169bb68725578b394f22fc9fd41a20bb00000021c000000b023949a6c487e9e6d6a36b0e0105bba8b88c62e405d4bfb394d7219434876145a03e633d9fea9702d857613690be3f90d0bceaa8fc45f084aa19a1d7ccff536e6431aa1e9f9d18563faf491ffc08bdded11cac110d5bf40a98f86fb4356586abb22d73fab3140d0feefda08faba7e1e930d4cb587b399bee7350f5c7d02277c46dee62a4aef73a88114e9913a25bb298c17a00a20173646241d2e4bb0d23af15df312aad1ce7f2462af8d6d55b1599e5b000000b02f5e1f632d8f87581f95cff082f25df2214cd47b6f0897dff00156d56ab941927fcc4bb40964d1acb3f865f8da0b577b5b495eaaa457267a191c48d5c2b181668009c7dd5a4f3916e80b7e63decc0458ea719ead281a52935f138d99f2f16a892aad6cca07e238db2734ed9b5689d2d8202ef014ea6cc9663da75918e2766e36552820002d97fa793469cc767edd5c79294a3f0d5b78d3b4d38704d1765fec754e83df82bbcc959fb16e569ee42d2b2b000000b00c1f1b376d4bea2751fb9b04dfe2e4581d575a4eeda2ed9a7690ca384dbf113e052dc280cc5928b1d62f3cea14239f2779054463b2bc5f2a0f9abce76b06af9a2a175fd25cfe980e4d996510036db691cf72a60a201441ae68117d39892c62218f60e4d813842c720303d314a34181370347b55a72a6e6d668f198fdfcad223f31dd44203a404b5fa5693880614a792010fb39bb28938307de0596149d67d8fb6da9b988023f96857c68f300e2a207370000021c000000b022f9a7a5621d202a6bdce5d2f99e560af5267d2a5a03c3864116b7f860506023975d7e2911ef6db687a7389e2289cb89fecbecd0d96d169094afc28d990420448e293e794c4ad537cae64200ed40d8b14d4a8c6b6be14692f12366d4a4493e4004a57c22f95342b7c865fbf959cf905816268cbf0903f242d9cf4610f1fc18a5f1a025d5f726a2df58a88b3107ff0ad118af540065528f0a46d50f9a8976d1029baab42ef54f226c4ea7f0ec91b3f31b000000b01f977c7e636234e7e56a8d2c791719665c87cb37345a7e89c15f69df5176c1d46028370a0bd5474d11b9be345285aa8efaafd425c18dcab0e21c8a8c422e29106a805b7cc3bed503a4225e8a1a026f6a90e9153856232bcadaa893cea9d4549f296ff38a3cd5ddaacd5ef8839e7f650a06ffc6d0d7fed02b1ea404d7170a7135a23f2be5072660c5e3ae66c280ce85a12f36a8e188bd5e118a124233af07a222e63505997efc28724aae2c5beebb2780000000b02924214e7f395321876fa87594ee20b16530e799f5f2d3157ca02da6f937045259dc2415ad85b5a8e345fe77dd00e6ccab2aabc7d5b8f548deb2a2d9c49ec0fdfd5ce183eb263d05c7a5cc4984be5f4d5c44276ca62735725174befdeccf9a3075af3620f56616c36a4db6e73b73e49b213c6a6c055414796e59f46accda35ab2e049d8d2a521bd3bee34fccdfd97931182b811f19c7247788426e4817babef294e07dbbea009af607ae357cc10a3b5900000fa400000168000000b00374356b15049409e77891746d3ef80550dfbc0d0ec44b814a6b381106602824677c31069cd53c0b4376fa271df9d555e9465d92eb6694fd20aaffe40d4aee9203f0eafb627ac3af196cf42b1cfbb7cf9670d148a8939eba40872dcafc478e9e7ec051894d46e5884df53bcba93b6d692444a8e5eacd7b467320f651f47bd5b796be15187c865a11bb4f33b97b6ee3ca2b3aff992d25291fe40a23f8324ff8af30cdb0f042f36e505686c0b46d59e8f4000000b0050a89e80f33f0dc5bb334e246c236f83620dd7f1e0abd090cb835e6bab8b0e7a8c18563203f3cb43497bf69fea3a7b434cc7a70100ff2cc6b5108d6c117e2ef112a1e81af9743a7a7b7e9c0563fe9086f9be7b69056f961a2a8fc00288df4e508ea8943409018f733ccf09a9dc68dd222749f2f207e4e5a1097f6b576eb4d7648b4c2abde74e2a43c22b7216635167a236c50c4b16801ccedb5ce9005c0954e1d560dc17b62fbe6615145ba74b9413c00000168000000b00b91c84a2688c18221854cb6896a680b8fd09be28a81bc089b65f436d5136a675523239d764ce9c4bfec04a8242572429d8de4822e7c8046986a348b2fe45327f4a8629fc6ed0f7e446e63cee346f2f99407b8a3668371304bb6bbfb2c12090087ab0f0be4aff65949893b9e6e74d53a0c2941329fa7189271cf82b319bdb7878b573228164be84f9b34e865d380cb4c281a54cf8ca16f9be3b82bdefd1c14c61c19cfe92d3472bcc85c8a7c496f1798000000b00c731b83ce694d8a0e4dc47d67dd2a1096460886b090833547a5298f8f49cea3ba9033ff2c68f8f4250239dba4b6c43afe54eb5433fdf84064368cdf2cdb18c374762f67ef4d143181b532f1fba78b154002b232cd8cc2d0aa28f805056acc738d4e4cdb98fadb3fc778a6a123ecd234075d3e8736f3246bf45e071bb0a72a64d73c7c1c807078bcbc7dfdaac14a5f1e00729cc1b9fffdbcc48596d6503146259d5507f65ff511ee367ef0b940466cd700000168000000b019a89caf500406c3572b276a088ad244f2edd93b56594ebab5e0673634aef8cf6e0770d4fee96407f82bdf47fdb1116e0ca112647fa0d4d711e9ca8425621a94e8c46f718fdc066a8bf9afaf37248eae7f58cdfb24a743b5cb357ce13b8195c75f6dfb471e84168c95544bc5a410517f259224a67da56e80d247342e987131b7814d5d9d5f01a32822e6fb5e72e867411caa7dbfe8e088d3debdcf6f4f3055035a33d28e86f2714a55997de8ddd0ec64000000b01f2b4ac6f959c8be301dac938b0c0ec088deae2a864dbb5c8789345386b282b2233d7e5da1f1b0ff2395524a318f1dc2061da63abf03f5c3600b0834546e4051a74effe14270dd7b1bfef63ee39c5d1a379e66c5448bbca44254fc0b6f4b9ff49e5934209e1b82475bb7721c040223250cc65897e4786294139311b955a5ccb2f17350cb675e8154e2badba5c497d34625054950df73cffea33886125b4779a81600979b3e6695a211f0d5393a367a1a00000168000000b02a41229c020fb028c80aca250f425a521272f637ec699629901c3fc37b8824ebb2756395431b5366d8b81d2e3d65418ae06cd890843733b2786f327f650e65f5df9c58fec4afd221869b74d45dea6ab154c2ffe03a2a9faf1eabcc39f4b80f15f35ec0eee13f88f19cea556398eb1dcb2de7848bc44f8035c4bceffa732db33f290bf6db352c66eca02e098d5e6237dc22ef5417af21becac9e32b4042b9c08144bb4488f3b3cc23fd64eb8bab32e1ee000000b0185a94325a07b1216ef6efe8a495dca76733b41fccfbbef1efd10227ca125799bfe78d8c7238aea310a59d96c34735453a5997b184d5edd74236064e29e5516cddf625656efd59aa67ccfbce44e41742469523c2399c74128e6967f2124aed39732a2d2be6f4c6f3109ae6cfe406f746120be9d9e32f22174dc8a5a0f9de5e9159dd194a9a74237657a9a37c018ee1c70170e8ed4f0ab7e348408aa98d573ba097f566c72f5a33a19852716fe661cf3400000168000000b0187e17a6b3a6119d3b9db1ed5d002b00847bc65111cd34df5213a928600bc1edf31a1e8293baad8b9e056dd1be82fbe39f94362f5f8cb2aa49b089625d1e556de75965f4722f909e26302099d816e56d7d9d4ec2f78eda9830aa2ed4df467ba4b5268b797a6516aac22a61b1974a628c06533b3e0ddd690f27995586b49290353cc9e6007f7125c49635eacae5bb0bef0f126ba0bfebce814c19a4f5bea5584af551be8ab15e89e606ee2f0052f04b4f000000b02593757ff3a32eb78b9fb53c7057d550de83dd2cc59a47747b392a7e46e626eec6e893ef0e3da1db0f1f561033939e8c3497e252992968db862be26c0447e63d6e3995b4f5cb492d43191516ffc41094ddef34f516e6453ffe1f277a89578f3f6c57f5e8fa5f5af7b9fcda0a7f2a97e20d8df7d6cb4721f77c89d871dc9f4685e479ed1b7d49b9de99520ad64e7c5ba81ecc31bbef3c2be91e401b665159eec65db72cfea17d28bef920eda61e4ce43800000168000000b020e2b5cc89751a1e2c9c49d5afcdeca20c66cf06c499e0a5ae08f8dd95c4ca9f21ba9cf8c8893a550d9f2451f8d73be90dad51bb98c90ea69efd81933be1dfd36df50e3be0803bda3fca1d9429384d41d4e4da05471cd7f398fab7d8734f50b4c9ea7102e99ec37ffb302178894bc597172c7847f836f2643cc0b5cf5cdce9253dea0251beb4195f74b77610e668362100dc06756dd5f706fbb1c0be979c3a413c15a002d08d3b94354fd6c7e405dfc6000000b01f49d61125dcad1eabe6f25759a1d55655fa3aae6c56f6c9a0c8f0695808603211b93e78d3ac4fdfebd4876f2891618d6651e69ee85f0efb02c28d58f92c11080122a834c0919d51d3b57d8fa06fbe200e23cd41fe87e97da8f7c01c7e5188163c2a3579456bf5f7d4c0b3685648ecb7096a605423839d34628698175e3f23a35a279460d73eabddb326091b7934eaad07dc2ae6cf4c2a9ff9296d481db7beb782076046287de1b15d6a325c4245593d00000168000000b02a12c23e5bd37562f9847fdc4c1c09135aea5db0df398b90d974b741be86bd722620b4a1da243da2227b91f6655c9192f869283669a667b6132772b1cb4d222356bb8ddfe47c83603c3b8e56b667f74ad8b9a8b8491f5398dc8fd1457a63394ce5ae70fa4c5561fa29e237032be77ae01e9b9db80ef4727cd6af3c96b25c5b79ba523bafa8bc0e9d1cc55b0a954f4e99233cd7d873903b6c05b76920672f6c8ea59485c7ef5b8982eddcf2fbd6227426000000b0253abca76472edce5835d43f60a41f13038ccb56b9a11bba143e2da880d6193e48fbf19f166c78c160b3a46ce5755cab8cfb8f8d5bd72c9323aa72284e2fca49726ac9148051170ce99fd78a7bea0c75d96560fcf74d42608c51105b82e337334765af81fcb8fc8f6b0e691b6780d2810ec986c4019b3923b03cd598c070b0deb5d5df68642cb014ba5cb540f691f09d00cac6243849f1fcac74f68ee7f0068682d0e1176d42d400af3a3a945a482f9300000168000000b02cfab6044a71ace9d14d825df34dec4bd24ae7d3bf274cfbfdc867ad067cd5ada2cc5afc00aec678e5abe6461e5cea11649a4b7ded96cf7eec1d66a35b0643e3f0111cb789346488e923fff1494835649556b1ac91e865a8e61b7ac3ae928c06d5a29f8eda4de57da71ab3083643a9b0057b438302e8afefc9c31eef4cf7d0335cffe0e632de4ca4c4269196fe77afdc245b46a8542565c9d702ab1143d592fd9a5a7732b29d25f2cdd3f8d16cb51dee000000b02e4f05c72684a4a56e7ede063c5cd039aa5937ed0b218712e428d33f6c9e71152968da71564658b17bf16853cd5434c967f93759c6aa55356b01f3d730b69051231fff565eac03214e96402c46f7d17c620f9e03a224da103cbc78902d67c52831f8f397594c066885028c1988c8a21912580ad3f2490b7347c20f934f589f89bcbcc0af8a8003ef961c020da62893fa1fa98879d1f5cc45767791b4559945861c1ca0c345116565e507fac9f3a7097b00000168000000b014334e973ae9e5d3597c015480ffc99bc091a8482e6f72960c25b4ae171282c39bbc932f5f646d85a3c52e84c0ced3422d18525db664fc5f48a0089eeed6df29deecf0e7d315023140d2ee7d58a58742b64ae8bc6426eeae8e953560a128820d5fae7d76836afce83a946a82e698d3862ad657328747ef4417343938ce9b8c6eecbe3674dcd383dc6a8f3af21ca8988f0e505ea6c56e4b75d54ac02cbf4cb0d87ec596e4d2eaf56e7f7eb49cff38dfad000000b01634c4bd23ecfbc73cf274c0c679bdcb1fa90964eecebaa1bdd4b4ad2802b83f63e8721340652611152e8c1aa95a7ab59f8eb5ac078757ed447ef75bed55ff58d11e4ce18c072971a7f40eeaaf43a1b3c1359633ae30586501c70f33e834f216d7840afea9f0d37d052f30b4be6f373105e8f063da1989bf62ede892e87f3ed028a5b331a1ba0ae7f834a2e2de188ed01d49705fedf840695e74fe8f1551bc91a3d496e5b16a1d7661ac43497061f15800000168000000b01b42ecaeb1306e59105db6124802b48395c9199ca5f8d2c71e896dd0ea723501841a6bd6d9f65436c9e3395e7c6f247296d638540e38c624e14f3bef11f37c68bf6a20f07570188f499a51a20f94017265c0e5fef5e3ac4d5299f9c752ff01d71824669283c9b3e02214d1047b3658a81fbd5eb08f95d0a9d078c79d5947502878b798209bac4a787abe9b976c52bfe0088e6adc0c330709a573372e58f72b1dc07ef9482b7eb8fe1a208ba28113226d000000b0150a21b51f59ee54a524d5689bdce2dff209f27ccc87bc9b069fdc15dfff9e76ab5ace83eb999321c74dbe7189c3506a1d6d63869a315f0e2e75138518f4800a983f9a22071d52e56b2c1f954f78eca55f1c0d45a5fea97c3cb886af5f0553c879a3d9da7e9fc295b3500fb06116c8b12af802d84d7178decef1507268ed734e5c442553c90ab3cfd3c47423e758bf78296397bce95900368a2a62fc50fad0e94438a54788b4b3057e7e01c13dc4002100000168000000b01b321a3d3637cbedc355d0a1d0d567f4da0069bbd47ecde84a1de2e091ec460e7c354fd00f2c28246d797de56e9d9a7e75b6d6d591cc55aebb4a176e7abb7484f2614564e0f2ba90e1eb1db629b6255a666634bd4a906522ed274f7512d99e626ce63f3d3744eb5d495edbd0329a9dfd24f265c34650389a2f6db734de14cfc711afcbc22c8a8cbf9ca1cacaf0151d9215376ce7c70d95ba00c77fa3ba56d7da0bf4358e3dca1a383134ea110430151e000000b029d30f1a2747fd1b061457668d08a8265469297b970ce0dbfbab71e7f55274a7e75479a3f7cd4f923b12cc8f7ccdd3c3dfd0e41458d61db508df64eaffa1dae58cd2df33fd64fcce954ca91696491f75363d7be034abc8c32146dfb8d7d189c89e0d78b86d1034999103b33b87d9b149003b8451db9f9035d531facf8fba219b1249d01ceca523b7c8bada258e4180402572c7e0b0b952eca6506e4c8939cbc1f41ea7880d74fd0b5a387ad6fedd5115", - "txsEffectsHash": "0xba6c2a6d813750dc256f667c3ba6c1c791bc56020496c7b490d00cccd40fdb69", + "archive": "0x0cdf664d86731715d9b4b90eb54fc313b6ed470b4d5f7379e6f79f1d123e5c8e", + "body": "0x0000001012e5643e26da426570dd999e0e044e5f83d60f3cd813c55059bc0ea0f4a7c9d413b2d2cea949fa0876265cd8eee3a4dce1e243783562ea07e2de537f469f7bf627abb3d4560e786bafd52f77ac52dea36c50419f32386567bd969b0c38e1bd7405d339cecb99fa74bfd631917f965357f0341d8c4dfe6a8f4b621d8df54c82941d560ac24523012499eeca2594f20ce238b7d21b98ad5c638767d70ee05532c2183e6d64e69b005709dfc4771c7ca5981adc54f3e8bd1b00222461ae90e44eda2f1d4572fe0b0b23100a7ea6d4780b25e826e41ca9e71897e010bcb218887b3d036d44eb30a430b5cfc6660270eb5fb7f274689ac73dfa53ba9d0739fe38637f01f7130af8c5888d4c65ea68109a1d58fe8d7d1ae62098857b0a3a3dcd393ef80ed8bcba6eb5e3b4887a32c51c5853b97a5eb59c87c520f36423c6d7be06071821ca1719330de5e3c51a521778b49cbbc1d53f8ed42e0562bf21ed72e8cb9a410b0e82ef5f7276df41353faef675fb408aeb246b6e2f704cab99bf28d1427e7b0fec7b9929c6effdcd045d3fdcec1d1b73faed495444699fab936630d69b519f0bf4f1453db36439419dbfba703b849d1aa5774fe9a5325e5bf3e7cdda9d1f7f2a9c2a035c72fd4a3e383306aff03448f9accc08a2c665837560cec8675fe2512bfaef35a8fb7df08a81001a7fd4903849c0371dedd87f31295f46269c5205dd00000004380000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f00000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000027200000000000000000000000000000000000000000000000000000000000002730000000000000000000000000000000000000000000000000000000000000274000000000000000000000000000000000000000000000000000000000000027500000000000000000000000000000000000000000000000000000000000002760000000000000000000000000000000000000000000000000000000000000277370000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f00000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000371000000000000000000000000000000000000000000000000000000000000037200000000000000000000000000000000000000000000000000000000000003730000000000000000000000000000000000000000000000000000000000000374000000000000000000000000000000000000000000000000000000000000037500000000000000000000000000000000000000000000000000000000000003760200000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000441100000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f0000000000000000000000000000000000000000000000000000000000000659000011000000021c000000b01453c45b00e4b9a564ced98590950638ec613525f2e881a1bfddc9b41dce55041cb96d8fd1a78b7078afd21e993bf88d39c6588d4adc62edbf02503c42b0aca6d453c02e06aac647141b005e241d2735f733dea4685536041df64e2d5d13f6c981a0b80bc8d94e3490a688ce4f021ba617b8bb5b18453ac824e66f7abfc703f5ae2b844bcb96e4dd478dd3f17fac851c1745a88c8290042dba40a23434ba28cbea50df7e1cb4951b13fe448ca6fe85b1000000b0262e0b94efbb3bad726526c8f1dfe7abb4b1e277fab48dc1215bdaf2daaf17eaca428361c2f2a93ffb776cd3f5ab9aa13051c4543c88764571504bed12216dddf1eaabc726e9dd84adcb21978d10e875fcd20d5bb4701c278f11d5111487f7cad6d92310aa51aff2065d85564d764aed1fd91d190f1bcccc14c8e71b19f6e722869c851b3c790e140701b5c6a8152fbe0452db67ab4cf63dfc61cb8f5ca63e22091ea15ba38374e02de726572ba9edff000000b02dd564d925644e3cc909fcd6814616363692ef8f79b5120c3e22f33ded265107d5b7518f7c2fc846365afca3285456fca072364b43d0d626cf5e7af2bdd15fbcf19d3ac37b1028f1dd8bcb51ddc4837ab10b7b4e66af89b7c39860314b5fdd39755188f9f6fd178a6e060efc5f4f70ba0a088f687f5f8080b0ddaf90158c2a73cc436d042905c12fdb03b19f292a212929eb704a46723fc8c9c67b1ec2e542ecdf9026e13c9bc55801569a40dc06fa060000021c000000b00eadadc76675966e3c03027b41970b1ab0510f2d98340cbd2d244514a74e181fbcba00a1370265c8e51d6f2b2ad7558717dfcecc7f004a5b1955381b1838856b40a616526f5f88f3d735492c3c5bf245c4bea2e7f83fdfbd2f3bffc373e642e5c89652b7b04e47f310ff7d748def37ff1903ac54d105200d226fa6b707e1bf3f1eb05bf622ecfb4b833f0d08ed05f5c21a7bd8214dd9c6b3f8e2d9464ef521513ecfd64c1f98abdca8707de65364027b000000b01f0bda7d83b5fea9461c09f20640bdd504049a548d8a677550c52f3c56d449ae3a592762311b861c418ee371b9825fb4b6630e80ab1d0a93b752faf048c49fca3acc21049e2600ab45b42dff48e22c5e19fdd1331b597d977a3a2053b11bd5baca5ecfcd302fadc401e3fe74821516d7085cf4cacdba7748b1e26b014350a013c22bcba7853b50bff89c2f39baf53688144f48e0bc1b9de5d1215d249d584cf18b3eca3ad8d5d476f2be4efcf68e171b000000b0204f25e4d7619cffee3075fdda079dffa14823155a070c91b19142135efdefb6df7e17590947558c0efee403208380b9951de8f17d456db2496daf24093ee5e05b2dc1a786b634d41423f0847c0a4a3200f1baa40cc9ced9d141861a83b0063a98daf0501ea0a7fcca1c899a025bc6340390687f63346b7d6f5bbfd96b6f9115560b42286453395c6c91e4a5ec382a8422c9f30cb47208eee3de05eeac74418fdd90d53d13052701ac1da0d112fad9940000021c000000b0073f12e1cff9a046eead73f1163a16f64eaeb1d7107546ca51ef1a787132fdf9cc4b8a99c5e03c03420562689358bfada6fa2143157560dc7ffc2af10e66cdf04271c9edff6f275514103f15b9c14912ea3c83f3c97990cedaa7ce8073792333b5fae87268746e654b82cff646674a202ba29e0741e5bee2fc3c8a7227898b66a49f3c7224340b961bbb17e175b4b0b721ddb15b326174c8e234f66ca2cfe9f7e8610492bd9dc454d1b974f78518f26e000000b01459bd2aa4460f6ea031375aefdbb2302fc2a7665a3157e9262a4ad2db2914060b700b517292eecccbb7f30955a01436dad3ff893676ca5f37592a82617af6c4dbcc61bb2bab9915ea623ec6d89df861ff05f35ab0c6db755d846aa720b435e024d6d7f34aef5870caa8f78f58ae495f2ed80c4b107916dfa0a52b7b5d2062a2ed1d26727d8be128973bb7a8a92082fb1c46215574992c59ea77b48e727f83ba7a2d4d5ec141dc3aa533dc1bc56b797a000000b013e0af63cc1a951806874a3d96c6609c80f3669d308817aeb4747bbca961ea6485be7b3cfebcfbaece59413722538299fb4d336031a242d2f7287d568873c01836657ce7628915aa69c625def994432f4712715fa12ff5995c521a2389dab51e08ce2f41fae736eadfddabe07bd23b33211f86de6e3d0642ad84c76c478007622dbe6d18bde746c76663889b08b1f0200a7bf2beea2ed4c749777d05d7ea21c6033aa80c7bb39ddc98d73555ce590c2b0000021c000000b00cc5d297624d9e9de04c1ed0e5b6514bed3395f3b1e7d9388b668bb3ee5e2649772b5c7e138ab328212bc056d3f542ef5ba9e737a4ed27f6e4e498f38ee6fa52b5d8c39c4787eb2cf07f09234e26efff1b3e8ce5cc0b3f622e33e61882842767270a7c384d772ac037b4af51980250b314d9f15563162787ef401a48d44bb89faf893f198937827b34f1860344b2f057160500199092e854ca0d0be620cf1fe47615a59062f576fe95ced0fe1a1d755b000000b000d65b31e42213cb038ece95de8f5c430bb9ac994c4c7c7f2aad977f066480438c6fdf5bbce378c01202fe5cf23f4de02a8c5f3f58aae3e8f322266cdcb6734e556b3ced61f20a1a1b88302a6c12919a0d5670af43821dfb3ea38bf1ac477e584fed3f19643e136079af552562aca3330112338de69599db6757c2230ec8c5ac26a4f6820a4bc287fb8ed6a3e4fc1d9d0ff2120fb2f9315c8919209d341059f441616b7ef40870d261b280cfe1927890000000b01f50714b0f61347e1523a0688354de8c5e717390f693c9cdef26a584794f39d45eecf7963d224fd97ad699d21271039a26c962c2beafcabcaacd0730bcc1029d9d81e6189c07874989ebb69e94543b6ff8cfdc239c6e77bc918737e6fcb56c456c8d58deade9efb64c5c069489a95dc11e772e285030fc63e5c0e37d34f2bdfbaf865ba339f554f090b4b584a30b8fe40f33ac376d5d3be138b9c7fab3d057372417048cf70d89aea400e904a7244fd90000021c000000b003d759720da2315273c204b6d7890a3965304fa846763837c534fc82e6c322d7406a182ab908bcf5de4d052fdc4147b3656b2a53449c4cf42d38b505174e95cbf63d750043038d8e13a12f40e9b5648aebd03fa3aed192dabc31ed13e8df8c2a136324edda13bb9831a2ea2a00988db60491fb2aa15d91285acf03331666c7ec02b8afa053a9b4d5ebba814e8187574b2a1874e4d1185eadfa13e4ac30902253c79402d7df7582c0f4ee803ee3886d3c000000b00e182cc48ba3dc9f7a8129a07f36070c46a4f237ac372aa8f5dee5646f35d7384912a217b8191d401bdce50de9261caa0121f587e6066f7b2d1fdb69837ebe8f2ed2dbaa4788e76104a3effa9a2faa57c5b5b63e97bcae40bbe8b2fb3f7aab30a31940933c474348e725f5a2f2b0eb7e25fc1402067d8d881378ebfba50e9614849cb105c814dd7b896d27c2d8f692e71a37695941f826ce13d227eee2690db1bf7234f532b3e2a00e87edbe633c5404000000b01656d5f2d23ef393dcf0db547f9160e0751a93ff005f8d9081c06ee49dbf428780dc4353907a7b80299561cc6ba259760ec6873fb2f3d41b929d997b3e138aebecc4d67ea500092036b10035e5978f7da1293dbabdb4226a4c04bbe4fac747ac671690f26fa89a915f6f03d949813ca90ce3dab24a594dad84f32d960bd3c48e27b1ee5b78865d4ae9d6a354881a40f411978d12f93003fcd7a20607b1d862ec6ce06b36715614e8f5b7c07e2ab5e9e70000021c000000b010fc206c3dd60a9c5bb378fa10265e5c97f883241bdca676178f9bd90f24779d263cc046acb4212423612ed97c2cb768a231b7e76c8ecab7fa800a81a7a7e70f66c99d5af353245fba52fd9f66a62032965a15c2aff6b5acc79bf7b4c3913217fe1e70961c24fe3c66d03282bd3151ef23568f4e663a879693f0d938f7a839a8b9715759a7b5eab5ebf7ba95b35b79311735672876b6a3ffb2823890714e416fcfaf0e7649a271ff6725dc917950699b000000b001910e5c283262409f91474c5f1eb313679188181846bdf9091fa522abd134435a1e95c27e0ca7a219be545baa8524aa1369cc99af9b984a585e76bf769fd3a9611195d264371ac37faf8bf7579ba2c1c21408f13dcfb92e0c5211bd46f3bb02ef615d3026f31bb0d2d24872de8651181b084682af96413f36c0fb670d634991841bd68c84f3a4c609a310639586344817e38a88261efea5464e5b42464bdecd751ba5cd7527ef3f4d9c07dd396e713a000000b021424cab97755958a7f27708f7b6957cd098c04ec1d52893796701354d0b04b0dd824aeae0e8f1f8e52cb80b2391dd1dfb5d6a0deedab1807c47a4ca87d3e55dd35761b45973900979f0dccbf4137ec8c21fed026fa08883fab72a51786b7c412ab1fcf56ce3c209b6933dfff0bdc212179081fecb9e882e242b73b6e133306af924efa41f874a05a1f593565d350b80028c375c06eecdcaab96258a7af537e4b320c2c55e5a76259743306b31ba242d0000021c000000b0196f50ae12f37d69b3c5692d2bffc9701b16fbbe8c4bace8fb916d08a99950219811358f28681720e8441eb332fdf13d27319c43ea98351c6451fab622acd699f9d870b83bdd8feedd831d876af7a12575f2173310aa747787e7284e78361eec33d4539442b60e3d178492c3173764400a457ba8afbb9aeccb51d0b311c8ef161fa9e193c1acdfaee2e654c92f682fbf0afd8f3e417aeb619287b2bb46722ee97d2f66b51be6db2e9f3d10f4b9f5ab3f000000b01ce9eb614388fd13206905867dc7f028fd91a5ede7f2fa98acc8be1564ee14d423e688f14241bb49d53fd0a34852ab3984e8ba251e623a4662c0e2aa2cd517b680b432724c56a198752799348c3531616f9cdc0870ec134d35ebbec414ffb595ff3bcb64db4c1d3750ccd66e99134bb10daf5275f7f445a9d210f308470ce0018e9f524b533f745dd04ce2af09ecdefd2c1822e813b90ab70bd703976b2af8c73329b9b867b97d4282d747eea3f48ba0000000b03023c224d5d780b38bb6e24e5a5244b9711016c24cd5b32d185e9b3de5a2760a26ad174049c676fd2d95a79fb32785927a27159459e9fdbbf7816767c9e19f497fe44e2706b99d7ead840afc1263544b4ff3c0fdabc9a63bb5871c623aefcae002234592ee3fc42f0af7f57b72caeb5e20f5444a2d0e32bb5b7ba1657adbc713e9b923287b4ef6560dfb343fdc32d5ba2b3d371411805a0bd78e9543d1f40746465c99c58c957fdbe407612caa0f508e0000021c000000b01f2b60b40f623ea6302aa8024a9862409c01a1850358d9cd64decf4d58a1c5ca213393fcef36a780d5f1b04e519f5ba2b687f3c8c68f3ab4e7e18ac14ce1f74142beaf905805803fa87168962b9ab35b4ba4e0e87a2d73d99a4e5c8152a158621ebaa9b61219c7665bebf743e950a6a3084cc3a6d4412ad42e9fac8f212330cb37d6bead44aceb0a53cc3077ec56b76a1d4d3cf0f45564dc94a66385fcfd2a5d44cd618a2bfb82d6e9c66ff93915468b000000b02f0a536db4fd08da9c1a04ca7dfbecd6aaeb6344cbe6c291385423dad46175b5234e27bf730cb45c5b25cd7db9ceee8ca9cf26dd45194ccb90ef3bf988219aaf6f01d45d525e5ed7bfa30183fcfadb6c5f715e4691449e3ecdc6d1458ebac61072d8a94deb6b9ecf059438281feb210712f25512b17e9be25633dcceec106b877eaae20ef06bfa43a5dddafc1def7ba20d2b172b13147a9a287e4692f88f5d4f9901c78ede1069b45035a1fc996dcf59000000b00569724074fb5a91df766bbeb5ab82eaad0ccc0051a6514a05f00c6640ff660102675a157c49a877899a9bc5cb38879b4a4bb327d58a91303e9c05b83dd1b7f1da07e1cec9f448c05812fe4b2d199d06a04c586287ae58c9f2461e2286e5d71256fd6dc0144c2024b63bc3da657cd04a17ebf37a2cc6d6b597e4ca07566caf900e20d0341b1be9be34fdc49b26b6b18421550c7dbebe16c2418a7a444791ccc66509742cad19e887c96a89165fce7a7400000fa400000168000000b00d83ced7a29892f41e67f6aea5ee7b3825d2ebc05ce53b1c3d44c64bdc34a22db9f3785a63b4d03f05d98e6cc931dad87c1b919ffca46e0583429758f698623f13e949c8091eddd5410c664220aca841f9b62bdea71f13df6c5d9ff38dc71fa6bd1dbc36b7688bffa2947a773ab7c13a275a725e81b8a69323246e8b5390eedb832902fd238d77adcf52573072a72e140205828926b4187da5622b0c4f7dd4a65aead5590c2944b6d04275a94f278244000000b0259a212f37220c66a8e77e9ef68ea5306b69288ca20debc2f785b810de193e30f8db1a84c64bc4b95cec927eb03bf1d30fcd4235224f2fdb867e9520513fe0caf1595a598cd69e7173795294acd1f754babc1a6fd9a1aceb202b64b200373090811ede8be67037f21d6f09125617bb08014ee3b6e8428f8e5ce547ed205ba3497c1653d2ee2dffbf0f8726496773293e09a2b8a0bbc487883023d07bcc1c25c5661dd20d2477cb06398cf088df29781000000168000000b030448e38c0357204e49790a794e244e14276c8636d04bd07c8af983579f8e6d02ea8728bc4a347d2985167f6c8efa1f44f0a7296e18d7448a9d7304a2bfb182d92bf382267155f6c20e9691555855daa3771f8f3907b3e3ab8c4bc1338767ee81b4fa4192a6accb5237dfcc4d2914ab31a04a53a3edee6dafc9f4717640822bb3677a4e8f45db244d4d439718cb96ca20990cd39aaa5134abd9778279610dc66892b148541c08cbfe2f622d457dc69a0000000b01d3bce14929d29c1f39a13afef993127f701f53ea490169185711e58bc23d4058b75dbef531767e3a21e86aa99a9ff1dabad56f2b21b86a0f27470c466c9a42c827128417bb7a8cb94168474902ffd3033dc877f688f3ce82282fa925a5b0796e957ba5518e41e9402fde6ba15f6a689171928e85acd9b642932a563d9ee50e7b800bd0d7f23b788c342c9c8874359bd029b934893b5eb9cde4e8459f0d9a7a9ac7ae86608f0243af50ca11d0007dca500000168000000b0254687b0f02f23993cff900d9d423339c5346307c8d51bf093c1ec708c9f104e6672228f09b9b42c9cddfc269b5ed0760a356f5a24e6376159431928287808981a564f0aad7b935cb5edd2a0c0b3d5bab273178f90de8061eaa02e4f76afedeab4b4d6a61170534220444fbf727cf79e29bd9c12bae5d4d24a99c2dc44258a4d8e2679a0783fd18240694c33ea9514ea0b3da004949cad896ab4016f211c00053ca9ab7ce845b8b3e2ad094f2ab65828000000b0294181e1f9b6790ea814200e3789b6e4e420b0d04ffa697fc11c403a1ca77a1cbe64f3593c4999be68801e385ab9c47debf1ef30c35e18faddb8514ffdd57b6991f354d44a37cdaaf4a5778b26bf2f6714b78b7278a1188cf0c4030207bdf54b9efbe76af64a68193e2ee3e67c365a0707325af3987fe35040d42310d89d02546f456a1cef99e79958219fe9a647781c08751aba0d165f25c64b19455a432df02e03be9c763fe7d433c402cf1d8f57bc00000168000000b02cd7f8c75b75c8ae998a6c26de45f01223d6e2b8e28cdaeaa6a9d89b2914bc9172a3d3e88d2ebe51a1652b798a669ffe279491f7d015f15b717647257ca6f2e903fc7086f43a896ae837c3e755fdba80894f1052e5806ca979c806d0b7f1fe17ca0a301bbd1acca53e29219626a39edf1ea6ca64efb2745480282e3658f55fc36565cd1509d016b2823e0a8b0ebe128322e2a45196fd9e9c4ba6d9d32df0682e554310399ea67f863338758212985308000000b0099b3c1037268cf0b06fc34d08e6f8f69d072b62094161d237769cad734794b02f16b634a1be8e1e1b79e680093b526a48223a43d32f65ebb01513ec00148d44c5c1b7850cab67c6d92525ae0c83cbfdd48003229a1c87db46f25b7b2e392f7fed6148f64615004ec7bae612171b3fc92289cf623db9412fa9f78ca4a3da32b7e5feb13d6e9d549660766ccce969758a2ef89f78ec711baf106fee9d782ccde3ee39882e4ea0153249b3a3f4bc875ff000000168000000b013c81a59b11500d2e42396bbd4ff110f52399e9e716ad257a381ff539c92dac73e484cb6671e5e351eaec78e134981db03177d8b45d9dff62a170fc1b84ebed24bfc1a71e5f2739446f4c6d88e5ae872874d560caaa7a0895393b794ad0bdd9636c0fe1bef02e8ca8841d9d638651de31545c13f1ddd71ad4d73229ed9f21fedf3b493fcf65353d6ba5d2e0e98b507351377c71c346bd6298f87f7bda61973eb38e4921826fa7db46a173f5c605e5ca1000000b00f50122d60b1abb94d7fbdccd58103770f94ff46893e725b28a88a0f7cfcbbf7e3aafbeaf98ee2bbaa3fd35e16f06507dd4fb62767c2764052ce2805d1bc614e148966142b19aee3f01500b8ac4bd8b432e2fdeecdea90fb466ee85601d59987dde65baf9fe7718abb41ebbbb48293ee1cf74cb1358474a212baf1a6b07864c47519c54a0976e1a5587528ecdb95e70000dcbf6887e86b9a48b57b0b74bfd6e22dbd172b8f33a5e13a58bf37d9d49a0100000168000000b0188ec22ada703efae5ee94afdafb370ed5454160388e5412ec145817691f4e5b8f1f92d75d5d11492924afbfb3029683338d6765e2deb40ab005460dbf19f3f13f99ae9ad17714fc0a5146354bb4e2be80dade70aa3451b419f33795c9568d176e446e8b1342512f95cb9a1ae7b1b97c296816c0ce62e306ca507fae5223f29a8b81e4b9f10368884864a8ac8b2356131faefa0a86a015a640446a7d04cbec7a6b942e6ec79a5d3dae53b1d8dcf14e94000000b01ccd2126274af5b76cd6d10ed448e883329e0769f09ac1328763c211c2e88c33825af8f3c0b09e833771f7193c0b60ecb6eb0a68dea3751aa2b44158d7912cc06af4dc483851e0b77adf85102cd78922f852cf1d5280c1d3e60bf3e58535bcf51175e5573307f2c64e4813caac2a2a160a7fafdaac77761d465515d405ee61fda39ddf14c877591379b44c5f7f1e013514b78518b49ed9de57c2a4e08e7d859a1695e8fbfa52475599431ad6685264a800000168000000b01773f6c0d783f530bf1858b343f66299626e43bf786d7d26846b391a5a6eb384971fe47a8c1cfe5dc910f496ccb314dcff5ad2bf783377b76eb99c624a2448e2f2e6f38a84aefd0e2781dd4ecb2e60965442cec23d0d4743f9f66af080bcbbd5ac30430812d1846b8b33eb47cc4cf0ee1ae9ecd1a15d7a92dd0952cdbd44be2a70f8a9fb27b001159ef8d88c2692d10e2237baf5758c3f0478f4655e1a08201d1dcec97e4908061a4bb00e3e1de8e135000000b0014648bea868122778cf300cdbb72d434ab369387d0eaeadb1e8e0efb2071c52f35d4117305f2821421f93ccbd85164a3c4c243a8503bbe8137b572e2337107f2d24be0c927a5b8364235f09ddf6475e6fb141d076e102b3073e5c446f6122f116e5708ff7d9a6c034922ac3868ee7cb2d99f0d26f2c852c01ea7899522ab176e76407791d7a774cf4188334bccce4480cc135b9fe10069b38bb7ec4df37e895052248c64fa46e806dab6c2aafe17c8000000168000000b00381f309b9939b7558333509dac98f269d5a2656885a702daee2157713d4d8df9b9056f1023d31a1b66471ac33702aa139a1a24ecace8fde71d703e99a06f1e596b519b94b357fb57820662b38182874141f01186372949e112260818e337571efc3bb014f9b432e866c5f9edd08b67c2f4f6d02210465c271cb90a077fb9a199eaf6e39c34d056086b7925313c09c0c0a692f399cfd92bef20efffa4d2c2b247ca149743337df730485f52a440cac3c000000b02c81b134ee02b1d34b691d1b5be827a2639df2123098979810bf013dbfa628cffbe16ac296f9a4a3de1a09f77d37a603cc8ded4422b067793d6a765a9a371709aca92f3eda3c896a944969affe2cb1fe8b1fda2cff90f98dab077e26fadf949a5a56ec9a20ab67629cb691eaa3d9d1b60cdbedd385a1cf7aa527f575833f4731a559ef35589e3dd0e4757df2501de74c2ad29b6949dde4b3157af8f020336d8277891c9d1518276cc04a073d0e4fdad600000168000000b0071e4ba97d58f9da74106ca1311f6908fd18b4cedc458c32501e0e482d24e128a02dc5ba0cf072bdf9e38f561e320b445dbda642b7eeb53bdcc3b2305237f169e6e4f322ad86ad8ba76d1199742e6b5677ef1c73814c1cc7f823f0354e118cb4cdd97088718854efcd03e0d750fec9b9113f38eeca55f087aac09c94bdb42646e88683bc94bd3027b1611f020fc505ad2ebdb6cb37d1a145234721b6f5c01bdf70f6fcd53bdc660cbd4611974d79d37c000000b015d6349f425f703c98bc524e67240116c17276769a0c343a5c39cc76452ffff2de640320f8c81c3429fee0146c88822b18bb5f4ca2b8faab323601f984e598161496ec3b0614a5f56e17686978e0fd8dd71b5c90243de9780fefc66830545bf67cdb9b41be31fdcfa90644d67901c90414bda2373d5a2ec0718ee8b0f76841a6d332f9c69555bbee77eb37df1608f1462b701e8fa4423d71fc75f6a5d3d7cb73ac122c242372073e19266d502b79d01200000168000000b02abc447694de0e1023f7ccac6889bbfdf8369adb543f1ddf7ca261b3d34cbe16b7414e0b79dfa5154285087ca3cdbff92b4f816cfb915f9450f954e0273de40264e37cbef6cfdedbfeaf3cf9876176bb1abe57205e4e0d7e99c74f9f933a55afbf689e3172f6b28ffb00c8b84987952a2ebf20d955f41ffecd933707a772757c9b315bd5eba5ee877907b8f05fd9a0d430123e529ecfcaa434cf40b15310d82c6185303988495477f62aec72df7c26cf000000b021902fd3e59ec1cc3db385e4442441c299dc37c1e6866e85d2e6c0fb4566888ada1b19380134618951ad638b2485d63e40beb4a60e2db6fa518424f4be88c7b7810d087df8553b513a89069d13a38581c21c346e37c5a8d6fdb452762ddd1332a767908768abaef2ac8a4d31697528840aaceab306f706fb558f3cd3f6c8c733fa13151c88cfbb5c932533e5f9238fae050cb2b0c325a29631effbab4237d2c9e1f4ee314445cd6dd6db5804d2502b6b00000168000000b0122ebc0b3013682691bb7264b9909cc4edb0d13c93a87157e984a58b298ec5960603815150263297683f0504b3486a9bcb69d7ae8b4b48bb5e847b751b9641f72c35b109dc6bc8453eda247e8bde7732b1a735d2200a19b2df3fa24a567a673445668466a0b07807f68086900b53b58a19e8aa92461135e7177ca6745d0d4e56df9b581ddf8d202d2e71b00591528e6e0d6f590586e363da71189cf2e5dfb25465fa274d0a94031a61365002757c1f28000000b01d9a84a93bc0c2cb6896362c1293e6d2862c05fb64e9e60419dd5002685f6441207736ae83feeb8c04ba2fc30306c74ade26d5cf207e31cf257b728e9525c681f205e21e869a6f1d0043da1b4540261d16698e2f5d9ae03c762464dedb6ca8ce996a9f4d0de3fae29cd5a44eca38036f1d33883181fa2c21e27dc0e1fc6499cfd39a5e9fa64cc44fae0e3a254f105c5113d6169ed5e2e3dc6044f7e85b64efa287955bb79aedcdff31228b9576f48e47380000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b7370000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b60200000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000481100000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f0000000000000000000000000000000000000000000000000000000000000699000011000000021c000000b0224ec7c2b1b37e6007d6974a7b87344bd0811a307400c93747925ece0b9a1cbb93dc5eac6f488c5be1e92c031e995d9c3bab51caccac635070c370896e747b62e8824abeea2c3b71aa27c7b1d6acee4cacd7b70b1174d2cc5901377067c181ffa5661d4252bf30d35bf380a2ccb8280b2d0910be5a8df561dead2de383bafcfaaef0f38b68665584c1cc2ade7ad918610b5b0bf28dbc2059d5fdf811e18b826dbd0c0c070dbe30da63ee993e41ac8ec0000000b0050a8c626fe1a9404984e6eb60ae8904400eb11370f4daa5928f1124a39f31c6154fad5e4206a9471c862c83c7d1a301f27add33791a9a7e9d1ea9a03657b2edaa2c0e72d8cabd4100c3f8f002dc230e3731a85bb83688bcf63e4dbe797f5431639c180fb2c679bdbb9ea7befe6c96c42a39fefff30b5e010fe821c26ead8bc4db1288f2505432a1bc7b118b77c07b8e2b0e748b346135c1e1c2420ce4938d268b86e7be4a04c2430049e5265335ffbe000000b02fea155c5d68cd354e9b66fb8ffb23fade2c3a6c0e9bc1fa33e3d1a49a8fb71932d7e60c3b4289375fcedc3dcd4b1f8d77ef021dca2ae9a0f9d99bc9c3358fc89b0d07d8ba50c6459dc788de766ccb9fb5935145aeb80cab053e725546cdb0a86dddfb41e95c8ddefdd0ba521739145c1dcfeffe2e45982a1348e76ae3f78173f122b7bc0e05b3ec9d7e9f41f6dcf4d1179c1270ea584942aa3df0ec3d8b5be39caf18f0d1ff6e1dee21d790021f3bf00000021c000000b011949846714b7ebf644ba3a5f73d621f5e0e1e359a1e5ea53ef522edd0f97f3b2cc1caacd5f88fdae875ce27b1396f3477842bc106f0e15d2f3553411f31ff4a6cfc809211e7a40bf555c0414a98c2217f744804bd5845a8ab6906480b762f447ffc940f9384e001081d9d189f0025eb2d71ef782db7ac33935a289a7d939862143336b1435b5941eca40109109e7ed92c13784359cf367d10ca0ea07b2d2deaa052f7ba06cebd24cdd9911cfad0d932000000b02e051993a495652f214c60a94d32728d3618a31ecfb539550c587a169aaa339a0bb6b9ab623d945191d4f1e03fbf1d6193f84eccca7c34614b57ee3091334504e336fcb819bfee804fe46cdeeca853d65acdabcc53ef27853bddb90741c564bef404fc724d86ec34b3f7b76f6286ddb917ba198f86e139e7f75d99d156961bc2723234baef29a4bc86ed194fd1904c0f1c8516f96c58ad3a4c223e410db7a38d6aa14518bb4c805327401c844c8397a7000000b021251fb1b684122d9b71978e6a2222607e3fccc34a918174ae3161eca14fa757b4580f59945104a52e19ab36c0af276c4ef806c9e5efa2374b5b64072cdf5052aa367ae675d9fc6b1be228931cf1a8ed565ad81408eba6ddfb103827ce370ed0dd2bca47fae0d4e7eb00fa1ba5b2d6e207b8b2290f1af89b8e4d9d417407c6af4b7fdc96865405debb09b7913f3d5146103700298d10eb0b97b9321950ee75f5b09413c44b9753307205d6900a99ead40000021c000000b02ba76e380ed514eaf6cf43648b98a86b38feb19ec7a6901ed169fef414e6ed64fe39c5d5f66a0de6990b3fc7e88024bf22376c3b0d52c223e587ee43848f4b88a3fd469bffa8f989d9501562c63ea93a05300d65a1398cf21227845420b06d9252bd2b781846220117c43f66573747c82d09ca67c6f8aad29a48334ebaa359ebcac75573839f9ab9070dd6bbcdd8e194296674b4d233519f1bceccaab0a138e705562445f1bfb605832912dc86ed5482000000b0016722d5c36fc5bfb60b0d54f3993cd64309b504a5fc4c67efafd536dc52528a7c0bdb66dfeebf8fdb3ed82c3bd69618153ecc110e96f39b74e1166f8a8d9070a9e0edc696f73f4287a055a80c252ff729f2c11f12345394613cfbd650a2b116f131af1586535f87f25ffd7af9a3cb4d15bf3b256bcf47c9e82aa96991c9e5aac9a79ed05144e21fa27498fb03005f5110c2992e13610967927bcf5a86070365239978a85b4f18e33cc498a4f1bbf468000000b0085e37e48885b91a85841795ced74cd60aea13a3eeef7c4882e08c831e9e3cc37600b23b6981d61c9c12ae1577455581c53b149d1a80662938c14a3016154ab86882cb8a0db1427ac81116cba990fec87089ba76d7d130ba54eefc4a1cb18a91e52793d6fb78c17a7fbde46dded13ba52f3d36d25164dec7a68436c2b4b345bf4ef2912c7965fd696900abdfeef155740402c302a564ba8087de176da5101dd57f9c4ef76170b8cdd4e0eca4702423f70000021c000000b00c299584089af354c9f9a40a8d5b2b0adcadc91d91d77ec54e9b8505b1d1dc66c1e93fb03460bd4a3388071fee168a3b3d3faf00f0e150fc630ab608aabe37c30997527a7fad74304f68dd4a2786a696a7bc6dbd7008ca976023443c502bd8c4213034ab20e469490bb09946f30d04e1125dc721fad4273aab7e31886253061fc8267eb387fc464cf6417827cf5091b51e5eb73ea7089b1153eaa0416422676350e1be6e92a0222ee2c2a922d4d9f8c8000000b02c5cdfdc38ac597ac1534b45c59e6459e2939b649f580a30f3db4f201784773cd47835e980835e675c9a0e1044842fda515849014b93f796f36a5ce6ad2c3cb9be54f35f1f4eb4110f6f1beff69370474c9d66e50058c4804b44fb9ece2de5d58cce7f40543a4dacec0ab1055e9c3c71244d7cec893d839a9a36f25388908996289843a1c0cb6aaa3db379edc8802a1826cfd18c6dbeff6fb31a0d9b02709702e0fc184de5871c3e3dde2022994a0b45000000b00b3eb84e9a1bcd9cee7fed45336432a704f6126edb35734cc8575e92b2c1c7da89b6f213f174b043db57b47f23e0b7ab1a90ecee9baf948753962415c326bebae86b44f3fdf1308a3a055d2da4e89e9900f2780074e92abdeb76e60c5613c691f09b99774ca56fe09c190190f00544fe1bdce0fa63d108d9c5e099779ffaef7d05deab2248e19507d3b72aab0efca87112924a9ae03aa4b41f65c27f5eb0192d044d828ac1a0385708b6e32c0808480b0000021c000000b002d8e0db7ee7da9ce8f08e41657512ac36382625991e74f7e36cd46cb6a0f03cbf9d90c262796f03e00c0acf9028af1244ae895b4bbe1e7a07b630c6fb3dac75d0cae6ccdfe5505717268994ab11cbd9de2cb11dcc82122bf1044bfd19b5a012be73703c7f0c7e7243bdeea127eb0faa203a1e3c0e386b8c2b19c9a398fafe3bcb4f99eb8cd80ebbb5b4f9eb1204ce0e102e58ad37799ae221d9e5f1ae0b6c54f4eb64180d9112f0350060cb08a8814d000000b024ecd1090dfbefe4fcd3ddee375cdb9c8067b13ee3182eb67c340ddd1d55baf2a6d0871c970d3cadbce22ec0a080c4daadb8d0e7dca4732e2994ab21dcce56a105e3e235e8fd3cb85f28553619f7d32e6fce5905829c7331f31ff3723763ec380141525e6d17d13fd0dd74f8555dfff204dafc5791e208e87dbbf406a6b5c5877bea345917f75a1af416c7cccef795972f9e34ee3236bfd4e7955d0e832f42a5b1147fe81cc5d7e45515620208024e00000000b00ac409101ffe949a022f078f602d6eaa8ce9dba723c6d9151bf9ad47b26e671860974214480a97daba66b871c6cd0efef241524b439c50a286e19929790d1bf50338b8ec5e666287aff52e065eae8e2ec0aa91d3db9d25ea90ae3012ff0f655b9f6efbdb860cb983ea534b26b62bb04026711ce4f3977b25bb0c6fac17e742c5f5c6357b9807aad5ddd519c7d234602920f32613894fe1835813092a10dd12750f10d44f49c5ba68a73572fe4ab4887c0000021c000000b02a7799c6d11c974b334caaa0e343684c98d41e46fcc8d1402c5db9bf2b25dc1cbcc7e23a169f375b23b236b1b5f4afe57e88024fcd1daeecec35122a60b553a5b2e448bc4884794296f5bddbeaef58a92eb809ced70fe66f60899e732880974cbd654f4d58fb6a37a4725f0579f1f2512647e1b2ea3ab0c553311114577e3e7606c99647b7fae0bc9efa4a2b0eebaf15253e11e2c2eaf2061fc728b5d0b1e0c4b5e0523a4c2c55a505eadfafe6bd0c93000000b01aecb37c8ed0e0490d2ba53a9e8f0162eec3396c9ef8c28dbafb167949999e4bf7e5c39d974e540acd17c6566690b7237191a42f9202257ff47901bcec999c19256a30a55a03a080a7f7ee070df6399c6f76e45764a3fcd2aa1aa203d65231ad238de70450faac96ec1fabfa6d95e98d2e645e3a6d6e77e88882c50c77d486c6c52a84bf565dbde9306a59d36c33140c23753618b352e3426538df87de4c98a43a54947b9bff27b2b4c9f3660927c04a000000b0239d12d5c084b1822912e7a7cd998068933aafd3572dbc95202af3e6f61ccdfbaa7e36cc84df6432110e5df07c4959705558a89f69d1dde613a687ccde9fb7017c77e77113e857585452d46f46888de2eeb32c95ca6a447b4737395528577a14eb8faefa51a9b5b304d44b633d32304819632a9f10b6553583664ed38d092240e16bfd2e30bfeead1bbc8c6c85f686a207a4eb0e1dd6b80b85d29249a86a8c7dc0d7431b05a46dbec1389d46336b4cc70000021c000000b004ef73f190a1d4b30b7613a0be6377050a1293772e68892a37dc6faedaa010026780ec12d99aaad3226480dd362b4461a05c3e3ab9aac851818f5d4ee4480384d82faad6415d57b89b4401b782bbb6c4d94f63c77cb03c31d0b44bf4c998730e964a6c7dd67d4e498addf4badec86816104585efd42c2cfa600ee05aba46f6c9f6b6d72afa4ba2a07b2530eb18604e77230a6ab78fd1ff1c247d9ab1f445ad4c626631fe4b3db913a635257566521b56000000b007b6a088be0df5198cc7f5b5b7057e360fe2a46bfa1ae43c33c1b11e62565d4c8ed2843ec6e9001d8d101ea8453cec6f2dab28c9e11f7b8627428cf6dc7fba1ff4fb6bb9a2418db49540b2f7f419d651f734f0de0f0fcc8b3f9e80dcf4a84b909040dc283240137a0b38ec3449cf406c02b18e061f142cb01f54961a6337964f9c61810a8ff3853030549ed5d4d0112408500da7dcd1ca4befea6e039a5841e1ad1afb1fade0b2a849f3b760add4ab14000000b01faa802e91eeb86e49ce38f52fb92bc345de0773c4b3028cab3b4623fd15d98ce1ba9d78ae1e8bef2d9410c13216fcf69c62d5b2f7f5307f8dc23baba507f61f26be80a11c4bc584c58e78148d2b2cf5b86a9696686a259ec36bc1f2d66f88715afd36c82c76235094081957108e080828c7b78347c58f4c2670730579e788b723201d79d76592656103ada83b9f52f825f1b97cd2c30188214f0f5fa27cdf062f855165cd85c3aedb45cf2146c2a40b0000021c000000b01da368fea6284c0b1ac7c4711bd151200a5288c2540f0844bb61b594dfabfa92d27ea2a3fb3cc310a32bbe01b23ab82380b4eea80b4371d26904d0e35dae0a523efe484e1fb6dbd0e2b2a824e39fe4705d2a5f77c16ee9d5b61bfb0f96a2651c62f77e711e43799e7b37832cc71dae9600075fdde7162d726d7177acba15deff2a0cb5f909a8f69dd466015260d778cf10663763aa338285d025ca18083c06392db22b19601f4f451ac3c87fddeaa37e000000b00a77aea26e32895a0f35ca8f33edece1bedaab0a47a6d2872d3b3aa7e32c0a8c54fc985ae2c77d348263a41b2f47e5dab177e4780fe58d40c19b1c7f154ff47ce5437906126d24dbbdb2eca0b1f16e9868fa8152fbf82d5b047bdedc4c96cee371e0b717c3c4600d1cd1da7374527b8124af1808d6d3b2da6f4b41b8461f693cb614686b430b89d546442dc9fad776e12db3cdcd0e0a0808dd2ed4b9cdcb29ac1d3d613990bc0b5c95fa3601ef1a91b2000000b02b9c1db685fa1533181ffa7e2cc931cb9e37c9c2eba3c8b7ae3338d939b8e7d5d0f8e460dd6cff82c3dfb438dd0aee7ec7ff402ed6b76c2b2e063abf0cf415e3350d1bb097e7a5d1b8d80d0b762f51030cccc62eedc8c2591461973519db94b11ea9e7b009acf748da611c0f02a0bc1f1c744370bfa1927a8c42b32295469849b448f7f9f6a2a23c3648947e823d4cd41e4949a64824c276ba3bb5eaddd43a2a161cf7195a989aab9f9ece53b52a945100000fa400000168000000b029071e3777675ccf43c783664411a4536296b2e3f2024b498fa6aaf5d5108261626ba93e410205cd1cecc245a191d28c9ee45b9891106844903595edea13670735295dcbcad66a1a5985fb507eade338637fb6142cd931091e02a6cbb3a8db4ca8f4650168631418ce033f8a930745e82011f3c5d71e7a29f2189ad77890fa4397bb97f605a3f9817c25a06cd8a0263e1616b32ee26a7401795580bc76a1308cb9f393f6501214bad860561ef25dcc76000000b002f6e362183c1d0bbdb6d8fd9c6eb35d583632bb10b3e7530d30d072b454fd7972f54a7625f8348b4d304fed9247303d852b5638e17eae8ff1fc2f3dc7780c17e4361f94894a625f64ee5dec0f4dd109cd7c201777455f92400af0964bb45676ee846b5a8e93c4f1b9a1eea03dca564e1854303de151ca31f53985b04196c91df6969bfc2d25bd997f279794353ea5112bf6bfb6cc95428ad8e44fe7b900403d448227888e37c2dcac4305e79a1ab41700000168000000b01abd3b7fa2a5ac5883b3a763b097496d9e6d7720074a265d042dd3ca4e7f517429afaca0ffb4c30b42b7244294d246abe1284459cbd0d5478ffe5cfbf364acc2c3bad123dfb54d1248d3c56300aa601f9eb91bc8e5f6591734a4f8c57e90205b964940daf9b789dd2618d4f06958fc3420a8117eca28095fe1a4dd26aa7025d0292289c922f62b6b1e3a9ea3b429fc0527d7c63442fcf304982a24045e7fcccc081e68acdf02066a26031d55d24d6ccc000000b0080cbe71f692d01d39048cd65316e0e2d9c21c469479c7d6a675d9ed13a90ddbbbef866a9a79e14d6f86e32c7d66375413bd4fa108fbaf265a347a2ab3a6366aba861c63206fb4c7aecf52039d9015e33287dc64a37b16f643b720377d84f54a9d4293a1f207b786651821e5a526209f114d92845215f73cca3073b0a7ab83a09d3e28f9a7b5394917172ad2aba9458209065484e6b93b52b48763c0286a548428506317d625e2200f9fab88b747c35200000168000000b017ed0309bbaead176d4d1d1bb4ed44b79307db0490c5989636b1c353fee7cd3ff9bd1a259c54392024c0b61cbefd428591a210a223fc5c314376d3f62854d1bafb59817741c2530095f90d3dc1977addc03f34264e4c004ac2fd06d63cf61e6fb3e8fabe3bef2b894f2d60795984835c00b448e09a5dd8d8148a009d931203884e55b1c45faa4f7d034bc52140084aaf17f6d59c86e69948c4e6c053ba98e991bf0c1c132afafcbcdfc5660ee39202ed000000b029de7c0421d772ed7f9ff46a230356c3eb076561ab77d5d46885db87bac41340ce3f47da491627993ead1a438252f958e85cf7c59b31a0b0f84cb409c0b6772fd6193ea38b5ab1983ef13d3cd4108c6f1ebe25c6a525a7dad52c771a447167dee1d079c9d72aa9b930ef1e6d4540856e143c2e038ac5e0c48f39e2a2cdd686e6ed2399f615ddb363f4f90c834e51638907d226f8a053a623030320fae31d28a7d60ad2f827b8831f6f97083ab63ca45a00000168000000b02df822d92fe3b9e56272ac28fe2b83a4ad81b44371f1acc2718db3c76c78191c318ecf7cd4220bb7bff163bffee729b9ab2db5124e6bcf934fc5e85a6c317076aec4b8d37baf9263f2dfecea8eddbf51650558f907d5b7ce5a6f4eead230912d70c66265c3d74c00a8777260bca4e7cf303be607cfb332b18e77db3df8b20eb0a0c7ab6500299335d7dfdaf4fa254bb31dfce978f6760045d1a363e228ecbc9f56e606974c4f820eb093515e4a75365f000000b002d2dd2302eddd13dec8e7d76a3fe477044e620ed6400686eb000f967d4416b16f94662754cc13c59b93f3f69b68efaf9a86302108309c09234b5ac52cba5eea4898c8c33ab5fb28842e3a1b775ab9dc5c45db32b919cca9f953af71e9340b0b616e272aa6586645137d0358585dadb50e89ff8c0ea94c60d5493734a6fe639b87c08488f55ebf2d192b85276f8c22fd22509a02785f1743f78bae9a3ffe58f3e848fc3df2328f7c330251c844a2d2e400000168000000b025f4c4bbcb68b37a0597aa3b7769f29b60c3fe5189a4c35ad117294640be748d8d1b037512916704d8ed77837a916acd28bcb7bd7681906320c5486ddd74562092261ca6f16efff4cca3b8aae4f37c4c686f7ddc96aae8aa7f2f2879082c313a5610b74dfe4ec469607ff34f68216fc9165934ece363ba2ca369e783b259f62fe39293d07840253e4104c44eac59f71c14ba9f3929c52d375510b51b95bcc5f1ed7cec66b525a0117acd8eee3fa8458b000000b02348bce527275e146128a2d4b53d9b609fba91526fe75e41ba2c662b94c8c14ee3a24b311884be5ea1d6232ab1b1c37b614212288bd492bacc32c6c4594efb0e5859de3c0539d0410e59ab0eba31e570ca0f6c94702bd51b924bce1bc8b938f692dc48c563cbc9635d29b8051d497bc828e7457d3896964087e50be9bc78efc37047f44e873899f64ba988b08cdb4eb8026d37dd407d9186b6809e2ba3f009382c9d0ecc9e2e3d76df5e2f6cc30c6c2900000168000000b01c6cfb5b6a880df7f554fb4a08e2bf6d4902c7b8edfbf9cd2165cb76103af9b0225e0c5199e411b5d5d4054359966059ffc6487c7608852d4d4fe437359d729b44a0243887db5213d1e4ddf1b688852c51b05a775a04ea3b0e916358a587b9e941d7092bc45f74deb420a7e900166e6f108157caba241c732f0993b5ab9a07f08ce6671919fec856c957864193bbeef60ce24b2a427b4fad9ef18515113916252429a7c14cb0a607ce4f2e33ae3ea431000000b019f6b2f5beb736ac7258fa2c1f4b84bb24ef00c8454a3b524ecc83dc0f1ddcfc915bb21ee902dfe10e6bf1e9820e54120ec6d99fb052fb6e9898043506374bf5b6c5e3ef16e1ff75c14d9b5190981bab0c8dbd019866dd4caf90a51c8698183c97b432747f7a29a23b1bbd75f90b7137132d1f8a72edf8dda4261633acc125738c34b5227f272ba13d1995b2de8534a7118fc3257d916617c5714f13153e062538c58d238720328111e127e197ea5d9d00000168000000b001be89d373abcbee7286aaf2ce233de6901a1dd896e186cccc94653a3f3709a35a90d6e3a63eae08eb8f7be15296cfd38b36c15bef0c017f83820e9db16eb0889853edb55ff56eefa16d1419877238340d1c75cdcbeb64e2db48a1ef2a0b80cdde5696c6a42cbe876e80dfa79623cc3e1b2da42f2be111aa5b21bce8dbbc5cfcf7739ddbbf5c2416def0df7762d972261eb7207f7ffb5555b768492eac005babd81120845c533e993f06b05149c3fd00000000b02d86a5d07cb21dd577cd4c8968207d278431fa86f7ecf940b0e59b80086afac8df02f9c49ac46bccf2c7d6211fa2384bf4a5c6cba0db73e449af8a75ea28a34b8fc7a6ee744359f75a8938c26492baca32f34871ce54a7a01c74011de90a7da1e1afe020edaa5aa71c471f90f92d8b27107d0634a44243d60950f60cc50c983d6cb740c41a4d1b9042315ff9b6f2ae2a2e4edd4e8fcfd6e8d0a8649efce0f4605361b6d4f3f6d035b57dcd5d241ee75300000168000000b00a1c1a17a463443d33eb36906ef8567e07644f2fd20dd9a37bd023cc3adfa8e0cb2395b1618ec4b96ed1d170e61bc27c50c078084f1c3d2506c7e0ef6546ee0c63c7896835263c8a8a85abf4023f9d1e79a47b4c623e1c32efe0873e58765a779ccaaba723f843606d0cf3ebbf5d06f9241b4437d69f0861b80f5508ea24f46533e05473eb906c587c2e4ca18e022cee0856fefcd74161817e81a4b7793dceab4dff5e56b3427e8c6e8062d6b2757586000000b023747f71593770bd08e3ed103001fc0e308b26eea05d2babe55a2a3b485a6c76915aeb94c8c43257ffa2b48d427c058b84bcfc05288453f5876ab1aa942f30a3bb3d049998f6774e83d0e40250f305330e267d51eaa1a72803ecd6874752ef6e3ad8ebb63eec7da62bc48f866d3c9ec006fc74a544bd97e2346d8139081a08025ddc2ae4329a8f36c4708c1c12f12fbc2bc3d1e8aa1b0a1db9d55459ca36fa41711ae4c977b90be0356302f0237eff3000000168000000b01d55558b884524ab7e7b2d666236b54c23b281beeca2783f2f9b96c301e9cfb4eb1b56ca1f4bda380f52bbb17add067b62538527a694fb39ebdb92d55e4879bb269e2e03a7ff1e26d647e25e0a5c07f05301947e3de36009facb9ed29d380c93ec0ba98d02674168f646ef1f9042020228139ec36961b2c7e73b275cf75c55aacedf2855f30d9abe4330646585f8cdc51778df2118cf7c59b38ea2fe4e16c1cb04c35a9e69fa93b8df8f3edcec2c9431000000b0083526e4d49653ec0011d56ccbfa097b6b4158cf4623fc48d01403d11499494ac98450db42bd022e96bcad5ced3d8765cf9850f4a4c1b404cb3d8f6d33b6f376cb3b9f01e56bb920868644c657782ca12ca96e7dde4e568c790c18bcf6dd51010d395446e91fe8bce92c19663d3fd0c22db501768f2096d747937bfd971a0e4f339cef53349f8c2d18236b5b374e48eb13cbaccdd4a777d3f2997dce2ff298e97868ffb24093f77c768f5209d0180a3d00000168000000b003cc87d3a82ddbfc436c985f1d3bf84ff98b8a3f93e4a6adeccc23dcaa2180d6a913a433b6d497f8159987f78f9f50b272579757537fe518bfd4a39a9577c4588c1cc7aec4485acca77fd9462215376ea686bea784e4a5f6fda9ce951bd6ebac2cc39df6c26096e69b99d2c1296f0c30305e1ac9c14bd90ae9df43a4a572f57f87edb0cebef2c6aee59af4fb31dd0a811ebc8121fa92eca3ac584a22311fc4c154cb9a8bda12471894734a7c8a54821a000000b01075bef06858e0156fd32093600cc9028f6aa12a2706455fd674f1144e9de3b110db8d7e3e9c59bec215b6d8bb9ac913b837f711b4b0ddec2a704b67133f9fefa3e6563a1bcd639274f0a60be6bdf537659986d53d49fdb34aacd1f65cb1d0f2e3d4a01971ad702ea7cca81238f87d1a297a4de9b92cc0688c1d7bf095c9cfb98207e94fe65624da700850531b123a2209c3fa589fc1924f5099305a02c5c3f41fb6c83a4d6b0e1f131f2da8f91e715f00000168000000b00fecc375cd63b6fcab408b28fa927fec11cc02acb60838c189f6d56d058989fe60951d9df77896b7a671624f6a82a8ae482afd71b3f29f3acb87f86fc212c276a71f010d8467370f75bdb0946749578ecb1c6c7adb6ca7e67f3ed000ca3be85790adbe105f1d43dfb95e5703eb7fb5732dfe8518b10b78cfd99ba50ff88c2550c838c25e22c44098d1f34ad2174ada3a0d8bef6bb4340271d5ee5f7f7a9cfd45544717b01ea8f942e1084e984ecb2597000000b02ca9662cecf693896bf97ddfa259eb26dc1ef6d5a1d6049194e02de3ab29f316e37cba3d1a7ac14980e0732e980355bd700042bf113bc270e097156d122b8319cc8941e15a829bdc2016e1dbefe64716dbff2ec859622862032b09a5d615a6ab05d2f49fd7a7354ec27c299a8f9a868022be65d7f438c6f38dae5a17e90d46d32cfdcdce6212d79201c68c576940af4329e7be9f4e21ddff4785c9357de4e3ed5548077d904b32567bf7c268a1f0445d3800000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f73700000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f60200000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c11000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d9000011000000021c000000b00e91e5660f1e83363cdc42f6c64b75d29885b70ea6793ce76a0c309097b88257d9f17f9a493c5c217cb33cf5a210dd95c02de7b06f4bcf66ccc3a80692cc6b9a4e12aae69781e01b4fa9310f70d79af2a431af5d81e0bd5c352b8c01fda4bde8d738822d48ce6148e0af49da61d572140e7917a4b57a1ed652cc8a5ef4e910d5d1355ed76831c8f71dd42b9c061e26460df76f31d0502b792161b2a149f5b36c2ece5d3bea3e4f043febbabdf4d74fc8000000b02d2542f6a5094bc932fe19bdc3417ab9795162872859b74017cc4d85adc22572001f65a46ff7341863e53b64821a69dfe62c8819962751c49d0aadd53980e35b443f152bed55d90c2b7f471af932e8f148ab3f420d9ed63ad05850e054d03b2f634c21a43a000d41e80c1a8554cda6782da1aeff1e6d244a9a287a8f885f372d15e09730cbc176b2083216d8eee2663d1a2f0fdd709fa8dfaa9dad82902fa919d28d5636c7044728dcb1aed916c6a72e000000b0034074f9ac74f35c70cf90028d3671cfbf73ee87192a17c7ed83da4deb3c8adafa081342160722e124d31f4be8ea8740d0084d7117e236a0ba2810fcaf93b7dfd3853320f76b0c6448a8085ed44fb7461ccc24653bc0dd5b9e3c7481d3abfd56d819da15860251f2b523b59b8d50a9dd29d44485d1071f828e00482a115a4314d0b1f4e538f3a47f2d2bc3cdc6e541311c4ee3e776da93f5b8e4eb44ee3257ba513c8b007a452980a15dd383dfdb98580000021c000000b00ba47fdee0ed223a059a604de00aa3c68ee8bfc40ca7f2399027ec9f0374aa75f4324e77920457c38d48784987a0183e09986ff8e8442c5bb5eb261ba71663f45625f159e377f33e537d3d5c030965727a04b47c1fce9c88d3f371ba41940cf1e7bcf0a4f5f294cf2b69eb2eab8d92c31444d60e89429821060f3b11e3d806d5769990460efdb5e9ef7bdcbc61712cf52e6764607ab6866676ccb926b2b90d02dfcb892dd66afc555fcb959e0335a847000000b003279b0ea84d3e719c963baf6d6c035a50c3add4c7a72f90fc0f791edf35f1630cb0b0fb67174bb40b7121d776fa5bac22d7daa7b81bda312d1afec4ea4bec58cfd71df522e807128a9abb76977116c64d40579f785c77ad6cdceb0dd60715cf1c4f96407e239760ffdd0555dbfd2b2f171007e0e65dfda7e1f28fb9b0332247ad6ea20bac00180f75c7a17ada7a1a1818628c000a14e3446cdacb44b5b5c6a344e180305185c7a195358df9d16efc4e000000b00d4deb56dc69d4d629d34d71f3d849080f03b556526c5789f649bae84f076005b81aca5590c60f70ff713063425bef7236de602c3e87abb1dd920a7fea982e361db93916a322e4585f09b9607fc21598347dc28115c6e8982f3e85a61ce8f5dbfdc7ada9f5d4e0c0a0651c0e2e487d27159d76daa98b39b7e8f25ec374818da58d2ddc14c21f0ce9ba99dde413b583a1112d3eb5b153d3214d665965c0230311b25a0e58667c49725d9415f36452ca3d0000021c000000b02f13e4bc1fde6416f7216410dfb9d096f94270c8bc13899ef2bce32017a01a4677fd489a065172226211e56c4cf3ca540d18a1b335605fcf6f357d20eade261b8f92a010bf8d00051d9ced1527b913aaf2dee558d7cdb34a750bcf83d837ef63125ae3ebc6f5463c9d64a64dade3adc60a3cdf63fbcc7a5dca473c39e3e490d82777385374ab4472d80891aa88f05b4f0faffbdf739014df6a14805d435205cab382b8de1c2e5b7eaeb10f22c2cc3182000000b025983674ca296e9a17be9cfc0f273a90b45fc3071ef78b03a137ee4ecd2b894dfebb63b2012d9f62680a6a30e7339ebedaeafe55991130f503e9a40cfb2e837c6d896253ffc8daea5be073b9281866cc1ca09ce8df4a8da61fd11e4d36870ce14260cb5f488ef5a29c54de7fae7f47a60c064028b4bc1d731ce4b11e3f1f62a3e91c3be3b319aba85ab9febbc0caf0bd0da0a6b76510a90de8ae2fc380a88f4664c62778be854e27aa502389f4609c4d000000b00a675282706bf33dccba1d21155e818a20e1f00a8c6a4451a6683e90e39869a88d053cd8614561cf6110f72d36fdf40e6ff18357da417774aa6f7abc91e41dba043bfac52980ffbb12865f3ab7f36e50facdd4b7a3e707f97ec3b38cc08d855a373cb7e92f07e415f5d93b7e326be7ba06c31eb48f8482eaf5dddac5077d6bb18986e377525075baeb3198fce4e2b9642d3e18081b327c5ac4725f221b7b819635ad2e53697b74a8391c6505e2f89b2d0000021c000000b01877efc03cf0fb2a7b4627f3251607542cb2efa139bf24e5a633508705ac0d54f50cef5e83ff321ad9b666301b65f200d92c3ae1396268f00b59af01c0ca1e0bdb81645278039043f25d4c7f1a34ff448b765c6bffe51323c341b2b77b0f8b1c9575d6069c57761740b4ebd93377f0a013c06c0daaa82202ecdf570c15f95f4599be7fb1e2c30b2fd0671be5fb1386cf25404a8fc762eed49fd17dac935ced0372fe0b82de3bd66fc5ea6f3bfb29fd1b000000b02095b02f1863b2b701b1ac3a8e6ca3e8638a3dab08f8ac903601d3980178425ba535650d88259e80a09aaec9060c4a16562d090a0836274c2e2c2fc10723a43fb797a222f378f99778157d8c35bcee96650aee13526d1684bb479e983487a522baa52dd6a90ae6e8d68ab921bc652ce623423fdd91523fc125c580127fef9c75d063bd453c3d5e1a8fb8a2783403a6c2057c560354bf2ed4c026e40cff08576863db4d90f1391f53e50cb10045c690b9000000b02bfbba346a8985f12518f6e86274b5df0ec06d38249eafcd20006e3bee44c3cb097d5fa45650b9c256abc8659220cd206e1fbcd98462b89e4b949e7b53f4c1345fcc547392e9ebcf38c678ce5c2a3c1cf059ccab654ba753a9359ca68cbf0692361474073d8c2f39cd2a37854dc1f13001c99b0683b222313548ffd2f464256d0e9f993efb9a51d57efd14851aad0b6a0639c25f865ad7e8914ad65bff16c5db6148ed6faa17b0e8e0630843ece1010d0000021c000000b007466d97c33277a16c3e44541ac64f032fb4a608e47d8826bba217220cbdf9b79b69285e97e7b49147337c9d5154da8c563440c0a6b27007bd57919ec719a6e9d2ffa7f0f22e3435a95a1e0e340aa3a33560890dc58c053e2e508add5cee11f079518f026a30dca08eb0e56274b3ed541ac8f0bbcba42800209703ed473949460e38ee36d02a2ef79689bcb6b8d746632144525589738f22d766324bd9e1b529d33b59179e99a89c77c2afbf88ff115d000000b014c997c4cbe5150388efb05921216a96f3b21cb434a1949c2e58b506edb35e29644e7ee3e3e275aa670a54112ba0592785fc904ad5185186c4af258e653f12edd886bd245d2c1387eb53810a34f38fd7437f17dfb021f265bdbc36f10d51d6369d051a1c5af56584c8ef0033a9667d79229c889d3beec357018675ebc5c2f4f81c74c3e3e3b14c75f7971f147ee4787704575682a82202f79f0af2f431fe1357059b6aedb951ef094f50218396ce5f07000000b0261f3eeb6f6b8c203dac9e51caba5ad4eed08060d4559d4e9ba66c896a7b87ec01bba35463d767a5534239c049aa7ada6569bd7f9c2c7c0297408362745dcb26df8b2b9bae1c37ced2efde2d6bf825ee790233b1c03d48ed96222fa4308b737da0595a46dc922567db81851ee305283d1f85840a87340076fb59715a808ec2a11207be1cfecd25096b31528ecdb9867b2595549d747b22d07f3bad67a2113661e324c39c3b6b03065dc9bddd0890e9cf0000021c000000b029a92f83f2dfae110f9376e3ac3a360cad24437d6bff64492957945225de37f04a76080f900f4918cad55d8207d23ab5719dbde40211a2f566e218fcf7215aa2ba8b04f68501d3f4b6bf9f8c9ad21543b7019c98341bc4408638ec089b1946c0eeb972f4043b71eb024efca44a326a781c0bd876ab39aa13e53fe60921fd74037aa55917a924b3628849a0fc4e92f5b70e256ceb91224288fec0fc9e2a68a641819870cc0a9e42c6fd3e077d12cbdd3d000000b00983c5e8f3c7ed0bae06285231b4afe725fc69b664c8ba2933480311ba3074526676b7f78f24ba5faf98b3c1bad689230e09ef58e60d097595ba1aa53a117d65f252292d7ff88b1c42592c679230d5cd740889e452b360563b1fb8900106b670e3c46ed84009fb6ae7d6e67c7e8cff7a08aaa583d83dfbef22539e5adb44f28da75635d642152380c06b697a505d9aa8262ed0944d33a0de211416b2826bec479215cccbba4f940e66283ae43da12fd9000000b0094e1d8012b07bad52d9e3851ee6d7c72ec4d878591f3cc700e1ea5af03bcb6b7df5b4a63d4f080881e40302f218d63bac8e21d14a811703ec0a91561efefa49171d360d57f2a99af9d8f000accce2595a982b223f07dc70c5a369fa85616ec9af8d34b6fd43c1437e8e182ff039c43607a7e20af1e4e08873041011959f49ba94a9c32c906ff7f77a2dad0f55d35ea7255bcb9e64803619db2f4ac58505c511a8da7757f587a47db77d000a7f2ff6ae0000021c000000b01eb4bb010faaffe659ed64af195337ddb667d35138d0fb0ac76aedf9f55e26f79405d602115eab2b1edf651e42368e17a16ca009355272bd38d9b7040b5a3c8643c7d7421a61f5979bbda01eea214bd15a1f5663eef1e991bdfb2071f238750a95e89a5928ca6f4e4a9c875655342b931a34a5a2b45fcd7686bacf46a3004cfe57712cbf6bb4ad9f90d1667a24818bfd2ce884a568ccc5f8bef74619529265e604eb963eb6b5fca097e17dc189c7dcb6000000b00034589aa5771c5c13a9f188cf59661089cb438830b7da659daa04df4965f3eb1d1a388e2f1260518dc55bff6ba0bad507fb963706ddf8164e68180c25549b78e3ff7328c442595c88f4092cfce2b578649a090a3d84204aef92434ee080971fd22b6baf5053bfce72fb3b45497bb7ba2c5155e31291d6fef0a30e3f7a56001bea7c6374282955a5a2927d86ea1db353109fceafc125da9330a57cd18c73629b41d0d3edad54cd57e62de2cd1bd57ad3000000b029ef5ea07d26606e71c1d4ccc3379e982c909715b4dbf6ec181070cc72432c17b7f4b45e4d83065c79904a836710d72c34877f00d7c5188e06771be07324e97c44498d336cbba5e8d8bbdc2598c22d511965aba3a1af79f776ae5a8d86b4ecdf43d1472ed3c905a21d8b1e2e829e3b520cd168548c160967f401ab369d0c07eca3ea4cb95ccd6c7aa7b2ffbdacf159531ec19433dc38d057a3f34918e7bd31f344b2f37aa27d7ecaa3461eff83c2cfc20000021c000000b019f00a983882d136916fee5f0064fd407fb023313ae65d4181f2ec9285737bf96ee1f989f0b5fb86a1cc857fa7a965e7c55480faeddf0deb9aee4bd2d6c839ad0935b7a4d0345f2ddb906eb7a597b5abb1988dbcdd99015e99d16955c8d83396cbb03d6e0b599a97acbff9a8e21af8f7241780a9c20befd79400143dee9bfc47efecb4383546de49c093d7230580645d2851627826383b4328f01e37e203738b086080e19d88696b0af7e65eb18221e8000000b007b86c0922887e71946298ce764e204ff0dbf0a4314615e6767ccb48248c3abaf3c7f44ef82844a795a168fb6da64e33d2395b4d7b850a3c14cc327de6fdc7cdd38cf3470b9ff3b9cd1d4df282cb34335b33679f536cc2b2b38fa1c34fc1a4919082dfab221e359d3b065e4a53ea20df0877c1b9fae1801c24b03bfb0014d0bedd34c2827936a912975574dafb0fbcca0be7e5ab68f4856d43e65208673762fe3de05dc255701a92042b96b3d7737030000000b02cc754e4404db839854355b43977c0a4d3f2f04ecea7ac07bce388b5d6bfb54cdbbf39f98a95eee09f03e6b4d660abd36ff76d91b393cb5a641bbe4970cd8cf64ad7e9e6022744b9c1a4afde7ba4683716bb6b968106efba509fd93c6dfd73a2b237173d26bd9090e0b257dd7f159579246e5ed75e51a55a6a154009a728036a963abb446ecf710f4202c036472963f5123495e99741c8a44839efbacd9bc016b287c7caf83a7b518b0d371fca032f7f00000fa400000168000000b018550d6eead26984bee95682340eb94858815784a946515bb33e46d13fa257a712a223d502eae5bbbc18692224da290206ceaca84015a8eee76b2795a5e4a3d18376eda12f489f997ab10993b976f80fe2cceb7e1e37acf028bec433eb265b79f1bf977f2dc70675e17b9260d01fac0c12cf6ce00eff06dcd7e24fe8895aa61461cebc67cde6aa7b9d686a0ecd435b6501c606fec02ea6787a8a9cc94f79caf3c185d20f62f1c8a65b4bad43734d9dc9000000b017f0268a076ef50fb96e8d06d4686d97d835cee9b54c8029da9101b7a674fac298e9ff805f7000802dbabcff9192611fa735c499b4a1ade22c3719afa4cc5a11ce0c493ecee12be6a32cbc0ee3343bc58e239381bafbd0db163205eda4b517989f77d59e6c958c6698b111c80508617f2631aa9e9c5895cf41adb7e4d4c774f4440749555d370688929217e042fd5d9617f5f8657dd1458bbeaeef887260e6230d07dac2e3c350eb8e9ad3352258ace200000168000000b018daef7348cec7ee8a1bb655c7ea4945aa010b24843a47e8cc3d0715103383494646fb2e7b766c64c5891eaa18831e9f6ffba18f304014cd683727a4de98bcd97f501b77a0a5b64329cf74051e855e995bb6390ed665ef1cc327b7dbda117ce37d874cd53597e47e1a726293645ea8a60383ccf4738c28fd20f814365ccf1a670a6d7d6f2e52b176b8798d983a7408c306f4f3b06f19d77ec0679720afd3b78d715d7da983c9b5463c8c4aa61d33ffa9000000b023a4c16370101c4d1d72498a7de6cefa88b6fdfaa49a829ed8d4a7e99212cdf0a1a5d98f5c83c3dc7aed8d0ed86637a2f411370840649717c7b12dbbcd6176179bcb386a00d03f05073239313e093b95ef4f4653c1a1d09ed00751e15f808c9d10d4a6217b40b50fe52cab6f4eed1dba238080fc3bb69cec27ccfb45b9b7951300236b98b1103faf0fa835c4e6e454b50fb42947ced38bb3dae2ec17b2561b7550ef93e4def63f4d1eaf5a6b4a6b00e600000168000000b025c57d2d290181abfafb71143de72d92b22a855fdab73cbed678d5f073a6253ed0becefb28862be21ed2d18bb12f7ec767c68649b0ad1bde168e1a0027afb1a9952543090644727dae23d92b794bc67fda1cc842c9933907724cb05c26eec82f009bc93981a8c9759701494f5782019915825a03969090ebc360c567ad4f1f327959325a50a774158d3f14e31aa6dc0925a4f7e9641efeba107fdf41ad420cac7bf74a2c9dc40baf49a7c8649a964522000000b024c7c77993ee659f5bd0bd87fb2d9486d63ec43bb648b4496979722a781dfabca8f5386e3eae3e1422f878b2f90c75e66f4f418c10fdc0feae6da3a89773f80b9850cd45f75b820d79e050567c0c9a64c3daa145332212e185c12ccea3c2b838f759b7fdb8e35936fe6fcb2ca40efcd618863fafe263838ee423120641a57b09b9d82b3841823c3b8d84b53a5c0926632d4beab1134ca39defee31baeea374e0cfc84ff6b8abd6759d856c52b08d216200000168000000b01f9a2087417d21c5102c497138b225c561b5f68af791beb896f59b51c520abb7916adc345de8eaaba469b274e5acab5436b3625fbe2e32272bc420865a663a3bbdc0d4b719400a2f2a97c4c7ef6be9bc2d8c1987f4e00d0aa11e37c748cb645d1cdf65a4708758bb675150ce826e379f135d92104290749259be022823ddf6f5b6ca7f9110335232b656637b1e8206b404c5dfba55816d18f691bf9c24f37de44ebab7419eb7c001d29a426185240beb000000b019cb9720a0eb64cf1b7adc4de4ee011f9f440528e01010052bc9b09be42e6798ab4b71547112ba616b80989b7765945b0c6e420713dfcb2d87ea1fb9420cc571754399bcb6f2d45ff74788cae2eb1175b712d065284272583664a1be17a4177363a1cbad43ce6571df3bf2c394db94c72bec5e12e2fa12cf603bfa6b3aae72806836e8c997bfdb99fb298f8f5f148d6703cc190698e435e3cde269ae62624082697fb6961a0c13bc075413ca58619ab000000168000000b015674af75ce0aa0a6978f640f9a56cdf1ab4bc0b8aad65faf60215d4ef4c51b76d0f1c1bc4869f0e8f70bc238235292aeda388c3310579b69ffd0de8d770f4262397c35791c70f61e918f4c8ade29c2c987550ce575edab728468f53b823031d73e753d7d557a4bb457c5d60efac0ac705b20f97d42f72db45219b3770a7522ae73244d2327668a4b2947cd9fb20b1052a2f4951cacc80a9cab9f1af497aac0474d51771638a0bcc1402824fad076d55000000b01ab9c5170967fefd897bbab1f5ad150530ec242638a85995e7c7d14d6bbce39757d6f8e25ffc0f464120728b5987539abb546de81c3218ef1d836a96273c45f1de606a0fe605bcdd44bf353696517d2b46d206cd843661e67631f6c899091146d99211730d1bb4a19cb70c37f7acf6381d79feeb40c2cda760c329b3c8472b94c8acb039e9a111197d6cbeb531988f39020d254eb7ecca431d2efe013bc2cb53425cdd24636af081a11cb0544243c9f600000168000000b02259f6d070a2ad1d578908756d5ae0ae72533a28f59ec2b9f3b38cbc0b818f026eb1d753f8eba43542a312c87f946e8b9ef8e55d0534bad29ccc417f27026dada2d69dc11f299162d0e5c3d683f66f74f8bf05a43dac300e6ad49173f08c23d48f42ec670052f01efe2d119631c050c51c09ae73e02d200d2718130099ff1564cb03faed09ae74357bce0f2f113df3881ed6c62770f1ca8d43ed411a8b24e926137faf25ba2b51d01854ab3db3fd6cb4000000b01f4538b53d3d8617a22619b284b15888be61a986eaa19b4a10e12dadd692247f9434112881e7834554a25d6530f2ad50b58784bc5e25ba1ad3ca8a8504d891e05f71d7053bb4a07403c88bcca29f24ac59f30043c4b70ebd70164239eaf127d6f804eb39b847f856d3aa0f79f0d6f8422b1ec410112137add770469321b9124f40eab66e63ef6a9c30522014d3a9bc4425a620722c08dab74df797c6ad3fa1dd8df45dd2817542eeea7d38f158d0bfd900000168000000b026f555571554b5880654d99d0ac75dd4c848bc3e54c20cd3298aa488e0216b33463ad515425a3065435b655419ae42d73263ee7861c3e51db8c0657e8cee980dcbe45b7317d25c00096228394faeae1d52d96a392f4b4cb7dcf4a65df71f2353093ceb630a2986c32b2d45ce25678d0113cd53421825ec6d70470378b05909067029975ccc87fbf849bdb987cf4009d81df355b38a811faad5362c0041dbbcbbae90b765e8add788b3b8defe8e10e0a0000000b026fcbcdb0251762d4f26831b1fa4295ef158f406ed816d7ce22c10325a8425d301efa3bfed6ee5362af4d6943e65e8c730bc4b1f7d064298fea24e627bda89f0ffbd88ad2cdd7b93f197a6cc3426ca215edab1033fabcab0bba8a03ef56c4eeef63bac34981a0ef4eadf38090dafa60e08b3d22ebcf2599e61b8cdb7baf210904d5df6fd240b211f931d8162cfd3c86f28755e94cc54e2979fd864ab96bd4d75e5dad5ae869a105a35c533f4198562d400000168000000b02a825563e4b88303a9490b67eee06f58267c076915a38253a704335dc38bccd4842dc95f0d9c742837ca839eee21c3373f1cd03b985563e51020992b3b666f420f964a6d9a2fcb23745a5fba3f8e4f18524ab037e0ec6109ffa1d1ae30a723767f705bc1917569ad0497751fa31023620e3c9aba65faec2e5962033b45243640cd4bb7fffae37a220960cf9fab57429910955f261dc6a8f84655b819a0d01c5709b8d1e71b92e167c46c805345347a3e000000b016c3d0908f51da34f2d32ed38ea08a4c1833037a5f3f6a09f20ab27e79f697c3eb7d91a8892438c923464c5381689b5681a8443686736bbf37743e23de010dddd0876670586fdc4fc3422846f39dd3e78f4e0a776685b7b9445f79b753d47d74d82771e0add25c1466aaf28746fa42703005b93d193ae3f93cdc068d0f27106b17f21072ccbc66de7e044f07362510af1f3aa38071c5ffc73d6c1d9d565db35ad4f0ab55a1b516a14da52e8430a8171800000168000000b00e3d1e0490a8cdea27d30b1dcb08fcbb295d9d3b6012adb29e6510f9d72fbc61f9d6b9a9d95b87b5af8ba3d1374855e12123692e94c88c12eda2e9787014dc91339c772772826f6173f06d5c8eaed919cb78eeab992bd1e86e49d4d901dca435ffc6e64c46db28d6e0bbaeab8b8b97d414a588fe204f3bb85cf7824f49a131ae7162b32e5342e69a1eec2960db67dee32bf2a62b285087778c2172d7d7a41d74b7a13afa15d0ea4f84167dd1d8220ce6000000b0124948966bfa90628ef99597392741e2ed8cb227be47bcd2cba96d29241b7cf8cde97c590ce4a3147e3ddd9637650bf13c9b3eb2918751a87beb3709b90b00fd259b7785ae3b94e69c25ef0e3b3b7a6d0cb4720be0b333467c7b8119a18f94ad116a81b869e773ec590c5589db381bc01adfd28a80cc12f7ef0b3fa78b312e1e40c5e1c25375c41a76496591c0aa80a81e3c39adbfc4d421f32e9daf92b8f7d1d54e61f2954e63a9a759b6c8e98605c600000168000000b0051b9b68598f8c7da90721c52ac04b934088b3fa7f73b5eb6be14b460f469279fd2160dd1d4910c82a4f63ddcb2e5ef88588d9a5c0661bc44bc863849a7c10020f4f857674741761420d4b6a930f5ef07c176ce0a4f699d9c82621d8e1d614eca705c31e552ad37d0e7f68e5193b42df0f3956047f304960c4ab27e759a8c6c7f712ae1001214e26c00febacbfa4d8192f9f4507385b951f9e8af418a591cc887e91ec667b004a9ca59b79167c3712d3000000b01d9a7693501bdf5573dd7f8df9379a44db0eac42d23892a4a658f9161eec044086ad85559d2f843026e323f55838c1296f34b0fd9199e5fdd713ca6b7bf8b449fa38092bbf96e47f83304986cb1d6b97358d65c1aa89947e807dd57af51393a5193df35a57d463b94cd9c51aeb15c26711ad6188ce1a6567a54375f3a28c633a581356a8696eb13887e5dd9f5be0e41700bd6ed0e18296c32d1f5097efbdc6a260f6ec08ffd32c3f6295dec4e3d5829100000168000000b03006b5f1944203001e0691fa92daba61bbc81e0361e77bd9ff5c6c83a79513f17b4e96a95f86b0ee421a941f1ff83944522ea282545ecbd4181a825005e12abd6fa9715e781ef8709ff43f301ced9705ce601a3ea708ff4b31ab0c5c629ae5440250124cfef228e0af1ed45f55f5a20a2ac8495f893ac2215c6e27edd5704c30d9b266bf0672e3654edc8a3eaa2f4a1b10a00091f75cc9d1d04cc57d61ee4c61f8ed7f51680745dc0c90ef11411cef41000000b01150a750ed714dd6e174e9f23ddc87aa0e781583ba1b8f808520bf88e90ba3001d67deddcc35fe89fcbdee3f2e7e741354527eb44a7af354ae359d37dce64c72a234a850a1b48ac1b5c864ee69b5fa9b606be557468c5e47e710dcbfd618ab2d123b28ff1de181e3b3dabbd1522a20e714b2acc97a88333252c6c3053dcd328efc440c5350b165b45530f03e3cf9dc0e18cc64bc800595d16490950a664f9f8ab4612c1ec51a50abfaa05f19c5e0bb37380000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f00000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000331000000000000000000000000000000000000000000000000000000000000033200000000000000000000000000000000000000000000000000000000000003330000000000000000000000000000000000000000000000000000000000000334000000000000000000000000000000000000000000000000000000000000033500000000000000000000000000000000000000000000000000000000000003360000000000000000000000000000000000000000000000000000000000000337370000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f00000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000431000000000000000000000000000000000000000000000000000000000000043200000000000000000000000000000000000000000000000000000000000004330000000000000000000000000000000000000000000000000000000000000434000000000000000000000000000000000000000000000000000000000000043500000000000000000000000000000000000000000000000000000000000004360200000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000501100000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f0000000000000000000000000000000000000000000000000000000000000719000011000000021c000000b01ca95a38ee1f625129ed061558e695cd4b41d7eaf046d0605768391e285be2aee719710cf156df888adba93d8b0590f4f69f819fd9e50f462e7999c40ef929075e95981f455df0a571a076715f574c33b2d3749eef6a9597392ebe177779d9a53099a3354fea81e11a21c157273382cb1209c4f6f6c0d1d646d91733de73e575145ddc51b11a3bc640a244da47f7ae2a1f8537c7a78c88fcbc42d42ddecd7170c99c5ed4f6a93df3e78ba0af1fd5bfdd000000b0161bac8b2c06986bffe90c25127520d8cdb7046e3bff807b4e34df8384118e3ddf25c4fe31e1a84a0f334c93a481a56477e97aeea138a3111c0a7fbf537d0c2d6aaf5b25991919f0d8a58b626664d437ad3117fbdc64b890653cc64659eccd56666871917dc0f0d9ae889f147a42c79d2a83ca309601e00641d706e5eea3ac9e5267cc81a65f3c42d6b9bc620082a42f16d61f2a856d98a0fcf9cdd67049ae2585c72139937d0cd6867e836fff780bdf000000b02aef312509e36917fc08fc8663dc25cd1a4e0298a12d0f3ee98dc464d1ff29ea418020f2aafc171ce676e36fee56c97a0695b48e2284b5a981a7c3c02446824968b0819585f696d51a4a7051ec4e1d548528faaee848c3804bb779d88786e3db686bbf034fbccd356e1ed8ce9be347c5067b7d5b0c201dcdb266eaa2e6df90f61c1a7f75efc27177af12a758bf5977ee13ae6b486335f09cfa0778750e00ad038b8d689de623ae706fea9120fd5664250000021c000000b02d78d6eef8cf736377ebb146438eb5b7459cb15634ef863a023cba0663588770c1e04915c9bb9a2e517e6d23cbbde6e622b9930a7bc66d2702749efb59f70cb1074df22c7bbd6e0d645334eb0784858820732491d4429639c44c1d43409b029daed3bab256f8c219764911e8ecd313a9176033138a5bec74725d92f47c84b90979707b0527de8e6d3f15bf20212418d10c1b4ad31f39155574133f7a0b0f60339eedea731c0b0ba8df633e6c285d9feb000000b0079f6d0541b6c739b3e48771404ca53d6ff881dc9d4da1bac755b51bae863556e710a1fab94a087cc73b7f41d8856811984b3fff1a2a56ea6fe1011440e7d619b08f223da43b54b4eb6e1b8567b11b5c6e73b6515dda447a8b8ac84eb419f81649b88361b81671d6f3810db73d3827401b0e62eea6bdb9ce82097bb7a45f8ea9d48612d75ac2a093ff0249af9ad00ef71e78fefdf0beca8c081714c2f0bb5e72e45eb11dea9cf8cc47b622d355c0582b000000b02d9d285384eae7fba6d404ba3f364e6aff97e06aa759523c2e3d3c7d31be8f102eb7f23794a62e380edd8080cf0aee92f2c13f2f42152397bd51c87d4da3961d414e5d18f19bb80a57de0cf21850510cac170b5b78f56d36297efd783212d6f96b26ffc9fbd922cfca7ad021ffc0c72208a1934f6537dd51bbf1e846f33f2466f7364a0534037bc8abb45c0edb35f83e0a90d8478c1967eaeadd68c8d8b3e07a69f6e0cbce77adb2a9816b00178acc560000021c000000b020195a68f64788a6e37f79994170a37dd8ca22f5ede7f4aea3f7b0406d8157e84c81935dc475cdfa378dd7479c8155cec2dc807deb79e2d291fac35c371ee3941886515fa226625387325865746ba43bb93c10eb10e05de31509d4d44d21ddd4cac3d279cec55cdddd7f5fa0c4a63683272f570af77b8b96f829c9340aaa18083590eff4abc26a2507aa85d9edd578691a76a8fe088875b979e4af0180c7d0f2b135478c0b39f6a2b5683fe5fe0533cf000000b0182b5083c3e411527d5c65aa51912f8e13c716079e8bc3c2a5ccd5a6c1b011580d0e9bd42134d35d0398e1aa986e2b01df8e314a86b22f07e97ebcd6bc002dea631cca0ea7d4d910b2e72512295dd47abaf2312b943118f7ea03d101131ab04af8ca7966dd5477dc395bcc09915748da1000a75b2216346636682d5bd621149c902160548c5282e3d0c98e07c77aa5c202a8d2c3a750f27c0690f5784349ef8f28c1db2f2d84cf7fd20e0de81ff09ae5000000b00074fc3e3b2682a37a7116ec7dea4a282ca644c84049aedc7ca4a7319159e21410a67b9e8c20d25f4efa2fb1190bb05d604f7a07bd8f43d0452e45d3a94462abe43b6cc75041518131115ee027e6279b7b2b87645184a484af2e8436f7374282aff01a3e2cd2c503439b82b5340e2c861bca579009f9a13974de1b6e80e4ae2f5cf85d0116a529eb36cbc97e6fa40cb22908d5974ce5285fb5bfd6876f9c62a0e29f7e760f2bd71d112fb23d65bbcdd50000021c000000b0022f1d2dcc23e91d7694e2f775c3bfc39fd032c604b8811130602e0dbe81fb64b35d6bd29aa09236639dbb4b207c405aafbd21a1fb28ea5d16366ffad297a152112e05bfd807dd8ffbb7f0e2422ef926cb83c5a08f91c620cd15a7ea65ce92b647306cdb2bbd8498f6018fcead3c26ce13d2c54fb87332ea4aa6aac79462a532e63ed4a498a2580404d278151f1ab23305ae1299e15459e625e0f8762097d5389c7d9d387076d112bf4077477e6abfd8000000b00555e0e0e6e901edff2b8de8130b44cf8a2001478e7619e74936efc59d19068af0c087e0c4c22b1a6166dc269eb3aa06aab2d7cd0f4ee3cc5701199aee473af09d18b1cc40306f2653d3c40d8a11a8c976c11f7b55cbb4a9b197c6f4f35adbd4587229c682c9b6fbf294a1d27c4b608222133c4ee8e959e855b55d7d097a854c408a47f7e0d6ceca37ed5bbe94dc8802056c764c92ca99248cd60dfaa762e572dda8789bc417ee5904ec2435d691be51000000b020b32425dbf5af5f8729d567c3d791f4b627d4886e20e26969558a3d024d4ddfeb78121609a26470ec015c392295aa92918e22db0429db21641fb9672e95ff7681db7b27a9bbf825a0bf1a1bf8cc6c27d2c687b58476abc19f61f8e56e3ec64c8653c175275ce9aaf8303e6f35fc41360d0068794df68cae9757e31daa0602af1681756cce1caca3e243a364d1b25fc32dbe40564022593e87b604b89b39f6ea16b063f0dec9a02a43b2342e244883540000021c000000b003d86614f74410d1a9df9b6e0272c9f55fa06df978eabbc0b3a196fc3001840658ce6048d5f701defe21570c30e4b197b0a81c2ab1780907c6171b31cef860ebb441eb53008815ccfdb761a2e54222b92e11ae483e189533f71f8da2705e421a5ed0cdf1be8fafb44b243977ed2131ec023d9e4e246fe94ddef56096b142a8964610e1ae3c35e16888d3bddd9461a5e92a9dd1e3d6c8a48a22e5195e9504def180b984c5d2e3a599c19a0b97d8eb4546000000b02c3e9a1d5253c27825a9d2586057d1c7444cee3501a3c6b708641da787c0248daba71884df3a6da55e7c291fd57598977564594312f994cee71f256c8760e19302b56f78ba196dcb606210d6072416cb0b02f726adeec94652b01d72ac29c5f35af053bf9efa2e4b94f476395e597d1901ba4981831938d925c5fc34fa8c448f53831fc4c0da969fc5dba252fe2c364301ca6b500e2c6cb280087018f87064280b6085edb402531f2b78386fe97cb193000000b00dbdc2bdd4221f423c44d0c82e99fec2d08a31902670fda1633a900bfe2c93bb81009c4f4c8ad40acde7eb8dfacc29f9808a86aa99071005ae7d4151cebf8c57d3ab6271ad243bcace21396cf857386addd4f3a548dadcf58b7b421b371dfab2aeb8e1380a7d5e317154441a46ea4da90686a2b4a8ddaa3c11f449ebfde0b2dc4f57a3ff225e31043c324fb1bd7c5b802249897985b79ea7cfcffb297411375b98f0b13d325ac2fef07466b2132bc4c00000021c000000b0011476cecaefb5d1a9ef3f10cd80ed4f11aee9585e0dfe0828cce93232f4b0d9c175605e771a2ecee50712d5b2f38a833444b3923ff6269a297e4a361b9ed31bd020c92c500ce2f91b56c6423dbb7a7c77320f5e1d96088c92f0f6165e83885dd6b63513b36cd6badf680279c4a63cca23f2322e59cb2554943fd983bd8b18b5eeaa3b8ae449c686d3858ff3b24e351112f0da78135f3c0cfd8334df623843e00ba669bc4b634c7f7d29476478c222dd000000b00b36301206a05674a37fa56fcde573448a238dd0310d476a9032fbb38d11025aa46cc5ebe9229fa4a0a5c3ed3f50881edd6b9b859448f437cf1f4dd0cb08e5e6bd7c75461754eb102b237845205366a1162839a0ea0e6fb1b712b0c4e0a575264eabb9273007ddd7540d7a5b222723ed05f2853af628c87f1653cd22bd2a0c5ffe0e69ba81a385c3f7564b35ee6a95f422118fca396e06f91b1f5b3a438055c6e4360a77ac042d51636186f0a4730213000000b02fd8d55e2a5e235e1ae9af58a96134de6268c80c45debded6287598a942113391536cd5df421055c9239b35ed6598a327601ade7123a0c8872a94e7a57bb13eb25b8ea189d8c9df99501be413460a91b48428c82293714c58b8c6649a9b89be696fff91e2fc5a344d816ebe0497e4d7a03806abfeea7f533ae2610bc76eb98bb79423dc9a320003a1efcc901fd1d5a04293e366b0c090a3ba449f6bd169c9d13455875aaf1448c89fc103dccd7d72eb00000021c000000b00d0f46a2cf5cb3d3eb427dceb4200606b38c3e817c35459f88ed1b4e93e7799242e22616b89744025b8027253bb129cf7ff3409e83265502179fab782ffef2392f6ad3751efa13ff99f74a4ac5e85b7dce29aaf90c56f192ac4ba8d71fd9b422928ae18c0028e4a3ef1fc82d56f69a5a247783590be214dea06b39d8cc4fb3264bf73822903b660dbd72900676fba08e2a089119453aa6938431b9f6cb16f70968309563e264c505d994cd5da5010d1e000000b01542987ea6022c7a6e39f22ab19f55cfdea9e820c57199289b79d2b8fb374dba732b3cfee5d9fc664783874c90b87388799e18d11cea2388a609addfe485e28b0fd9971a0079aaeba9557865327789bd329a59e4b28ea08de8b682f50fbf11a475b9466f16d45aa9dd7a00f0e1b2533a2b349ad3e746e48d3bc9ec2135acc5b2cbe5dedf892670a433bc509190d87b152ba025240e0668c5d19d184d91610f26a35d2f6e5e93e7336d7705137351439d000000b019e09e0a94720220e1dde564ca0dcc71b24019f378c7ff5741b7e6864ab0ce4d8c32936b2ee9713907440843f85ac713ec442c9d1d7c566faf7443ffa8d7a538cc8decb4ff178b35fad4730890520c851993fa702064160c616b95b9ce3e2dc06bc6d641774e6b072a4e0fa722978b3e250219c28cc04868eab433c07ce324b1c5a655862700d885ba1b393f5d63a933285eb14a108f1f767f02699c3dd5ddc9eccb133e21a8b00067ba371c23e9be1a0000021c000000b017516321cd1684598fe8175553478f9d79023763f7467df43e3b513884fd8ecdc9f43220e2c84954b1a488b7bcc2c0a90056b1940eec7883889bc95f4f7deb5d27fde5554663c8d20b4e1d4ca770e6245ad03fdb84e3020f043e9c6e00ef97d95e723224320a0ba4e11b6e1b3cabf43f0b11a31e35f0b53d111b2882789a3cc0714d9a4c24576752431d986b9efd99210e2a568d16037e19a31a128047b82ce87714706452326461d2d1d4ddc4a1efcb000000b0272f1bcfeda0d3ff5f2e9ccbaff1d301879e70109d0f3a4e788a4895fc6ee2eb6bac66d562b357cc46b83f71f78e14b15270aca9bb35f4b7d56c3c7f3760b544640865c9c42c8f9a35e995b76a613365318e5d0f1ec6f8a6b4512817f282033312bb1cdc8aeab3d89eee4fd4de68521c0f2b9326026bb90c3364d7a1be46a5630d84c224755e5d86c887eba9e8f2c34c14f3d825eb6d30ec610e7650cab51fa114d5a734e03746231bc6bf09595f28a1000000b01252618e0ced5456fcfb9783af5b459b540e44ba8fac142d6a0411936a96252484d9bc12d95e4c3437f5f2bdb6d361b1f322033c54b1868fc2b092a7e1309cbafe96350dfcfcfd839a37edbc05c36ee31b78f2085d163b201d9e14469f0bc3e0a006b1ae93f081db662fe60a997202f2070eb422fbff7401157c30abf1f3254947adf2357f818e8b23c411c9b65c36f41cc7eeada33c364f5f577f490f7b61981b20d536cab771eda71692ae71e40de500000fa400000168000000b01aabea8444110fd2521125e870c323bab7b67ca0b33925df06b5adcd20716505214cab90fb71f0ff6467b2ea2237e0a9a60fda9c517a3f956c4612d65b9b70f110b0755d399f5b08b3365a588fd8c5a1bd491142f0453f70ef7c8483ad7e518067477ecd2ad49d5ac5d85590642390000aad10671bace8256cc5df3d1a4c0e252eb6367b1989ef8b738369e8535d73ab0c6a5d0caf3c868edfdf8edc08c674ac9f031f6436444a2d5ecb133fb6a1d0da000000b0142af2e21236c8fa33eca343ccd06f89d6239ecca8c30326e7ae712243e67f5bbce19ef32ed2eb42f21a9a16b7c55379f0d88b99c9d79b076cf400e1f7da99075f50acc3e8ceb095d7c48eb3f244b68bfe2189530ba81d1d0ce61861f420ae13d69408ff59f888df052e21d986c6ffef250612869b76f00a9a7f47cbe734da30ea7034620ec4c131e3e5e08a482f65570f93c39830be86ba524834445c9ae73bc57d0e1989b6294320791c94de336b2400000168000000b005801010d388403443ffb94fcfdcd53ff4c6556af2e6a6af93f745228447b1d75cf287b1932853b0e87328296db21fc2a509684296a06e5c14cad5c98fcff9c700a69a4b191e76bd4e046632ff4483115441507877ef902261c608c00f4956668eadeff6f98655f53804c7073af89a6f08742ccf39b6f5df0e0a69b9c3e2e0c3d949afa97aeda2a4656d9540705425d8218b5b59b00d4d3c12193f4da8af141370c1ab428be0a64b51e792d9ab9662e2000000b02376d97a96663ef4db5907c539400b2c546e2f992ba3e7f91a34dd8c3d50e106283aed41fec55988b71e9bb7499d5be2902287b5ec2fc131729737e4c00a2f11ea93e133a890101e6507114926bf58ae9d539a8598b7e0414929ba517cf5da85f036b18eed826c36a7c1a827ea042a46295e7713134707568a39258f29fc09619f07b93bdab66721026a0e013268191a06f287f711195409702278ba74a46e9d0edc05079dbfd7bf17bbd027cb1e173b00000168000000b019160db80a19c8b9cab1fa7a906c095c43892862c4336a08279996f7906d5302977bdd8dfebe256c22d3268141e557fea2833a51ccb6f1e8ff89437655ebc6843aa4f58cf958374b30131efa824f70985738d0ce9cbfef8316eb0ce20ec9c667cc24600a46fb50a17867cb773f66b72d06c72d35b3ac267fe6c1f1487719a8a8199ae156cbcf45ca920a2c449947fc5b105c743a64d9cd67c936139afa452617628ac1710b1944f2be37846c0bc74cd3000000b00fcddd75a85a0410045d15b3ae95ae7091cf4950699307fc5d74e27c43c5417ae115cd1e9bdec80fe3696c4093cb27ad0e270f5069aecbc274479fcf6d22a527652d89152a451303a95a8af8ff85ad49753cfc5d1bb7cf0d1a6c64dad8661ca120cc87e5b245399d5d14590f6d95609c1f4f0c1d7e18ded0e84c15adbd430f202ab676e1c5fadf0cdbe3a8491941086e0dafd02050d45c4eeeee9fff911f9c2a02e9be660edca42493902891559b100200000168000000b01402ec40a2cab35f51de2c07f95ac799b6e364a8c295fcffae1171b6718f22df630b270eb101df0d51b0566d45e34b08fcc01b5af9dc1de33cbaf21235913e02e6d03faea4635b6ee502ea9a41272731fcf22d7afd3dde20febbf7a847b856fff7d9ebc8ef35830d387b59ca4c2d68ae28c2137bf20812afc0d21ca795a653514f013d77eecbeddd78794f4874d078b312540cec5690bfb612758d485dc0d1d2077168c4991e17adde777dcf87960518000000b01728363bae09c7c58a1c8e7da47852da7fda639ae583a6e5e8dfae0caec68c6ea608844c646106dca5112c70613d2d1ee6cc6caf6d06f66c9900679a7f9baa15a41e645a5ef74ce8ede9299c5905b679fd3edc642af9b4f5003d677ded06def3cf660db411788fe79904c9aead2c5312109fe1a897863be88ca321d3eb876d662b3f681da3cbb292d9d7fe2ae529854d14fff43b678d0d5fc25754542287b29b9e3c7f44a5ac952f390522fd0fdf4c1c00000168000000b01f549eee4a32a28c9b2bb37a3606f08533f625efd12423f9c9fa5f29b2da938b8fe57a3414136b4712e24ff04d1c30114dac904507a656b4b1bdb660eb56e514657310b2ae780a65b336b3ee48879b4c8ae8e3b2b212d01d6ec87736a172ffae53b1791a72368f60e585e539175f3cac2eacd236b7780801e5fa41b5ad9f0d3c5c06d05c25eb5a55626d76e90f7bb02d113d089c96b79a68cd60dec8e8d47357a320965e49fb1d47dc0d0c8c783c02ac000000b0030e88a546b545bbc1c24ab72f4b01e5868b303682f78768dc1fa3c95c07b5d293f96710e25bf3ca9ae89c896cfbf5904fd93630e7dfdcb79f6f5f5b5c0fb4f36637f0c6e3dc8f4a7216dfcb465c7ebb3cbc57c088fe69233bd69fe3dd75a7f1859e4eaf44bb3c5e70ef8239e3bca8422cc01c4b11a2d1844d9fa569aa964fbf03a9db26f6fda73348e23cafe715c66e1cf99149206b507c3ca7de2e7468496eee3978cc32306c4a2d959d0500aa4d7300000168000000b0003f85dddf77ef920f6456daea356ef7504c09dad7b52654c14ec13436c93fe210d4e88c40d9ed7c298d97b735407a1c92d307e5c45827dc09c7e8288d8b6ac463c06f05e29617f02265d6fcaaa46db39d0a29252c363a817a592be3294a365d913bfbfa3ff0f3c521fe36dd06cbb8e10e2ce8c11b1314b679236de533dd532782cbed680bf7ea05330cc9108dbe7eff231f1e9fc34c519b395c6671c556a382681f24d6133d11ae0710b2f9915555b7000000b0256a415d7e18d916e7a037034e665f4fbbf0d3e44da30de17e61ccd0289c39b9abe577d52a444c7acda034103e59613ccfd13070ffdf034404d132f3f2788b8206e2f6178f4bc581099dccfd7c472797303619c9fbfd6f785a797b847e2bd5d3a9933524c88fe95db986dacbadb9606f205b0691a545318143db89cf970b124304a13fefe696ca415988aeaa961f9eee2e978cf7ed017770e8b4c402a79a23aedf4d90cdfdf0c14fb42621470ac0fecb00000168000000b000b0251a8c8b697e63254b6e5d90dfeba98f2e270aa5cdaa8da09654be25b22d7c5ac3b2b32ced096a2247bcf6e22bd089a8ff68bb408394d0f082db4c819f1f68f805e3b77783e7f58a87b19d317a27aa5a785ecf31b5610379e707d9b035dca9be3b3ad252e74d69e12cd422c5191a046dcf6b0a9091f90b71ddf7de1fa1b9aa2db03025fcd9d1d57da2fa21fecbff16d701e48a3ab9fa67f27e630c9ff6c35447b8c2a929bc9b41856bcb3ca7ec6c000000b004ffa1bc1d6d5d031bd09fe755fe127fe14e92e5dc54e0875420fb308d1051ef16338b5dfb1a8bf282d6eed46b9ebceb2bd49df96fd8be0e82665111ef7a195331c33eccff09ac2842f30648298cdd67d5b6035fd24bff8d994d307f66678153928cc9828f0a53c4d55c5a545eb4b2182732a399013a28a1531355e118e2db0f3f26cb369ad10026d95056906c36910523db6209424fe9d93364c5b733b7af9a531de34fb4bb9e8051ac083a6abfa4f700000168000000b02405a96f61f6ef17a02003575a93c878325b287271b7faabae157688ccfada728db465f5d52ad87ac5e3a3dcb7366c0393eaefd537c59872fe37de43b20c5e107e316c0f954cf3eaec16a7de2a00b587770caab251796a9db9242caa129be64c2c9b634d36e002864bb39aeede1035002c0238ea14c586e2d28263066f76073432e9b9959df798f7447f2d98c2e4ec290944813e456182a83af14616b794dcac9a7f132de33dc9dd5e06b2000d5b7d8a000000b00ab3b93771986ea698e440ec3871c28ded7e0611832e0e03231bda06f03488910f5e8f9ce61d5882804ea19e681138d454b4035527cf0085035cbf5cca44b5b76597fdd0950582660d0e48e0e5599fff64c8ac62aa5a9d8481b9014688e56d82d6ae2641c438d456e46d3e2c46ccc20e28970cadce6b8eb509ddb0daca6ae2b96a175d3c4ffc2c7533a784dd435caab805a109472f9663b480defeeb0f8251c068db62e4e8d8bd295669c565a177609b00000168000000b01fe15c9b0ac687152364aa6a592e7ad6ba2164986c490feba56386f72b878ea0cefe33a105c7916a56369b03372a73d74f20bd1a2b73e4bb4837db1d62ca8d938c5c2959f014280708b7f9a57cfaa2142ce864e671ca470b7572b3c7118d6cf4f7d1612a8ab79a4287e76e819e8b3a6a21f22e8fc5a446259a7c4e8157a78391ac58e513fd848d27c5c2be6e05ea1e4927f75b55697b73097a77a351bb45531dd6826db6c204fb8ac93780d6ae41ef95000000b0205c2faf1c063c87c3105e9edb3b62f8a5f69299c55982e3c72363b75583e1fa0a1c94613b1243cf6b222c2e59d56d86eab043092e8f1bf5f4ed6bc5c8d6a199e56b356daaaa01539be90b4bd8999eedc3f9633c5ccc6e9a758368bde3fbd126ae923ad54ecc0466fd29c07e392d4e021bbd3aff6dc886ad59af0a2970f3a2975b11441578477a1b41055c137ffd099c2af3e69fdbc176b2b286bb6b667e694ec4ad96435aea93fdf0d487945f3a00e300000168000000b0137ba05eab7fbaf836b206b29d27ba39164abf627a8fb9067eba299fcfa6c162f909f6271a82392ff84a5fa4997e028a1fd0ad43f39ec30ace1592796f80eb3d714382ada1084adc94ef2eb1d6190e0c7d5c74e6d043ff3ce7544488a2148a13d9c8b1108892f3f47d18ab85a124870a1440aeaff103d7594a0f2161a4b19ef06ef76f5997500ed60f6c18b1aaca535718dbec7a60c1b7e8a59b699814de64d8c998a074402eb43ca857e3d938b0a154000000b02f29eae1fbbfcf45bfa87be2d3c950ff524e7c4bcc0543fca977fcdfac6a25d20e6d02b1f70e6fcdefe35969bd9892e28a50acc30e1529cdfc977d0768a0c97651ee012ad45b9820072d315fcd5cd4fea47456d00bd7890e705f99c99ec5ea42d3e31559cc87a84fc701d71db0931d3f2459fb17c6a46d9b0e7a533507ad0e6ff2c11abf8202311d37d3db4c95a6f618020fd85dbec80ff7b16bf5c2d69093f7f0967430d16fd435465a1ba3105e36ce00000168000000b03007edb592d74abfe475aaa44fae51d0b54b2e679576cf0be0c24296ee14c9175cce60fa5d7e14b67e11bee1ed2130de0fd24c1d6bb2ee518d25dd6f35db87f1a91e83b1c90921af6eade9ccf7fdf8f53cb682faaa8bafd42751932223715c4e778ed35d788dc7f557b7880f0ccd11d503fb3535bfb10f64195e5d73afdb9cb5e30cb93679d42c2609630c08f4869da822e78a9fcc0562f31eba8a2b3af47867ea2b619c8377825108a7fcaff617849c000000b02316545590a39dbb9957ddcb5e5b161f9e57ccbd5c60a5b87b7eb449a96d1a1c50a7a1a3f735cfa37746634f9c684f6d0d8708271c8493fe7fc787e5849f6bfdb2cd9d1f0026532cf27034701af258853023faf11fb29f602067549caf686733b416370885c462146ddcbc61596b3a312e8d87cc61c5a2613f6f181e8cc3d8423162d03fff13c55d0c1e0101dfded8451092a351ab5df1baa16358ff931f86ce617e919e013de7b7624e246c8176ebf3", + "txsEffectsHash": "0x43b8bd02d2c6ca958303c71be5c272b917a436b3f9d779ffc3ffd66ba41de258", "decodedHeader": { "contentCommitment": { "inHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "outHash": "0x3c00faec8dc481e71433eb21f1dd016134bf403950c146783ba1928cddcb315d", "txTreeHeight": 2, - "txsEffectsHash": "0xba6c2a6d813750dc256f667c3ba6c1c791bc56020496c7b490d00cccd40fdb69" + "txsEffectsHash": "0x43b8bd02d2c6ca958303c71be5c272b917a436b3f9d779ffc3ffd66ba41de258" }, "globalVariables": { "blockNumber": 2, "chainId": 31337, - "timestamp": 1709733970, + "timestamp": 1709939074, "version": 1, - "coinbase": "0x2c4ed998adb9ea58602c2f521338d85e796983c2", - "feeRecipient": "0x08e3c9234b16ba719d1fa970253ee4631f0204c4dc25b86b46eef390ab581e80" + "coinbase": "0x3763c27097c7679fde3c516b87d7a57fbff2b401", + "feeRecipient": "0x12f0936cd74975821fef2537b6501306af902a7084887216691bce9ac330b88c" }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x136a8f7d7909e8b294472fef24dc3a6187259aa5005e2e0c32bfd1f49b80b5c8" + "root": "0x00f4e742fc0ed23e57b5bdbabad8806c1fc9f51695dadc9fe2dda7a6dd16e830" }, "stateReference": { "l1ToL2MessageTree": { @@ -80,10 +80,6 @@ "root": "0x06c76caee115a61eeb6788977c68a3bea359061b678a1a4f5ffde13e0451717b" }, "partialStateReference": { - "contractTree": { - "nextAvailableLeafIndex": 8, - "root": "0x05cc2e9c54598a9b5cdf0983d442311b0b963c93ce46c5930be845b12d616b9a" - }, "noteHashTree": { "nextAvailableLeafIndex": 512, "root": "0x023ef973dbaa366409f7a01a4ced696227685ce75e57b510d0e7015ebfa72c50" @@ -99,8 +95,8 @@ } } }, - "header": "0x136a8f7d7909e8b294472fef24dc3a6187259aa5005e2e0c32bfd1f49b80b5c8000000020000000000000000000000000000000000000000000000000000000000000002ba6c2a6d813750dc256f667c3ba6c1c791bc56020496c7b490d00cccd40fdb6900000000000000000000000000000000000000000000000000000000000000003c00faec8dc481e71433eb21f1dd016134bf403950c146783ba1928cddcb315d06c76caee115a61eeb6788977c68a3bea359061b678a1a4f5ffde13e0451717b00000020023ef973dbaa366409f7a01a4ced696227685ce75e57b510d0e7015ebfa72c5000000200231b77b7e0311a71fae5cec0f0281816950f94a24bfc2e67c5ae8619c6ed4c880000028005cc2e9c54598a9b5cdf0983d442311b0b963c93ce46c5930be845b12d616b9a000000082ae3a1bf2752c8c8bd6741bb3fd0d9e3811dbf7681454436125ccb7afeca31c9000001400000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000065e878522c4ed998adb9ea58602c2f521338d85e796983c208e3c9234b16ba719d1fa970253ee4631f0204c4dc25b86b46eef390ab581e80", + "header": "0x00f4e742fc0ed23e57b5bdbabad8806c1fc9f51695dadc9fe2dda7a6dd16e83000000002000000000000000000000000000000000000000000000000000000000000000243b8bd02d2c6ca958303c71be5c272b917a436b3f9d779ffc3ffd66ba41de25800000000000000000000000000000000000000000000000000000000000000003c00faec8dc481e71433eb21f1dd016134bf403950c146783ba1928cddcb315d06c76caee115a61eeb6788977c68a3bea359061b678a1a4f5ffde13e0451717b00000020023ef973dbaa366409f7a01a4ced696227685ce75e57b510d0e7015ebfa72c5000000200231b77b7e0311a71fae5cec0f0281816950f94a24bfc2e67c5ae8619c6ed4c88000002802ae3a1bf2752c8c8bd6741bb3fd0d9e3811dbf7681454436125ccb7afeca31c9000001400000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000065eb99823763c27097c7679fde3c516b87d7a57fbff2b40112f0936cd74975821fef2537b6501306af902a7084887216691bce9ac330b88c", "l1ToL2MessagesHash": "0xa10cc8559615be5a44cfb608374b1f84fd11cdb5844ebffafd92a77c068350f1", - "publicInputsHash": "0x08bb34a501366d5985915c898cd411d7ca1658821088cff7a52b696e96470b74" + "publicInputsHash": "0x2af486d91d741bafe33b4e5fad0cbde6b32bace6e82fff0677dd1c58cafdafad" } } \ No newline at end of file diff --git a/noir-projects/aztec-nr/aztec/src/context/avm.nr b/noir-projects/aztec-nr/aztec/src/context/avm.nr index 63a8a63d7ca..96902336a98 100644 --- a/noir-projects/aztec-nr/aztec/src/context/avm.nr +++ b/noir-projects/aztec-nr/aztec/src/context/avm.nr @@ -82,7 +82,17 @@ impl AVMContext { pub fn send_l2_to_l1_msg(self, recipient: EthAddress, content: Field) {} #[oracle(avmOpcodeCall)] - fn call( + pub fn call( + self, + gas: [Field; 3], // gas allocation: [l1Gas, l2Gas, daGas] + address: AztecAddress, + args: [Field; ARGS_COUNT], + temporary_function_selector: Field + ) -> ([Field; RET_SIZE], u8) {} + // ^ return data ^ success + + #[oracle(avmOpcodeStaticCall)] + pub fn call_static( self, gas: [Field; 3], // gas allocation: [l1Gas, l2Gas, daGas] address: AztecAddress, @@ -140,4 +150,23 @@ impl AVMContext { returnData } + + pub fn static_call_public_function( + self: Self, + contract_address: AztecAddress, + temporary_function_selector: FunctionSelector, + args: [Field; ARGS_COUNT] + ) -> [Field; RET_SIZE] { + let gas = [/*l1Gas*/42, /*l2Gas*/24, /*daGas*/420]; + + let (returnData, success): ([Field; RET_SIZE], u8) = self.call_static( + gas, + contract_address, + args, + temporary_function_selector.to_field() + ); + + assert(success == 1, "Nested static call failed!"); + returnData + } } diff --git a/noir-projects/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr b/noir-projects/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr index 48339688ea9..a2bf9752ee2 100644 --- a/noir-projects/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr +++ b/noir-projects/aztec-nr/aztec/src/context/inputs/private_context_inputs.nr @@ -1,5 +1,5 @@ use dep::protocol_types::{ - abis::call_context::CallContext, contrakt::contract_deployment_data::ContractDeploymentData, + abis::call_context::CallContext, header::Header }; use crate::context::globals::private_global_variables::PrivateGlobalVariables; @@ -9,7 +9,6 @@ use crate::context::globals::private_global_variables::PrivateGlobalVariables; struct PrivateContextInputs { call_context : CallContext, historical_header: Header, - contract_deployment_data: ContractDeploymentData, private_global_variables: PrivateGlobalVariables, } // docs:end:private-context-inputs \ No newline at end of file diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index 15f12340fe2..4bc91a32835 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -23,7 +23,7 @@ use dep::protocol_types::{ MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, - MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, + MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, NUM_FIELDS_PER_SHA256, RETURN_VALUES_LENGTH }, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, @@ -140,11 +140,6 @@ impl PrivateContext { } } - pub fn is_deployment(self) -> bool { - // TODO(#4738): Implement this - false - } - // Returns the header of an arbitrary block whose block number is less than or equal to the block number // of historical header. pub fn get_header_at(self, block_number: u32) -> Header { @@ -167,6 +162,7 @@ impl PrivateContext { // - in the private circuit inner that it remains 0 // I've had to initialize the counter here so that it would work for contract deployments // the above checks should be doable after we figure out fee payments for contract deployments + // TO(fees): there are no more contract deployments at the protocol level min_revertible_side_effect_counter: self.min_revertible_side_effect_counter, note_hash_read_requests: self.note_hash_read_requests.storage, nullifier_read_requests: self.nullifier_read_requests.storage, @@ -182,7 +178,6 @@ impl PrivateContext { encrypted_log_preimages_length, unencrypted_log_preimages_length, historical_header: self.historical_header, - contract_deployment_data: self.inputs.contract_deployment_data, chain_id: self.inputs.private_global_variables.chain_id, version: self.inputs.private_global_variables.version }; @@ -349,7 +344,6 @@ impl PrivateContext { // Assert that the call context of the enqueued call generated by the oracle matches our request. assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call); assert(item.public_inputs.call_context.is_static_call == is_static_call); - assert(item.public_inputs.call_context.is_contract_deployment == false); if (is_delegate_call) { // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address. @@ -457,6 +451,7 @@ impl PrivateContext { args_hash: reader.read(), return_values: [0; RETURN_VALUES_LENGTH], nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL], + nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL], contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL], contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL], public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], @@ -485,7 +480,6 @@ impl PrivateContext { // Assert that the call context of the enqueued call generated by the oracle matches our request. assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call); assert(item.public_inputs.call_context.is_static_call == is_static_call); - assert(item.public_inputs.call_context.is_contract_deployment == false); if (is_delegate_call) { // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address. diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index 11a5aac333e..352e8f03f38 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -15,7 +15,8 @@ use dep::protocol_types::{ MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - MAX_NULLIFIER_READ_REQUESTS_PER_CALL, NUM_FIELDS_PER_SHA256, RETURN_VALUES_LENGTH + MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, + NUM_FIELDS_PER_SHA256, RETURN_VALUES_LENGTH }, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, hash::hash_args, header::Header, messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader @@ -29,6 +30,7 @@ struct PublicContext { return_values : BoundedVec, nullifier_read_requests: BoundedVec, + nullifier_non_existent_read_requests: BoundedVec, contract_storage_update_requests: BoundedVec, contract_storage_reads: BoundedVec, public_call_stack_hashes: BoundedVec, @@ -102,6 +104,7 @@ impl PublicContext { args_hash, return_values: BoundedVec::new(), nullifier_read_requests: BoundedVec::new(), + nullifier_non_existent_read_requests: BoundedVec::new(), contract_storage_update_requests: BoundedVec::new(), contract_storage_reads: BoundedVec::new(), public_call_stack_hashes: BoundedVec::new(), @@ -117,11 +120,6 @@ impl PublicContext { } } - pub fn is_deployment(self) -> bool { - // TODO(#4738): Implement this - false - } - pub fn block_number(self) -> Field { self.inputs.public_global_variables.block_number } @@ -148,6 +146,7 @@ impl PublicContext { call_context: self.inputs.call_context, // Done args_hash: self.args_hash, // Done nullifier_read_requests: self.nullifier_read_requests.storage, + nullifier_non_existent_read_requests: self.nullifier_non_existent_read_requests.storage, contract_storage_update_requests: self.contract_storage_update_requests.storage, contract_storage_reads: self.contract_storage_reads.storage, return_values: self.return_values.storage, @@ -170,6 +169,12 @@ impl PublicContext { self.side_effect_counter = self.side_effect_counter + 1; } + pub fn push_nullifier_non_existent_read_request(&mut self, nullifier: Field) { + let request = ReadRequest { value: nullifier, counter: self.side_effect_counter }; + self.nullifier_non_existent_read_requests.push(request); + self.side_effect_counter = self.side_effect_counter + 1; + } + pub fn message_portal(&mut self, recipient: EthAddress, content: Field) { let message = L2ToL1Message { recipient, content }; self.new_l2_to_l1_msgs.push(message); diff --git a/noir-projects/aztec-nr/aztec/src/history/contract_inclusion.nr b/noir-projects/aztec-nr/aztec/src/history/contract_inclusion.nr index 6cd81a277cf..1a16ea986c7 100644 --- a/noir-projects/aztec-nr/aztec/src/history/contract_inclusion.nr +++ b/noir-projects/aztec-nr/aztec/src/history/contract_inclusion.nr @@ -1,85 +1,64 @@ use dep::protocol_types::{ - abis::{new_contract_data::NewContractData as ContractLeafPreimage}, - address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, - grumpkin_point::GrumpkinPoint + address::{AztecAddress, EthAddress}, + contract_class_id::ContractClassId, + grumpkin_point::GrumpkinPoint, + hash::silo_nullifier, + constants::DEPLOYER_CONTRACT_ADDRESS }; use dep::std::merkle::compute_merkle_root; -use crate::{context::PrivateContext, oracle::get_membership_witness::get_contract_membership_witness}; +use crate::{ + context::PrivateContext, + history::{ + nullifier_inclusion::prove_nullifier_inclusion_at, + nullifier_non_inclusion::prove_nullifier_not_included_at, + } +}; -// Proves that a contract exists at block `block_number` and returns its address. -// Note: This can be used to approximate a factory pattern --> a factory contract could perform this proof and that -// way verify that a contract at a given address is what it expects. Then it could store it in an internal -// map of contracts (like what Uniswap Factory does with pool contracts - it stores them in a mapping). -// By passing in the construct hash the factory can also verify that the contract was constructed with the -// correct constructor arguments. Typically the factory would store the expected construct hash and assert that -// it is what it expects. The constructor param check is the reason of why we pass in the preimage of contract's -// aztec address instead of just the address. -pub fn prove_contract_inclusion( - public_key: GrumpkinPoint, - contract_address_salt: Field, - contract_class_id: ContractClassId, - initialization_hash: Field, - portal_contract_address: EthAddress, +pub fn prove_contract_deployment_at( + contract_address: AztecAddress, + block_number: u32, context: PrivateContext -) -> AztecAddress { - // 1) Get block header from context - // let block_header = context.historical_header; - - // 2) Compute the contract address - let contract_address = AztecAddress::compute_from_public_key( - public_key, - contract_class_id, - contract_address_salt, - initialization_hash, - portal_contract_address - ); +) { + // Compute deployment nullifier + let nullifier = silo_nullifier(AztecAddress::from_field(DEPLOYER_CONTRACT_ADDRESS), contract_address.to_field()); - // TODO(@spalladino): Use initialization and/or deployment nullifier for this proof. - // Consider splitting this into 2 methods, one for initialization and one for public deployment. + // Prove its inclusion + prove_nullifier_inclusion_at(nullifier, block_number, context); +} - // 3) Form the contract tree leaf preimage - // let preimage = ContractLeafPreimage { contract_address, portal_contract_address, contract_class_id }; - // - // 4) Get the contract tree leaf by hashing the preimage - // let contract_leaf = preimage.hash(); - // - // 5) Get the membership witness of the leaf in the contract tree - // let witness = get_contract_membership_witness(block_number, contract_leaf); - // - // 6) Prove that the leaf is in the contract tree - // assert( - // block_header.partial.contract_tree.root - // == compute_merkle_root(contract_leaf, witness.index, witness.path), "Proving contract inclusion failed" - // ); - // - // --> Now we have traversed the trees all the way up to archive root. +pub fn prove_contract_non_deployment_at( + contract_address: AztecAddress, + block_number: u32, + context: PrivateContext +) { + // Compute deployment nullifier + let nullifier = silo_nullifier(AztecAddress::from_field(DEPLOYER_CONTRACT_ADDRESS), contract_address.to_field()); - contract_address + // Prove its non-inclusion + prove_nullifier_not_included_at(nullifier, block_number, context); } -pub fn prove_contract_inclusion_at( - public_key: GrumpkinPoint, - contract_address_salt: Field, - contract_class_id: ContractClassId, - initialization_hash: Field, - portal_contract_address: EthAddress, +pub fn prove_contract_initialization_at( + contract_address: AztecAddress, block_number: u32, context: PrivateContext -) -> AztecAddress { - // 1) Get block header from oracle and ensure that the block is included in the archive. - let header = context.get_header_at(block_number); +) { + // Compute initialization nullifier + let nullifier = silo_nullifier(contract_address, contract_address.to_field()); - // 2) Compute the contract address - let contract_address = AztecAddress::compute_from_public_key( - public_key, - contract_class_id, - contract_address_salt, - initialization_hash, - portal_contract_address - ); + // Prove its inclusion + prove_nullifier_inclusion_at(nullifier, block_number, context); +} - // TODO(@spalladino): See above func to impl +pub fn prove_contract_non_initialization_at( + contract_address: AztecAddress, + block_number: u32, + context: PrivateContext +) { + // Compute initialization nullifier + let nullifier = silo_nullifier(contract_address, contract_address.to_field()); - contract_address + // Prove its non-inclusion + prove_nullifier_not_included_at(nullifier, block_number, context); } diff --git a/noir-projects/aztec-nr/aztec/src/initializer.nr b/noir-projects/aztec-nr/aztec/src/initializer.nr index 70858cfe8ab..13826bf48db 100644 --- a/noir-projects/aztec-nr/aztec/src/initializer.nr +++ b/noir-projects/aztec-nr/aztec/src/initializer.nr @@ -2,17 +2,9 @@ use dep::protocol_types::hash::silo_nullifier; use crate::context::{PrivateContext, PublicContext, ContextInterface}; use crate::history::nullifier_inclusion::prove_nullifier_inclusion; -pub fn mark_as_initialized(context: &mut PrivateContext) { +pub fn mark_as_initialized(context: &mut TContext) where TContext: ContextInterface { let init_nullifier = compute_unsiloed_contract_initialization_nullifier(*context); - context.push_new_nullifier(init_nullifier, 0); -} - -// TODO(@spalladino): Using the trait here fails with "No matching impl found for `&mut TContext: ContextInterface`" -// on the `push_new_nullifier` call. Remove this method in favor of a single method that uses the trait (and update -// the noir compiler macro accordingly) once we sort it out. -pub fn mark_as_initialized_public(context: &mut PublicContext) { - let init_nullifier = compute_unsiloed_contract_initialization_nullifier(*context); - context.push_new_nullifier(init_nullifier, 0); + ContextInterface::push_new_nullifier(context, init_nullifier, 0); } pub fn assert_is_initialized(context: &mut TContext) where TContext: ContextInterface { diff --git a/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr b/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr index 3cf9edcdc85..61e3bbc4256 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr @@ -1,11 +1,8 @@ -use dep::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}; - -// contract_address + -// args_hash + -// crate::abi::FUNCTION_DATA_SIZE + -// crate::abi::CALL_CONTEXT_SIZE -// = 2 + 4 + 8 -global ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE: Field = 14; +use dep::protocol_types::{ + abis::function_selector::FunctionSelector, + address::AztecAddress, + constants::ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH +}; #[oracle(enqueuePublicFunctionCall)] fn enqueue_public_function_call_oracle( @@ -15,7 +12,7 @@ fn enqueue_public_function_call_oracle( _side_effect_counter: u32, _is_static_call: bool, _is_delegate_call: bool -) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE] {} +) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {} unconstrained pub fn enqueue_public_function_call_internal( contract_address: AztecAddress, @@ -24,7 +21,7 @@ unconstrained pub fn enqueue_public_function_call_internal( side_effect_counter: u32, is_static_call: bool, is_delegate_call: bool -) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE] { +) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] { enqueue_public_function_call_oracle( contract_address, function_selector, diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_membership_witness.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_membership_witness.nr index 1e82b12c91e..4c7ac8ce2ac 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_membership_witness.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_membership_witness.nr @@ -1,8 +1,7 @@ -use dep::protocol_types::{constants::{ARCHIVE_HEIGHT, CONTRACT_TREE_HEIGHT, NOTE_HASH_TREE_HEIGHT}, utils::arr_copy_slice}; +use dep::protocol_types::{constants::{ARCHIVE_HEIGHT, NOTE_HASH_TREE_HEIGHT}, utils::arr_copy_slice}; -global CONTRACT_TREE_ID = 0; -global NOTE_HASH_TREE_ID = 2; -global ARCHIVE_TREE_ID = 5; +global NOTE_HASH_TREE_ID = 1; +global ARCHIVE_TREE_ID = 4; // Note: We have M here because we need to somehow set it when calling get_membership_witness function and one way to // do it is to set M here and then set type of the return param, e.g.: @@ -32,13 +31,6 @@ unconstrained pub fn get_membership_witness( MembershipWitness { index: fields[0], path: arr_copy_slice(fields, [0; N], 1) } } -unconstrained pub fn get_contract_membership_witness( - block_number: u32, - leaf_value: Field -) -> MembershipWitness { - get_membership_witness(block_number, CONTRACT_TREE_ID, leaf_value) -} - // Note: get_nullifier_membership_witness function is implemented in get_nullifier_membership_witness.nr unconstrained pub fn get_note_hash_membership_witness( diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr index f57bc941123..23837400645 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr @@ -31,7 +31,6 @@ contract AppSubscription { global SUBSCRIPTION_DURATION_IN_BLOCKS = 5; global SUBSCRIPTION_TXS = 5; - global CANONICAL_GAS_TOKEN_ADDRESS = AztecAddress::from_field(10518537853519909204957666322334442672584410385979059968848104222965977783517); #[aztec(private)] fn entrypoint(payload: pub DAppPayload, user_address: pub AztecAddress) { @@ -82,12 +81,7 @@ contract AppSubscription { storage.subscription_recipient_address.initialize(subscription_recipient_address); storage.subscription_price.initialize(subscription_price); - let actual_gas_token_address = if is_empty(gas_token_address) { - CANONICAL_GAS_TOKEN_ADDRESS - } else { - gas_token_address - }; - storage.gas_token_address.initialize(actual_gas_token_address); + storage.gas_token_address.initialize(gas_token_address); } #[aztec(public)] diff --git a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr index 102e09a5b66..eb1feef8589 100644 --- a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr @@ -161,10 +161,8 @@ contract AvmTest { fn emit_unencrypted_log() { context.emit_unencrypted_log(/*event_selector=*/ 5, /*message=*/ [10, 20, 30]); context.emit_unencrypted_log(/*event_selector=*/ 8, /*message=*/ "Hello, world!"); - // FIXME: Try this once Brillig codegen produces uniform bit sizes for LT - // FIXME: TagCheckError: Tag mismatch at offset 22, got UINT64, expected UINT32 - // let s: CompressedString<1,13> = CompressedString::from_string("Hello, world!"); - // context.emit_unencrypted_log(/*event_selector=*/ 10, /*message=*/ s); + let s: CompressedString<2,44> = CompressedString::from_string("A long time ago, in a galaxy far far away..."); + context.emit_unencrypted_log(/*event_selector=*/ 10, /*message=*/ s); } #[aztec(public-vm)] @@ -248,4 +246,44 @@ contract AvmTest { let addResult = returnData[0]; addResult } + + // Directly call_static the external call opcode to initiate a nested call to the add function + #[aztec(public-vm)] + fn raw_nested_static_call_to_add(argA: Field, argB: Field) -> pub (Field, u8) { + let selector = FunctionSelector::from_signature("avm_addArgsReturn(Field,Field)").to_field(); + let gas = [/*l1Gas*/42, /*l2Gas*/24, /*daGas*/420]; + + let (resultData, success): ([Field; 1], u8) = context.call_static(gas, context.address(), [argA, argB], selector); + + (resultData[0], success) + } + + // Directly call_static setAdmin. Should fail since it's accessing storage. + #[aztec(public-vm)] + fn raw_nested_static_call_to_set_admin() -> pub u8 { + let selector = FunctionSelector::from_signature("avm_setAdmin()").to_field(); + let gas = [/*l1Gas*/42, /*l2Gas*/24, /*daGas*/420]; + + let (_returnData, success): ([Field; 0], u8) = context.call_static(gas, context.address(), [], selector); + + success + } + + // Indirectly call_static the external call opcode to initiate a nested call to the add function + #[aztec(public-vm)] + fn nested_static_call_to_add(argA: Field, argB: Field) -> pub Field { + let selector = FunctionSelector::from_signature("avm_addArgsReturn(Field,Field)"); + + let resultData: [Field; 1] = context.static_call_public_function(context.address(), selector, [argA, argB]); + + resultData[0] + } + + // Indirectly call_static setAdmin. Should revert since it's accessing storage. + #[aztec(public-vm)] + fn nested_static_call_to_set_admin() { + let selector = FunctionSelector::from_signature("avm_setAdmin()"); + + let _resultData: [Field; 0] = context.static_call_public_function(context.address(), selector, []); + } } diff --git a/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr index 636390cdb3e..5f05fbb5bf9 100644 --- a/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr @@ -11,19 +11,11 @@ contract FPC { gas_token_address: SharedImmutable, } - global CANONICAL_GAS_TOKEN_ADDRESS = AztecAddress::from_field(10518537853519909204957666322334442672584410385979059968848104222965977783517); - #[aztec(public)] #[aztec(initializer)] fn constructor(other_asset: AztecAddress, gas_token_address: AztecAddress) { - let actual_gas_token_address = if is_empty(gas_token_address) { - CANONICAL_GAS_TOKEN_ADDRESS - } else { - gas_token_address - }; - storage.other_asset.initialize(other_asset); - storage.gas_token_address.initialize(actual_gas_token_address); + storage.gas_token_address.initialize(gas_token_address); } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr index 87f9667582b..4d57d958875 100644 --- a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr @@ -9,7 +9,10 @@ contract InclusionProofs { use dep::aztec::{context::Context, note::note_getter_options::NoteStatus}; // docs:start:imports use dep::aztec::history::{ - contract_inclusion::{prove_contract_inclusion, prove_contract_inclusion_at}, + contract_inclusion::{ + prove_contract_deployment_at, prove_contract_non_deployment_at, + prove_contract_initialization_at, prove_contract_non_initialization_at + }, note_inclusion::{prove_note_inclusion, prove_note_inclusion_at}, note_validity::{prove_note_validity, prove_note_validity_at}, nullifier_inclusion::{ @@ -216,32 +219,35 @@ contract InclusionProofs { } } - // Proves that a contract exists at block `block_number`. - // Note: This can be used to approximate a factory pattern --> a factory contract could perform this proof and that - // way verify that a contract at a given address is what it expects. Then it could store it in an internal - // map of contracts (like what Uniswap Factory does with pool contracts - it stores them in a mapping). - // By passing in the construct hash the factory can also verify that the contract was constructed with the - // correct constructor arguments. Typically the factory would store the expected construct hash and assert - // that it is what it expects. The constructor param check is the reason of why we pass in the preimage of - // contract's aztec address instead of just the address. + // Proves that a contract was publicly deployed and/or initialized at block `block_number`. #[aztec(private)] fn test_contract_inclusion( - public_key: GrumpkinPoint, - contract_address_salt: Field, - contract_class_id: ContractClassId, - initialization_hash: Field, - portal_contract_address: EthAddress, - block_number: u32 // The block at which we'll prove that the public value exists + contract_address: AztecAddress, + block_number: u32, + test_deployment: bool, + test_initialization: bool ) { - let proven_contract_address = prove_contract_inclusion_at( - public_key, - contract_address_salt, - contract_class_id, - initialization_hash, - portal_contract_address, - block_number, - context - ); - // Here typically the factory would add the contract address to its internal map of deployed contracts. + if test_deployment { + prove_contract_deployment_at(contract_address, block_number, context); + } + if test_initialization { + prove_contract_initialization_at(contract_address, block_number, context); + } + } + + // Proves that a contract was NOT publicly deployed and/or initialized at block `block_number`. + #[aztec(private)] + fn test_contract_non_inclusion( + contract_address: AztecAddress, + block_number: u32, + test_deployment: bool, + test_initialization: bool + ) { + if test_deployment { + prove_contract_non_deployment_at(contract_address, block_number, context); + } + if test_initialization { + prove_contract_non_initialization_at(contract_address, block_number, context); + } } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr index 49076a1a403..43c012dc9ba 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr @@ -3,14 +3,14 @@ use dep::types::{ abis::{ call_request::CallRequest, accumulated_data::CombinedAccumulatedData, function_data::FunctionData, kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputsBuilder, - membership_witness::NoteHashReadRequestMembershipWitness, new_contract_data::NewContractData, + membership_witness::NoteHashReadRequestMembershipWitness, private_circuit_public_inputs::PrivateCircuitPublicInputs, private_kernel::private_call_data::PrivateCallData, kernel_data::{PrivateKernelInnerData, PrivateKernelTailData}, side_effect::{SideEffect, SideEffectLinkedToNoteHash} }, address::{AztecAddress, EthAddress, PartialAddress, compute_initialization_hash}, - contract_class_id::ContractClassId, contrakt::contract_deployment_data::ContractDeploymentData, + contract_class_id::ContractClassId, constants::{ MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, @@ -19,11 +19,11 @@ use dep::types::{ grumpkin_private_key::GrumpkinPrivateKey, hash::{ compute_constructor_hash, compute_l2_to_l1_hash, compute_logs_hash, - compute_new_contract_address_hash, contract_tree_root_from_siblings, - function_tree_root_from_siblings, pedersen_hash, private_functions_root_from_siblings, - root_from_sibling_path, silo_note_hash, silo_nullifier, + compute_new_contract_address_hash, function_tree_root_from_siblings, pedersen_hash, + private_functions_root_from_siblings, silo_note_hash, silo_nullifier, stdlib_recursion_verification_key_compress_native_vk }, + merkle_tree::check_membership, utils::{arrays::{array_length, array_to_bounded_vec, validate_array}}, traits::{is_empty, is_empty_array} }; @@ -73,8 +73,14 @@ pub fn validate_note_hash_read_requests( // but we use the leaf index as a placeholder to detect a 'pending note read'. if (read_request != 0) & (witness.is_transient == false) { - let root_for_read_request = root_from_sibling_path(read_request, witness.leaf_index, witness.sibling_path); - assert(root_for_read_request == historical_note_hash_tree_root, "note hash tree root mismatch"); + assert( + check_membership( + read_request, + witness.leaf_index, + witness.sibling_path, + historical_note_hash_tree_root + ), "note hash tree root mismatch" + ); // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1354): do we need to enforce // that a non-transient read_request was derived from the proper/current contract address? } @@ -108,8 +114,6 @@ pub fn initialize_end_values( public_inputs.end.encrypted_log_preimages_length = start.encrypted_log_preimages_length; public_inputs.end.unencrypted_log_preimages_length = start.unencrypted_log_preimages_length; - - public_inputs.end.new_contracts = array_to_bounded_vec(start.new_contracts); } fn perform_static_call_checks(private_call: PrivateCallData) { @@ -300,95 +304,43 @@ pub fn update_end_values( public_inputs.end.unencrypted_log_preimages_length = public_inputs.end.unencrypted_log_preimages_length + private_call_public_inputs.unencrypted_log_preimages_length; } -pub fn contract_logic( - private_call: PrivateCallData, - public_inputs: &mut PrivateKernelCircuitPublicInputsBuilder, - contract_dep_data: ContractDeploymentData, - function_data: FunctionData -) { - let private_call_public_inputs = private_call.call_stack_item.public_inputs; - let portal_contract_address = private_call.portal_contract_address; +pub fn contract_logic(private_call: PrivateCallData) { let contract_address = private_call.call_stack_item.contract_address; // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3062): Why is this using a hash function from the stdlib::recursion namespace let private_call_vk_hash = stdlib_recursion_verification_key_compress_native_vk(private_call.vk); - let is_contract_deployment = public_inputs.constants.tx_context.is_contract_deployment_tx; - - // input storage contract address must be 0 if its a constructor call and non-zero otherwise - if is_contract_deployment { - let computed_initialization_hash = compute_initialization_hash( - function_data.selector.to_field(), - private_call_public_inputs.args_hash - ); + assert(!contract_address.is_zero(), "contract address cannot be zero"); + // std::println(f"contract_address={contract_address}"); + // std::println(f"private_call_vk_hash={private_call_vk_hash}"); - assert( - computed_initialization_hash == contract_dep_data.initialization_hash, "initialization hash does not match computed one" - ); - - let new_contract_address = AztecAddress::compute_from_public_key( - contract_dep_data.public_key, - contract_dep_data.contract_class_id, - contract_dep_data.contract_address_salt, - contract_dep_data.initialization_hash, - contract_dep_data.portal_contract_address - ); - - let new_contract_data = NewContractData { - contract_address: new_contract_address, - portal_contract_address, - contract_class_id: contract_dep_data.contract_class_id - }; - public_inputs.end.new_contracts.push(new_contract_data); - - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3062) VKs are mocked out for now - // assert(contract_dep_data.constructor_vk_hash == private_call_vk_hash, "constructor_vk_hash doesn't match private_call_vk_hash"); - - assert( - contract_address.eq(new_contract_address), "contract address supplied does not match derived address" - ); - - let new_contract_address_nullifier = compute_new_contract_address_hash(new_contract_address); - - public_inputs.end.new_nullifiers.push( - SideEffectLinkedToNoteHash { value: new_contract_address_nullifier, note_hash: 0, counter: 1 } - ); - } else { - // non-contract deployments must specify contract address being interacted with - assert(!contract_address.is_zero(), "contract address cannot be zero"); - // std::println(f"contract_address={contract_address}"); - // std::println(f"private_call_vk_hash={private_call_vk_hash}"); - - // Recompute the contract class id - let computed_private_functions_root = private_functions_root_from_siblings( - private_call.call_stack_item.function_data.selector, - private_call_vk_hash, - private_call.function_leaf_membership_witness.leaf_index, - private_call.function_leaf_membership_witness.sibling_path - ); - // std::println(f"computed_private_functions_root={computed_private_functions_root}"); + // Recompute the contract class id + let computed_private_functions_root = private_functions_root_from_siblings( + private_call.call_stack_item.function_data.selector, + private_call_vk_hash, + private_call.function_leaf_membership_witness.leaf_index, + private_call.function_leaf_membership_witness.sibling_path + ); + // std::println(f"computed_private_functions_root={computed_private_functions_root}"); - let computed_contract_class_id = ContractClassId::compute( - private_call.contract_class_artifact_hash, - computed_private_functions_root, - private_call.contract_class_public_bytecode_commitment - ); - // std::println(f"computed_contract_class_id={computed_contract_class_id}"); + let computed_contract_class_id = ContractClassId::compute( + private_call.contract_class_artifact_hash, + computed_private_functions_root, + private_call.contract_class_public_bytecode_commitment + ); + // std::println(f"computed_contract_class_id={computed_contract_class_id}"); - // Recompute contract address using the preimage which includes the class_id - let computed_partial_address = PartialAddress::compute_from_salted_initialization_hash( - computed_contract_class_id, - private_call.salted_initialization_hash - ); - // std::println(f"computed_partial_address={computed_partial_address}"); + // Recompute contract address using the preimage which includes the class_id + let computed_partial_address = PartialAddress::compute_from_salted_initialization_hash( + computed_contract_class_id, + private_call.salted_initialization_hash + ); + // std::println(f"computed_partial_address={computed_partial_address}"); - let computed_address = AztecAddress::compute(private_call.public_keys_hash, computed_partial_address); - // std::println(f"computed_address={computed_address}"); + let computed_address = AztecAddress::compute(private_call.public_keys_hash, computed_partial_address); + // std::println(f"computed_address={computed_address}"); - assert( - computed_address.eq(contract_address), "computed contract address does not match expected one" - ); - } + assert(computed_address.eq(contract_address), "computed contract address does not match expected one"); } pub fn validate_previous_kernel_values(end: CombinedAccumulatedData) { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr index 6da43c3f9ba..b94c09f3000 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr @@ -100,12 +100,7 @@ impl PrivateKernelInitCircuitPrivateInputs { self.update_end_values(&mut public_inputs); common::update_end_values(self.private_call, &mut public_inputs); - common::contract_logic( - self.private_call, - &mut public_inputs, - self.tx_request.tx_context.contract_deployment_data, - self.tx_request.function_data - ); + common::contract_logic(self.private_call); // TODO(David): What previous kernel proof are we talking about, since this is private-kernel-init let (is_previous_state_valid, updated_aggregation_object) = verify_previous_kernel_state(public_inputs.aggregation_object, self.private_call.proof); @@ -142,15 +137,7 @@ mod tests { impl PrivateKernelInitInputsBuilder { pub fn new() -> Self { - PrivateKernelInitInputsBuilder::new_with_config(false) - } - - pub fn new_constructor() -> Self { - PrivateKernelInitInputsBuilder::new_with_config(true) - } - - fn new_with_config(is_constructor: bool) -> Self { - let private_call = PrivateCallDataBuilder::new(is_constructor); + let private_call = PrivateCallDataBuilder::new(); let tx_request = private_call.build_tx_request(); PrivateKernelInitInputsBuilder { tx_request, private_call } @@ -167,33 +154,6 @@ mod tests { } } - pub fn validate_deployed_contract_address(tx_request: TxRequest, public_inputs: PrivateKernelInnerCircuitPublicInputs) { - assert_eq(public_inputs.end.new_contracts.len(), 1); - let cdd = tx_request.tx_context.contract_deployment_data; - - let computed_initialization_hash = compute_initialization_hash( - tx_request.function_data.selector.to_field(), - tx_request.args_hash - ); - assert( - computed_initialization_hash == cdd.initialization_hash, "initialization hash does not match computed one" - ); - let contract_address = AztecAddress::compute_from_public_key( - cdd.public_key, - cdd.contract_class_id, - cdd.contract_address_salt, - cdd.initialization_hash, - cdd.portal_contract_address - ); - assert(public_inputs.end.new_contracts[0].contract_address.eq(contract_address)); - } - - pub fn validate_no_new_deployed_contract(public_inputs: PrivateKernelInnerCircuitPublicInputs) { - for new_contract in public_inputs.end.new_contracts { - assert(new_contract.is_empty()); - } - } - #[test] fn deposit() { let mut builder = PrivateKernelInitInputsBuilder::new(); @@ -208,8 +168,6 @@ mod tests { let public_inputs = builder.execute(); - validate_no_new_deployed_contract(public_inputs); - // Check the first nullifier is hash of the signed tx request let tx_hash = builder.tx_request.hash(); assert_eq(public_inputs.end.new_nullifiers[0].value, tx_hash); @@ -226,27 +184,9 @@ mod tests { assert_eq(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); } - #[test] - fn basic_contract_deployment() { - let builder = PrivateKernelInitInputsBuilder::new_constructor(); - - let public_inputs = builder.execute(); - - validate_deployed_contract_address(builder.tx_request, public_inputs); - - // Since there are no logs, log preimages length should be 0 and both logs hashes should be a sha256 hash of 2 zero - // values - assert_eq(public_inputs.end.encrypted_log_preimages_length, 0); - assert_eq(public_inputs.end.unencrypted_log_preimages_length, 0); - - let expected_logs_hash = compute_logs_hash([0, 0], [0, 0]); - assert_eq(public_inputs.end.encrypted_logs_hash, expected_logs_hash); - assert_eq(public_inputs.end.unencrypted_logs_hash, expected_logs_hash); - } - #[test(should_fail_with = "invalid array")] fn input_validation_malformed_arrays_return_values() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); + let mut builder = PrivateKernelInitInputsBuilder::new(); builder.private_call.public_inputs.return_values.extend_from_array([0, 9123]); @@ -255,7 +195,7 @@ mod tests { #[test(should_fail_with = "invalid array")] fn input_validation_malformed_arrays_note_hash_read_requests() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); + let mut builder = PrivateKernelInitInputsBuilder::new(); builder.private_call.public_inputs.note_hash_read_requests.extend_from_array( [ @@ -269,7 +209,7 @@ mod tests { #[test(should_fail_with = "invalid array")] fn input_validation_malformed_arrays_commitments() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); + let mut builder = PrivateKernelInitInputsBuilder::new(); builder.private_call.public_inputs.new_note_hashes.extend_from_array( [ @@ -283,7 +223,7 @@ mod tests { #[test(should_fail_with = "invalid array")] fn input_validation_malformed_arrays_nullifiers() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); + let mut builder = PrivateKernelInitInputsBuilder::new(); builder.private_call.public_inputs.new_nullifiers.extend_from_array( [ @@ -297,7 +237,7 @@ mod tests { #[test(should_fail_with = "invalid array")] fn input_validation_malformed_arrays_private_call_stack() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); + let mut builder = PrivateKernelInitInputsBuilder::new(); builder.private_call.public_inputs.private_call_stack_hashes.extend_from_array([0, 9123]); @@ -306,7 +246,7 @@ mod tests { #[test(should_fail_with = "invalid array")] fn input_validation_malformed_arrays_public_call_stack() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); + let mut builder = PrivateKernelInitInputsBuilder::new(); builder.private_call.public_inputs.public_call_stack_hashes.extend_from_array([0, 9123]); @@ -315,7 +255,7 @@ mod tests { #[test(should_fail_with = "invalid array")] fn input_validation_malformed_arrays_new_l2_to_l1_msgs() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); + let mut builder = PrivateKernelInitInputsBuilder::new(); builder.private_call.public_inputs.new_l2_to_l1_msgs.extend_from_array( [ @@ -327,51 +267,9 @@ mod tests { builder.failed(); } - #[test(should_fail_with="contract address supplied does not match derived address")] - fn contract_deployment_incorrect_contract_address_fails() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); - - let random_address = AztecAddress::from_field(27); - builder.private_call.public_inputs.call_context.storage_contract_address = random_address; - builder.tx_request.origin = random_address; - builder.private_call.contract_address = random_address; - - builder.failed(); - } - - #[test(should_fail_with="origin address does not match call stack items contract address")] - fn contract_deployment_contract_address_mismatch_fails() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); - - let random_address = AztecAddress::from_field(27); - builder.private_call.public_inputs.call_context.storage_contract_address = random_address; - builder.private_call.contract_address = random_address; - - builder.failed(); - } - - #[test(should_fail_with="tx_request function_data must match call_stack_item function_data")] - fn contract_deployment_function_data_mismatch_fails() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); - - builder.tx_request.function_data.selector.inner = 27; - - builder.failed(); - } - - #[test(should_fail_with="noir function args passed to tx_request must match args in the call_stack_item")] - fn contract_deployment_args_hash_mismatch_fails() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); - - // Modify the args hash in tx request. - builder.tx_request.args_hash = 29; - - builder.failed(); - } - #[test(should_fail_with="Private kernel circuit can only execute a private function")] fn private_function_is_private_false_fails() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); + let mut builder = PrivateKernelInitInputsBuilder::new(); // Set is_private in function data to false. builder.private_call.function_data.is_private = false; @@ -381,7 +279,7 @@ mod tests { #[test(should_fail_with="Cannot call an internal function directly")] fn private_function_is_internal_fails() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); + let mut builder = PrivateKernelInitInputsBuilder::new(); builder.private_call.function_data.is_internal = true; @@ -390,7 +288,7 @@ mod tests { #[test(should_fail_with="Users cannot make a static call")] fn private_function_static_call_fails() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); + let mut builder = PrivateKernelInitInputsBuilder::new(); // Set is_static_call to true. builder.private_call.public_inputs.call_context.is_static_call = true; @@ -400,7 +298,7 @@ mod tests { #[test(should_fail_with="Users cannot make a delegatecall")] fn private_function_delegate_call_fails() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); + let mut builder = PrivateKernelInitInputsBuilder::new(); // Set is_delegate_call to true. builder.private_call.public_inputs.call_context.is_delegate_call = true; @@ -410,7 +308,7 @@ mod tests { #[test(should_fail_with="Storage contract address must be that of the called contract")] fn private_function_incorrect_storage_contract_address_fails() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); + let mut builder = PrivateKernelInitInputsBuilder::new(); // Set the storage_contract_address to a random scalar. builder.private_call.public_inputs.call_context.storage_contract_address = AztecAddress::from_field(356); @@ -508,7 +406,6 @@ mod tests { let public_inputs = builder.execute(); - validate_no_new_deployed_contract(public_inputs); // Check the first nullifier is hash of the signed tx request assert_eq(public_inputs.end.new_nullifiers[0].value, builder.tx_request.hash()); @@ -524,7 +421,6 @@ mod tests { let public_inputs = builder.execute(); - validate_no_new_deployed_contract(public_inputs); // Check the first nullifier is hash of the signed tx request assert_eq(public_inputs.end.new_nullifiers[0].value, builder.tx_request.hash()); @@ -540,7 +436,6 @@ mod tests { let public_inputs = builder.execute(); - validate_no_new_deployed_contract(public_inputs); // Check the first nullifier is hash of the signed tx request assert_eq(public_inputs.end.new_nullifiers[0].value, builder.tx_request.hash()); @@ -556,7 +451,6 @@ mod tests { let public_inputs = builder.execute(); - validate_no_new_deployed_contract(public_inputs); // Check the first nullifier is hash of the signed tx request assert_eq(public_inputs.end.new_nullifiers[0].value, builder.tx_request.hash()); @@ -572,7 +466,6 @@ mod tests { let public_inputs = builder.execute(); - validate_no_new_deployed_contract(public_inputs); // Check the first nullifier is hash of the signed tx request assert_eq(public_inputs.end.new_nullifiers[0].value, builder.tx_request.hash()); @@ -589,7 +482,6 @@ mod tests { let public_inputs = builder.execute(); - validate_no_new_deployed_contract(public_inputs); // Check the first nullifier is hash of the signed tx request assert_eq(public_inputs.end.new_nullifiers[0].value, builder.tx_request.hash()); @@ -605,7 +497,6 @@ mod tests { let public_inputs = builder.execute(); - validate_no_new_deployed_contract(public_inputs); // Check the first nullifier is hash of the signed tx request assert_eq(public_inputs.end.new_nullifiers[0].value, builder.tx_request.hash()); @@ -617,7 +508,7 @@ mod tests { #[test] fn propagate_nullifier_read_requests() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); + let mut builder = PrivateKernelInitInputsBuilder::new(); let storage_contract_address = builder.private_call.public_inputs.call_context.storage_contract_address; let request_0 = ReadRequest { value: 123, counter: 4567 }; @@ -643,7 +534,7 @@ mod tests { #[test] fn propagate_nullifier_key_validation_requests() { - let mut builder = PrivateKernelInitInputsBuilder::new_constructor(); + let mut builder = PrivateKernelInitInputsBuilder::new(); let request = NullifierKeyValidationRequest { public_key: GrumpkinPoint { x: 1, y: 2 }, secret_key: GrumpkinPrivateKey { high: 3, low: 4 } }; builder.private_call.public_inputs.nullifier_key_validation_requests.push(request); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr index 4b2fd76d3b1..0ed47ed052b 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -20,15 +20,6 @@ impl PrivateKernelInnerCircuitPrivateInputs { common::validate_call_against_request(self.private_call, call_request); } - fn validate_contract_tree_root(self) { - let purported_contract_tree_root = self.private_call.call_stack_item.public_inputs.historical_header.state.partial.contract_tree.root; - let previous_kernel_contract_tree_root = self.previous_kernel.public_inputs.constants.historical_header.state.partial.contract_tree.root; - - assert( - purported_contract_tree_root == previous_kernel_contract_tree_root, "purported_contract_tree_root does not match previous_kernel_contract_tree_root" - ); - } - fn validate_inputs(self) { let this_call_stack_item = self.private_call.call_stack_item; let function_data = this_call_stack_item.function_data; @@ -63,17 +54,7 @@ impl PrivateKernelInnerCircuitPrivateInputs { //TODO(David): feels like update_end_values should happen later common::update_end_values(self.private_call, &mut public_inputs); - // ensure that historical/purported contract tree root matches the one in previous kernel - self.validate_contract_tree_root(); - - let this_call_stack_item = self.private_call.call_stack_item; - - common::contract_logic( - self.private_call, - &mut public_inputs, - this_call_stack_item.public_inputs.contract_deployment_data, - this_call_stack_item.function_data - ); + common::contract_logic(self.private_call); let (is_previous_state_valid, updated_aggregation_object) = verify_previous_kernel_state(public_inputs.aggregation_object, self.private_call.proof); assert(is_previous_state_valid); @@ -105,7 +86,7 @@ mod tests { impl PrivateKernelInnerInputsBuilder { pub fn new() -> Self { let previous_kernel = PreviousKernelDataBuilder::new(false); - let private_call = PrivateCallDataBuilder::new(false); + let private_call = PrivateCallDataBuilder::new(); PrivateKernelInnerInputsBuilder { previous_kernel, private_call } } @@ -159,17 +140,6 @@ mod tests { builder.failed(); } - #[test(should_fail_with = "purported_contract_tree_root does not match previous_kernel_contract_tree_root")] - fn private_function_incorrect_contract_tree_root_fails() { - let mut builder = PrivateKernelInnerInputsBuilder::new(); - - // Set historical contract tree root to a wrong value (the correct value + 1). - let contract_tree_root = builder.previous_kernel.historical_header.state.partial.contract_tree.root; - builder.previous_kernel.historical_header.state.partial.contract_tree.root = contract_tree_root + 1; - - builder.failed(); - } - #[test(should_fail_with="computed contract address does not match expected one")] fn private_function_incorrect_function_leaf_index_fails() { let mut builder = PrivateKernelInnerInputsBuilder::new(); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr index b6d6de9fab3..46f9cda62a5 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr @@ -1,12 +1,11 @@ use crate::common; use dep::std::{cmp::Eq, option::Option, unsafe}; -use dep::reset_kernel_lib::{NullifierReadRequestResetHints, reset_read_requests}; +use dep::reset_kernel_lib::{NullifierReadRequestHints, reset_read_requests}; use dep::types::{ abis::{ call_request::CallRequest, nullifier_key_validation_request::NullifierKeyValidationRequestContext, kernel_data::{PrivateKernelInnerData, PrivateKernelTailData}, kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputsBuilder, PrivateKernelTailCircuitPublicInputs}, - membership_witness::{MembershipWitness, NullifierMembershipWitness}, side_effect::{SideEffect, SideEffectLinkedToNoteHash, Ordered} }, constants::{ @@ -26,7 +25,7 @@ struct PrivateKernelTailCircuitPrivateInputs { read_commitment_hints: [u64; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], sorted_new_nullifiers: [SideEffectLinkedToNoteHash; MAX_NEW_NULLIFIERS_PER_TX], sorted_new_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], - nullifier_read_request_reset_hints: NullifierReadRequestResetHints, + nullifier_read_request_hints: NullifierReadRequestHints, nullifier_commitment_hints: [u64; MAX_NEW_NULLIFIERS_PER_TX], master_nullifier_secret_keys: [GrumpkinPrivateKey; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], } @@ -43,7 +42,7 @@ impl PrivateKernelTailCircuitPrivateInputs { let pending_nullifiers = self.previous_kernel.public_inputs.end.new_nullifiers; - let hints = self.nullifier_read_request_reset_hints; + let hints = self.nullifier_read_request_hints; let nullifier_tree_root = public_inputs.constants.historical_header.state.partial.nullifier_tree.root; @@ -256,7 +255,7 @@ mod tests { use dep::std::{cmp::Eq, unsafe}; use crate::{private_kernel_tail::PrivateKernelTailCircuitPrivateInputs}; use dep::reset_kernel_lib::{ - NullifierReadRequestResetHintsBuilder, + tests::nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder, read_request_reset::{PendingReadHint, ReadRequestState, ReadRequestStatus} }; use dep::types::constants::{ @@ -277,7 +276,7 @@ mod tests { previous_kernel: PreviousKernelDataBuilder, read_commitment_hints: [u64; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], nullifier_commitment_hints: [u64; MAX_NEW_NULLIFIERS_PER_TX], - nullifier_read_request_reset_hints_builder: NullifierReadRequestResetHintsBuilder, + nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder, } impl PrivateKernelTailInputsBuilder { @@ -286,7 +285,7 @@ mod tests { previous_kernel: PreviousKernelDataBuilder::new(false), read_commitment_hints: [0; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], nullifier_commitment_hints: [0; MAX_NEW_NULLIFIERS_PER_TX], - nullifier_read_request_reset_hints_builder: NullifierReadRequestResetHintsBuilder::new(MAX_NULLIFIER_READ_REQUESTS_PER_TX) + nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder::new(MAX_NULLIFIER_READ_REQUESTS_PER_TX) } } @@ -326,10 +325,10 @@ mod tests { pub fn add_nullifier_pending_read(&mut self, nullifier_index_offset_one: u64) { let nullifier_index = nullifier_index_offset_one + 1; // + 1 is for the first nullifier let read_request_index = self.previous_kernel.add_read_request_for_pending_nullifier(nullifier_index); - let hint_index = self.nullifier_read_request_reset_hints_builder.pending_read_hints.len(); + let hint_index = self.nullifier_read_request_hints_builder.pending_read_hints.len(); let hint = PendingReadHint { read_request_index, pending_value_index: nullifier_index }; - self.nullifier_read_request_reset_hints_builder.pending_read_hints.push(hint); - self.nullifier_read_request_reset_hints_builder.read_request_statuses[read_request_index] = ReadRequestStatus { state: ReadRequestState.PENDING, hint_index }; + self.nullifier_read_request_hints_builder.pending_read_hints.push(hint); + self.nullifier_read_request_hints_builder.read_request_statuses[read_request_index] = ReadRequestStatus { state: ReadRequestState.PENDING, hint_index }; } pub fn nullify_transient_commitment(&mut self, nullifier_index: Field, commitment_index: u64) { @@ -383,7 +382,7 @@ mod tests { read_commitment_hints: sorted_read_commitment_hints, sorted_new_nullifiers, sorted_new_nullifiers_indexes, - nullifier_read_request_reset_hints: self.nullifier_read_request_reset_hints_builder.to_hints(), + nullifier_read_request_hints: self.nullifier_read_request_hints_builder.to_hints(), nullifier_commitment_hints: sorted_nullifier_commitment_hints, master_nullifier_secret_keys: unsafe::zeroed() }; @@ -480,10 +479,10 @@ mod tests { builder.append_nullifiers(3); builder.add_nullifier_pending_read(1); - let mut hint = builder.nullifier_read_request_reset_hints_builder.pending_read_hints.pop(); + let mut hint = builder.nullifier_read_request_hints_builder.pending_read_hints.pop(); assert(hint.pending_value_index == 2); hint.pending_value_index = 1; - builder.nullifier_read_request_reset_hints_builder.pending_read_hints.push(hint); + builder.nullifier_read_request_hints_builder.pending_read_hints.push(hint); builder.failed(); } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr index d0a97da56de..550649723f8 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr @@ -2,18 +2,18 @@ use dep::types::{ abis::{ call_request::CallRequest, public_call_stack_item::PublicCallStackItem, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputsBuilder, - new_contract_data::NewContractData, kernel_data::{PrivateKernelTailData, PublicKernelData}, - public_call_data::PublicCallData, public_data_read::PublicDataRead, - public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequestContext, - side_effect::{SideEffect, SideEffectLinkedToNoteHash} + kernel_data::{PrivateKernelTailData, PublicKernelData}, public_call_data::PublicCallData, + public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, + read_request::ReadRequestContext, side_effect::{SideEffect, SideEffectLinkedToNoteHash} }, address::AztecAddress, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, constants::{ MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, - MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_PUBLIC_DATA_READS_PER_CALL, NUM_FIELDS_PER_SHA256, - MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_PUBLIC_DATA_READS_PER_CALL, NUM_FIELDS_PER_SHA256, MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, + MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX }, hash::{silo_note_hash, silo_nullifier, compute_l2_to_l1_hash, accumulate_sha256}, @@ -25,9 +25,6 @@ use crate::hash::{compute_public_data_tree_index, compute_public_data_tree_value pub fn validate_inputs(public_call: PublicCallData) { // Validates commons inputs for all type of kernel inputs let this_call_stack_item: PublicCallStackItem = public_call.call_stack_item; - assert( - this_call_stack_item.public_inputs.call_context.is_contract_deployment == false, "Contract deployment cannot be a public function" - ); assert( !this_call_stack_item.contract_address.eq(AztecAddress::zero()), "Contract address cannot be zero" ); @@ -66,7 +63,6 @@ pub fn initialize_emitted_end_values( circuit_outputs.end.unencrypted_log_preimages_length = start.unencrypted_log_preimages_length; circuit_outputs.end.encrypted_logs_hash = start.encrypted_logs_hash; circuit_outputs.end.encrypted_log_preimages_length = start.encrypted_log_preimages_length; - circuit_outputs.end.new_contracts = array_to_bounded_vec(previous_kernel.public_inputs.end.new_contracts); } let start_non_revertible = previous_kernel.public_inputs.end_non_revertible; @@ -94,6 +90,7 @@ pub fn initialize_end_values( let start_non_revertible = previous_kernel.public_inputs.end_non_revertible; circuit_outputs.end_non_revertible.public_call_stack = array_to_bounded_vec(start_non_revertible.public_call_stack); circuit_outputs.end_non_revertible.nullifier_read_requests = array_to_bounded_vec(start_non_revertible.nullifier_read_requests); + circuit_outputs.end_non_revertible.nullifier_non_existent_read_requests = array_to_bounded_vec(start_non_revertible.nullifier_non_existent_read_requests); } fn perform_static_call_checks(public_call: PublicCallData) { @@ -166,6 +163,7 @@ pub fn update_public_end_non_revertible_values( circuit_outputs.end_non_revertible.public_call_stack.extend_from_bounded_vec(public_call_requests); propagate_nullifier_read_requests_non_revertible(public_call, circuit_outputs); + propagate_nullifier_non_existent_read_requests_non_revertible(public_call, circuit_outputs); propagate_new_nullifiers_non_revertible(public_call, circuit_outputs); propagate_new_note_hashes_non_revertible(public_call, circuit_outputs); propagate_valid_non_revertible_public_data_update_requests(public_call, circuit_outputs); @@ -187,6 +185,8 @@ pub fn update_public_end_values(public_call: PublicCallData, circuit_outputs: &m circuit_outputs.end.public_call_stack.extend_from_bounded_vec(public_call_requests); propagate_nullifier_read_requests_revertible(public_call, circuit_outputs); + propagate_nullifier_non_existent_read_requests_non_revertible(public_call, circuit_outputs); // TODO - Requests are not revertible and should be propagated to "validation_requests". + propagate_new_nullifiers(public_call, circuit_outputs); propagate_new_note_hashes(public_call, circuit_outputs); @@ -229,6 +229,22 @@ fn propagate_nullifier_read_requests_revertible( } } +fn propagate_nullifier_non_existent_read_requests_non_revertible( + public_call: PublicCallData, + circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder +) { + let public_call_public_inputs = public_call.call_stack_item.public_inputs; + let nullifier_non_existent_read_requests = public_call_public_inputs.nullifier_non_existent_read_requests; + let storage_contract_address = public_call_public_inputs.call_context.storage_contract_address; + + for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL { + let request = nullifier_non_existent_read_requests[i]; + if !is_empty(request) { + circuit_outputs.end_non_revertible.nullifier_non_existent_read_requests.push(request.to_context(storage_contract_address)); + } + } +} + fn propagate_valid_public_data_update_requests( public_call: PublicCallData, circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr index 810e32dcf37..defa25ed06e 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr @@ -68,23 +68,21 @@ mod tests { use crate::{ public_kernel_app_logic::PublicKernelAppLogicCircuitPrivateInputs, utils::{ - assert_eq_call_requests, assert_eq_new_contracts, assert_eq_public_data_reads, - assert_eq_public_data_update_requests, compute_public_data_reads, - compute_public_data_update_requests + assert_eq_call_requests, assert_eq_public_data_reads, assert_eq_public_data_update_requests, + compute_public_data_reads, compute_public_data_update_requests } }; use dep::types::{ abis::{ - new_contract_data::NewContractData, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, public_data_read::PublicDataRead, - public_data_update_request::PublicDataUpdateRequest, + public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequest, side_effect::{SideEffect, SideEffectLinkedToNoteHash} }, address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, hash::{compute_l2_to_l1_hash, compute_logs_hash, silo_note_hash, silo_nullifier}, messaging::l2_to_l1_message::L2ToL1Message, tests::{kernel_data_builder::PreviousKernelDataBuilder, public_call_data_builder::PublicCallDataBuilder}, - utils::{arrays::array_eq} + utils::arrays::{array_eq, array_length} }; use dep::types::constants::{MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL}; @@ -398,14 +396,6 @@ mod tests { #[test] fn circuit_outputs_should_be_correctly_populated_with_previous_private_kernel() { let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new(); - let new_contracts = [ - NewContractData { - contract_address: AztecAddress::from_field(123), - portal_contract_address: EthAddress::from_field(456), - contract_class_id: ContractClassId::from_field(78) - } - ]; - builder.previous_kernel.end.new_contracts.extend_from_array(new_contracts); builder.public_call.append_public_call_requests_for_regular_calls(2); let storage = builder.public_call.public_call_stack.storage; @@ -421,7 +411,6 @@ mod tests { let public_inputs = builder.execute(); - assert_eq_new_contracts(public_inputs.end.new_contracts, new_contracts); assert_eq_call_requests(public_inputs.end.private_call_stack, []); assert_eq_call_requests(public_inputs.end.public_call_stack, public_call_stack); assert_eq_public_data_update_requests( @@ -430,4 +419,30 @@ mod tests { ); assert_eq_public_data_reads(public_inputs.end.public_data_reads, read_requests); } + + #[test] + fn propagate_nullifier_non_existent_read_requests() { + let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new(); + let storage_contract_address = builder.public_call.public_inputs.call_context.storage_contract_address; + + let request_0 = ReadRequest { value: 123, counter: 4567 }; + builder.public_call.public_inputs.nullifier_non_existent_read_requests.push(request_0); + let request_1 = ReadRequest { value: 777888, counter: 90 }; + builder.public_call.public_inputs.nullifier_non_existent_read_requests.push(request_1); + + let public_inputs = builder.execute(); + + let end_requests = public_inputs.end_non_revertible.nullifier_non_existent_read_requests; + assert_eq(array_length(end_requests), 2); + + let request_context = end_requests[0]; + assert_eq(request_context.value, request_0.value); + assert_eq(request_context.counter, request_0.counter); + assert_eq(request_context.contract_address, storage_contract_address); + + let request_context = end_requests[1]; + assert_eq(request_context.value, request_1.value); + assert_eq(request_context.counter, request_1.counter); + assert_eq(request_context.contract_address, storage_contract_address); + } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr index 539eff98fe9..560b2b848e6 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr @@ -70,17 +70,16 @@ mod tests { use crate::{ public_kernel_setup::PublicKernelSetupCircuitPrivateInputs, utils::{ - assert_eq_call_requests, assert_eq_new_contracts, assert_eq_public_data_reads, - assert_eq_public_data_update_requests, compute_public_data_reads, - compute_public_data_update_requests + assert_eq_call_requests, assert_eq_public_data_reads, assert_eq_public_data_update_requests, + compute_public_data_reads, compute_public_data_update_requests } }; use dep::types::{ abis::{ call_request::CallRequest, function_selector::FunctionSelector, - kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, - new_contract_data::NewContractData, public_data_read::PublicDataRead, - public_data_update_request::PublicDataUpdateRequest, public_call_data::PublicCallData + kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, public_data_read::PublicDataRead, + public_data_update_request::PublicDataUpdateRequest, public_call_data::PublicCallData, + read_request::ReadRequest }, address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, contrakt::storage_read::StorageRead, hash::compute_logs_hash, @@ -377,14 +376,6 @@ mod tests { #[test] fn circuit_outputs_should_be_correctly_populated_with_previous_private_kernel() { let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); - let new_contracts = [ - NewContractData { - contract_address: AztecAddress::from_field(123), - portal_contract_address: EthAddress::from_field(456), - contract_class_id: ContractClassId::from_field(78) - } - ]; - builder.previous_kernel.end.new_contracts.extend_from_array(new_contracts); builder.public_call.append_public_call_requests_for_regular_calls(2); let storage = builder.public_call.public_call_stack.storage; @@ -413,7 +404,6 @@ mod tests { let public_inputs = kernel.public_kernel_setup(); - assert_eq_new_contracts(public_inputs.end.new_contracts, new_contracts); assert_eq_call_requests(public_inputs.end.private_call_stack, []); assert_eq_call_requests( public_inputs.end_non_revertible.public_call_stack, @@ -507,4 +497,30 @@ mod tests { let expected_unencrypted_logs_hash = compute_logs_hash(prev_unencrypted_logs_hash, unencrypted_logs_hash); assert_eq(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); } + + #[test] + fn propagate_nullifier_non_existent_read_requests() { + let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); + let storage_contract_address = builder.public_call.public_inputs.call_context.storage_contract_address; + + let request_0 = ReadRequest { value: 123, counter: 4567 }; + builder.public_call.public_inputs.nullifier_non_existent_read_requests.push(request_0); + let request_1 = ReadRequest { value: 777888, counter: 90 }; + builder.public_call.public_inputs.nullifier_non_existent_read_requests.push(request_1); + + let public_inputs = builder.execute(); + + let end_requests = public_inputs.end_non_revertible.nullifier_non_existent_read_requests; + assert_eq(array_length(end_requests), 2); + + let request_context = end_requests[0]; + assert_eq(request_context.value, request_0.value); + assert_eq(request_context.counter, request_0.counter); + assert_eq(request_context.contract_address, storage_contract_address); + + let request_context = end_requests[1]; + assert_eq(request_context.value, request_1.value); + assert_eq(request_context.counter, request_1.counter); + assert_eq(request_context.contract_address, storage_contract_address); + } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr index d6242fe3292..f0ed14abc3c 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr @@ -1,17 +1,23 @@ use crate::common; -use dep::reset_kernel_lib::{NullifierReadRequestResetHints, reset_read_requests}; +use dep::reset_kernel_lib::{ + NullifierReadRequestHints, NullifierNonExistentReadRequestHints, reset_non_existent_read_requests, + reset_read_requests +}; use dep::types::{ abis::{ kernel_circuit_public_inputs::{PublicKernelCircuitPublicInputs, PublicKernelCircuitPublicInputsBuilder}, kernel_data::PublicKernelData, side_effect::SideEffectLinkedToNoteHash }, - constants::MAX_NEW_NULLIFIERS_PER_TX, utils::{arrays::{array_length, array_merge, array_concat}} + constants::MAX_NEW_NULLIFIERS_PER_TX, + utils::{arrays::{array_length, array_merge, array_concat, array_to_bounded_vec, assert_sorted_array}}, + hash::silo_nullifier, traits::is_empty }; use dep::std::unsafe; struct PublicKernelTailCircuitPrivateInputs { previous_kernel: PublicKernelData, - nullifier_read_request_reset_hints: NullifierReadRequestResetHints, + nullifier_read_request_hints: NullifierReadRequestHints, + nullifier_non_existent_read_request_hints: NullifierNonExistentReadRequestHints, } impl PublicKernelTailCircuitPrivateInputs { @@ -44,7 +50,7 @@ impl PublicKernelTailCircuitPrivateInputs { let pending_nullifiers: [SideEffectLinkedToNoteHash; MAX_NEW_NULLIFIERS_PER_TX] = array_concat(end_non_revertible.new_nullifiers, end.new_nullifiers); - let hints = self.nullifier_read_request_reset_hints; + let hints = self.nullifier_read_request_hints; let nullifier_tree_root = public_inputs.constants.historical_header.state.partial.nullifier_tree.root; @@ -62,6 +68,42 @@ impl PublicKernelTailCircuitPrivateInputs { ); } + fn validate_nullifier_non_existent_read_requests(self, public_inputs: &mut PublicKernelCircuitPublicInputsBuilder) { + let end_non_revertible = self.previous_kernel.public_inputs.end_non_revertible; + let end = self.previous_kernel.public_inputs.end; + + // The values of the read requests here need to be siloed. + // Notice that it's not the case for regular read requests, which can be run between two kernel iterations, and will to be verified against unsiloed pending values. + let mut read_requests = end_non_revertible.nullifier_non_existent_read_requests; + for i in 0..read_requests.len() { + let read_request = read_requests[i]; + if !is_empty(read_request) { + read_requests[i].value = silo_nullifier(read_request.contract_address, read_request.value); + } + } + + let nullifier_tree_root = public_inputs.constants.historical_header.state.partial.nullifier_tree.root; + + let hints = self.nullifier_non_existent_read_request_hints; + + let pending_nullifiers: [SideEffectLinkedToNoteHash; MAX_NEW_NULLIFIERS_PER_TX] = array_concat(end_non_revertible.new_nullifiers, end.new_nullifiers); + assert_sorted_array( + pending_nullifiers, + hints.sorted_pending_values, + hints.sorted_pending_value_index_hints, + |a: SideEffectLinkedToNoteHash, b: SideEffectLinkedToNoteHash| a.value.lt(b.value) + ); + let sorted_pending_nullifiers = array_to_bounded_vec(hints.sorted_pending_values); + + reset_non_existent_read_requests( + read_requests, + hints.non_membership_hints, + nullifier_tree_root, + sorted_pending_nullifiers, + hints.next_pending_value_indices + ); + } + pub fn public_kernel_tail(self) -> PublicKernelCircuitPublicInputs { let mut public_inputs: PublicKernelCircuitPublicInputsBuilder = unsafe::zeroed(); @@ -73,6 +115,8 @@ impl PublicKernelTailCircuitPrivateInputs { self.validate_nullifier_read_requests(&mut public_inputs); + self.validate_nullifier_non_existent_read_requests(&mut public_inputs); + public_inputs.to_inner() } } @@ -80,57 +124,114 @@ impl PublicKernelTailCircuitPrivateInputs { mod tests { use crate::{public_kernel_tail::PublicKernelTailCircuitPrivateInputs}; use dep::reset_kernel_lib::{ - NullifierReadRequestResetHintsBuilder, + tests::{ + nullifier_non_existent_read_request_hints_builder::NullifierNonExistentReadRequestHintsBuilder, + nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder + }, read_request_reset::{PendingReadHint, ReadRequestState, ReadRequestStatus} }; use dep::types::{ abis::{ kernel_circuit_public_inputs::{PublicKernelCircuitPublicInputs, PublicKernelCircuitPublicInputsBuilder}, - kernel_data::PublicKernelData + kernel_data::PublicKernelData, nullifier_leaf_preimage::NullifierLeafPreimage }, - constants::MAX_NULLIFIER_READ_REQUESTS_PER_TX, - tests::{kernel_data_builder::PreviousKernelDataBuilder} + constants::{ + MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT, + NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_HEIGHT + }, + hash::silo_nullifier, + tests::{kernel_data_builder::PreviousKernelDataBuilder, merkle_tree_utils::NonEmptyMerkleTree}, + utils::arrays::array_concat }; + fn build_nullifier_tree() -> NonEmptyMerkleTree { + let mut pre_existing_nullifiers = [NullifierLeafPreimage::empty(); MAX_NEW_NULLIFIERS_PER_TX]; + pre_existing_nullifiers[0] = NullifierLeafPreimage { nullifier: 0, next_nullifier: 100, next_index: 1 }; + pre_existing_nullifiers[1] = NullifierLeafPreimage { nullifier: 100, next_nullifier: 0, next_index: 0 }; + NonEmptyMerkleTree::new( + pre_existing_nullifiers.map(|preimage: NullifierLeafPreimage| preimage.hash()), + [0; NULLIFIER_TREE_HEIGHT], + [0; NULLIFIER_TREE_HEIGHT - NULLIFIER_SUBTREE_HEIGHT], + [0; NULLIFIER_SUBTREE_HEIGHT] + ) + } + struct PublicKernelTailCircuitPrivateInputsBuilder { previous_kernel: PreviousKernelDataBuilder, - nullifier_read_request_reset_hints_builder: NullifierReadRequestResetHintsBuilder, + nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder, + nullifier_non_existent_read_request_hints_builder: NullifierNonExistentReadRequestHintsBuilder, } impl PublicKernelTailCircuitPrivateInputsBuilder { pub fn new() -> Self { let previous_kernel = PreviousKernelDataBuilder::new(true); + let mut nullifier_non_existent_read_request_hints_builder = NullifierNonExistentReadRequestHintsBuilder::new(); - PublicKernelTailCircuitPrivateInputsBuilder { + let mut builder = PublicKernelTailCircuitPrivateInputsBuilder { previous_kernel, - nullifier_read_request_reset_hints_builder: NullifierReadRequestResetHintsBuilder::new(MAX_NULLIFIER_READ_REQUESTS_PER_TX) - } + nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder::new(MAX_NULLIFIER_READ_REQUESTS_PER_TX), + nullifier_non_existent_read_request_hints_builder + }; + builder.set_nullifiers_for_non_existent_read_request_hints(); + builder + } + + pub fn with_nullifier_tree(&mut self) -> Self { + let nullifier_tree = build_nullifier_tree(); + self.previous_kernel.historical_header.state.partial.nullifier_tree.root = nullifier_tree.get_root(); + self.nullifier_non_existent_read_request_hints_builder.set_nullifier_tree(nullifier_tree); + *self + } + + pub fn add_nullifier(&mut self, unsiloed_nullifier: Field) { + self.previous_kernel.add_nullifier(unsiloed_nullifier); + self.set_nullifiers_for_non_existent_read_request_hints(); } pub fn append_nullifiers(&mut self, num_nullifiers: u64) { self.previous_kernel.append_new_nullifiers_from_public(num_nullifiers); + self.set_nullifiers_for_non_existent_read_request_hints(); } pub fn append_nullifiers_non_revertible(&mut self, num_nullifiers: u64) { self.previous_kernel.append_new_nullifiers_non_revertible_from_public(num_nullifiers); + self.set_nullifiers_for_non_existent_read_request_hints(); + } + + fn set_nullifiers_for_non_existent_read_request_hints(&mut self) { + let previous_kernel_public_inputs = self.previous_kernel.to_public_kernel_data().public_inputs; + let nullifiers = array_concat( + previous_kernel_public_inputs.end_non_revertible.new_nullifiers, + previous_kernel_public_inputs.end.new_nullifiers + ); + self.nullifier_non_existent_read_request_hints_builder.set_nullifiers(nullifiers); } pub fn add_nullifier_pending_read(&mut self, nullifier_index: u64) { let read_request_index = self.previous_kernel.add_read_request_for_pending_nullifier(nullifier_index); - let hint_index = self.nullifier_read_request_reset_hints_builder.pending_read_hints.len(); + let hint_index = self.nullifier_read_request_hints_builder.pending_read_hints.len(); let pending_value_index = nullifier_index + self.previous_kernel.end_non_revertible.new_nullifiers.len(); let hint = PendingReadHint { read_request_index, pending_value_index }; - self.nullifier_read_request_reset_hints_builder.pending_read_hints.push(hint); - self.nullifier_read_request_reset_hints_builder.read_request_statuses[read_request_index] = ReadRequestStatus { state: ReadRequestState.PENDING, hint_index }; + self.nullifier_read_request_hints_builder.pending_read_hints.push(hint); + self.nullifier_read_request_hints_builder.read_request_statuses[read_request_index] = ReadRequestStatus { state: ReadRequestState.PENDING, hint_index }; } pub fn add_nullifier_pending_read_non_revertible(&mut self, nullifier_index_offset_one: u64) { let nullifier_index = nullifier_index_offset_one + 1; // + 1 is for the first nullifier let read_request_index = self.previous_kernel.add_read_request_for_pending_nullifier_non_revertible(nullifier_index); - let hint_index = self.nullifier_read_request_reset_hints_builder.pending_read_hints.len(); + let hint_index = self.nullifier_read_request_hints_builder.pending_read_hints.len(); let hint = PendingReadHint { read_request_index, pending_value_index: nullifier_index }; - self.nullifier_read_request_reset_hints_builder.pending_read_hints.push(hint); - self.nullifier_read_request_reset_hints_builder.read_request_statuses[read_request_index] = ReadRequestStatus { state: ReadRequestState.PENDING, hint_index }; + self.nullifier_read_request_hints_builder.pending_read_hints.push(hint); + self.nullifier_read_request_hints_builder.read_request_statuses[read_request_index] = ReadRequestStatus { state: ReadRequestState.PENDING, hint_index }; + } + + pub fn read_non_existent_nullifier(&mut self, unsiloed_nullifier: Field) { + self.previous_kernel.add_non_existent_read_request_for_nullifier(unsiloed_nullifier); + let siloed_nullifier = silo_nullifier( + self.previous_kernel.storage_contract_address, + unsiloed_nullifier + ); + self.nullifier_non_existent_read_request_hints_builder.add_value_read(siloed_nullifier); } pub fn execute(&mut self) -> PublicKernelCircuitPublicInputs { @@ -138,7 +239,8 @@ mod tests { let kernel = PublicKernelTailCircuitPrivateInputs { previous_kernel, - nullifier_read_request_reset_hints: self.nullifier_read_request_reset_hints_builder.to_hints() + nullifier_read_request_hints: self.nullifier_read_request_hints_builder.to_hints(), + nullifier_non_existent_read_request_hints: self.nullifier_non_existent_read_request_hints_builder.to_hints() }; kernel.public_kernel_tail() @@ -154,9 +256,10 @@ mod tests { } #[test] - fn public_kernel_circuit_tail_succeeds() { + unconstrained fn public_kernel_circuit_tail_succeeds() { let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); builder.succeeded(); + // TODO: Check the values in public inputs. } #[test] @@ -194,9 +297,9 @@ mod tests { builder.append_nullifiers(3); builder.add_nullifier_pending_read(1); - let mut hint = builder.nullifier_read_request_reset_hints_builder.pending_read_hints.pop(); + let mut hint = builder.nullifier_read_request_hints_builder.pending_read_hints.pop(); hint.pending_value_index -= 1; - builder.nullifier_read_request_reset_hints_builder.pending_read_hints.push(hint); + builder.nullifier_read_request_hints_builder.pending_read_hints.push(hint); builder.failed(); } @@ -214,4 +317,32 @@ mod tests { builder.failed(); } + + // TODO: Add tests for reading (non-existent) settled values. + + #[test] + unconstrained fn nullifier_non_existent_read_request() { + let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new().with_nullifier_tree(); + + builder.add_nullifier(3); + builder.add_nullifier(1); + builder.add_nullifier(9); + + builder.read_non_existent_nullifier(8); + + builder.succeeded(); + } + + #[test(should_fail_with="Value exists in pending set")] + unconstrained fn nullifier_non_existent_read_request_failed_read_exist() { + let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new().with_nullifier_tree(); + + builder.add_nullifier(3); + builder.add_nullifier(1); + builder.add_nullifier(9); + + builder.read_non_existent_nullifier(1); + + builder.succeeded(); + } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr index ae6af32e33f..efa4111dcdf 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr @@ -66,16 +66,14 @@ mod tests { use crate::{ public_kernel_teardown::PublicKernelTeardownCircuitPrivateInputs, utils::{ - assert_eq_call_requests, assert_eq_new_contracts, assert_eq_public_data_reads, - assert_eq_public_data_update_requests, compute_public_data_reads, - compute_public_data_update_requests + assert_eq_call_requests, assert_eq_public_data_reads, assert_eq_public_data_update_requests, + compute_public_data_reads, compute_public_data_update_requests } }; use dep::types::{ abis::{ call_request::CallRequest, function_selector::FunctionSelector, - kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, - new_contract_data::NewContractData, public_data_read::PublicDataRead, + kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest }, address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/utils.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/utils.nr index 7c3fe79a05a..2cbdf5c485d 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/utils.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/utils.nr @@ -1,7 +1,7 @@ use crate::hash::{compute_public_data_tree_index, compute_public_data_tree_value}; use dep::types::{ abis::{ - call_request::CallRequest, new_contract_data::NewContractData, public_data_read::PublicDataRead, + call_request::CallRequest, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest }, address::AztecAddress, @@ -60,10 +60,3 @@ pub fn assert_eq_public_data_update_requests( ) { assert(array_eq(public_data_update_requests, expected)); } - -pub fn assert_eq_new_contracts( - new_contracts: [NewContractData; N], - expected: [NewContractData; S] -) { - assert(array_eq(new_contracts, expected)); -} diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/lib.nr index 8e41dc16d8d..07a22b9eb44 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/lib.nr @@ -1,6 +1,10 @@ +use non_existent_read_request_reset::reset_non_existent_read_requests; +use nullifier_non_existent_read_request_reset::NullifierNonExistentReadRequestHints; +use nullifier_read_request_reset::NullifierReadRequestHints; use read_request_reset::reset_read_requests; -use nullifier_read_request_reset::NullifierReadRequestResetHints; -use nullifier_read_request_reset::NullifierReadRequestResetHintsBuilder; -mod read_request_reset; +mod non_existent_read_request_reset; +mod nullifier_non_existent_read_request_reset; mod nullifier_read_request_reset; +mod read_request_reset; +mod tests; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/non_existent_read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/non_existent_read_request_reset.nr new file mode 100644 index 00000000000..4beeee665ae --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/non_existent_read_request_reset.nr @@ -0,0 +1,354 @@ +use dep::types::{ + abis::{side_effect::OrderedValue, read_request::ReadRequestContext}, + merkle_tree::{assert_check_non_membership, IndexedTreeLeafPreimage, MembershipWitness}, + traits::{Empty, is_empty} +}; + +trait NonMembershipHint where LEAF_PREIMAGE: IndexedTreeLeafPreimage { + fn low_leaf_preimage(self) -> LEAF_PREIMAGE; + fn membership_witness(self) -> MembershipWitness; +} + +fn check_no_matching_pending_value( + read_request: ReadRequestContext, + sorted_pending_values: BoundedVec, + next_value_index: u64 +) -> bool where T: OrderedValue { + if next_value_index == sorted_pending_values.len() { + let highest_value = sorted_pending_values.get_unchecked(sorted_pending_values.len() - 1).value(); + highest_value.lt(read_request.value) + } else { + let next_value = sorted_pending_values.get_unchecked(next_value_index).value(); + let is_less_than_next = read_request.value.lt(next_value); + let is_greater_than_prev = if next_value_index == 0 { + true + } else { + let prev_value = sorted_pending_values.get_unchecked(next_value_index - 1).value(); + prev_value.lt(read_request.value) + }; + is_less_than_next & is_greater_than_prev + } +} + +fn check_is_read_before_pending_value( + read_request: ReadRequestContext, + sorted_pending_values: BoundedVec, + next_value_index: u64 +) -> bool where T: OrderedValue { + if next_value_index == sorted_pending_values.len() { + false + } else { + let pending = sorted_pending_values.get_unchecked(next_value_index); + if pending.value() == read_request.value { + assert(read_request.counter < pending.counter(), "Value exists in pending set"); + true + } else { + false + } + } +} + +// Unlike regular read requests, which can be reset at any time between two function executions. +// Non existent read requests can only be verified at the end, after all pending values are present. +// The values in read_requests and in sorted_pending_values should've been siloed before calling this. +pub fn reset_non_existent_read_requests( + siloed_read_requests: [ReadRequestContext; N], + non_membership_hints: [NON_MEMBERSHIP_HINT; N], + tree_root: Field, + sorted_pending_values: BoundedVec, + next_pending_value_indices: [u64; N] +) where + T: OrderedValue, + NON_MEMBERSHIP_HINT: NonMembershipHint, + LEAF_PREIMAGE: IndexedTreeLeafPreimage { + for i in 0..siloed_read_requests.len() { + let read_request = siloed_read_requests[i]; + if !is_empty(read_request) { + // Verify that it's not in the tree. + let hint = non_membership_hints[i]; + assert_check_non_membership( + read_request.value, + hint.low_leaf_preimage(), + hint.membership_witness(), + tree_root + ); + + // Verify that its value is either not in the pending set, or is created after the read. + let next_value_index = next_pending_value_indices[i]; + assert( + next_value_index <= sorted_pending_values.len(), "Next pending value index out of bounds" + ); + let no_matching_value = check_no_matching_pending_value(read_request, sorted_pending_values, next_value_index); + let is_read_before_value = check_is_read_before_pending_value(read_request, sorted_pending_values, next_value_index); + assert(no_matching_value | is_read_before_value, "Invalid next pending value index"); + } + } +} + +mod tests { + use crate::non_existent_read_request_reset::{NonMembershipHint, reset_non_existent_read_requests}; + + use dep::types::{ + address::AztecAddress, abis::{read_request::ReadRequestContext, side_effect::SideEffect}, + merkle_tree::{leaf_preimage::IndexedTreeLeafPreimage, membership::MembershipWitness}, + hash::silo_nullifier, tests::merkle_tree_utils::NonEmptyMerkleTree + }; + + struct TestLeafPreimage { + value: Field, + next_value: Field, + } + + impl IndexedTreeLeafPreimage for TestLeafPreimage { + fn get_key(self) -> Field { + self.value + } + + fn get_next_key(self) -> Field { + self.next_value + } + + fn as_leaf(self) -> Field { + self.value * 100 + } + } + + struct TestNonMembershipHint { + low_leaf_preimage: TestLeafPreimage, + membership_witness: MembershipWitness<3>, + } + + impl NonMembershipHint<3, TestLeafPreimage> for TestNonMembershipHint { + fn low_leaf_preimage(self) -> TestLeafPreimage { + self.low_leaf_preimage + } + + fn membership_witness(self) -> MembershipWitness<3> { + self.membership_witness + } + } + + global sorted_pending_values = BoundedVec { + storage: [ + SideEffect { value: 5, counter: 17 }, + SideEffect { value: 15, counter: 8 }, + SideEffect { value: 25, counter: 11 }, + SideEffect::empty(), + SideEffect::empty(), + ], + len: 3, + }; + + global leaf_preimages = [ + TestLeafPreimage { value: 0, next_value: 10 }, + TestLeafPreimage { value: 20, next_value: 30 }, + TestLeafPreimage { value: 30, next_value: 0 }, + TestLeafPreimage { value: 10, next_value: 20 }, + ]; + + fn build_tree() -> NonEmptyMerkleTree<4, 3, 1, 2> { + NonEmptyMerkleTree::new( + leaf_preimages.map(|leaf_preimage: TestLeafPreimage| leaf_preimage.as_leaf()), + [0; 3], + [0; 1], + [0; 2] + ) + } + + fn get_non_membership_hints(leaf_indices: [Field; N]) -> ([TestNonMembershipHint; N], Field) { + let tree = build_tree(); + let hints = leaf_indices.map( + |leaf_index| TestNonMembershipHint { + low_leaf_preimage: leaf_preimages[leaf_index], + membership_witness: MembershipWitness { leaf_index, sibling_path: tree.get_sibling_path(leaf_index as u64) } + } + ); + let tree_root = tree.get_root(); + (hints, tree_root) + } + + #[test] + fn test_reset_non_existent_read_requests_in_range() { + let read_requests = [ + ReadRequestContext { value: 11, counter: 50, contract_address: AztecAddress::zero() }, + ReadRequestContext { value: 22, counter: 51, contract_address: AztecAddress::zero() }, + ReadRequestContext { value: 6, counter: 52, contract_address: AztecAddress::zero() } + ]; + let (non_membership_hints, root) = get_non_membership_hints([3, 1, 0]); + let next_pending_value_indices = [1, 2, 1]; + reset_non_existent_read_requests( + read_requests, + non_membership_hints, + root, + sorted_pending_values, + next_pending_value_indices + ); + } + + #[test] + fn test_reset_non_existent_read_requests_less_than_min() { + let read_requests = [ + ReadRequestContext { value: 3, counter: 50, contract_address: AztecAddress::zero() }, + ReadRequestContext { value: 2, counter: 51, contract_address: AztecAddress::zero() } + ]; + let (non_membership_hints, root) = get_non_membership_hints([0, 0]); + let next_pending_value_indices = [0, 0]; + reset_non_existent_read_requests( + read_requests, + non_membership_hints, + root, + sorted_pending_values, + next_pending_value_indices + ); + } + + #[test] + fn test_reset_non_existent_read_requests_greater_than_max() { + let read_requests = [ + ReadRequestContext { value: 35, counter: 50, contract_address: AztecAddress::zero() }, + ReadRequestContext { value: 31, counter: 51, contract_address: AztecAddress::zero() } + ]; + let (non_membership_hints, root) = get_non_membership_hints([2, 2]); + let next_pending_value_indices = [3, 3]; + reset_non_existent_read_requests( + read_requests, + non_membership_hints, + root, + sorted_pending_values, + next_pending_value_indices + ); + } + + #[test] + fn test_reset_non_existent_read_requests_read_before_pending_emitted() { + let read_requests = [ + ReadRequestContext { value: 25, counter: 10, contract_address: AztecAddress::zero() }, + ReadRequestContext { value: 5, counter: 11, contract_address: AztecAddress::zero() } + ]; + let (non_membership_hints, root) = get_non_membership_hints([1, 0]); + let next_pending_value_indices = [2, 0]; + reset_non_existent_read_requests( + read_requests, + non_membership_hints, + root, + sorted_pending_values, + next_pending_value_indices + ); + } + + #[test(should_fail_with="Cannot check non membership against empty leaf")] + fn test_reset_non_existent_read_requests_empty_leaf_failed() { + let read_requests = [ReadRequestContext { value: 10, counter: 50, contract_address: AztecAddress::zero() }]; + let (non_membership_hints, root) = get_non_membership_hints([0]); + let mut hint = non_membership_hints[0]; + hint.low_leaf_preimage = TestLeafPreimage { value: 0, next_value: 0 }; + let next_pending_value_indices = [1]; + reset_non_existent_read_requests( + read_requests, + [hint], + root, + sorted_pending_values, + next_pending_value_indices + ); + } + + #[test(should_fail_with="Low leaf does not exist")] + fn test_reset_non_existent_read_requests_invalid_preimage_failed() { + let read_requests = [ReadRequestContext { value: 10, counter: 50, contract_address: AztecAddress::zero() }]; + let (non_membership_hints, root) = get_non_membership_hints([3]); + let mut hint = non_membership_hints[0]; + hint.low_leaf_preimage = TestLeafPreimage { value: 9, next_value: 20 }; + let next_pending_value_indices = [1]; + reset_non_existent_read_requests( + read_requests, + [hint], + root, + sorted_pending_values, + next_pending_value_indices + ); + } + + #[test(should_fail_with="Key is not greater than the low leaf")] + fn test_reset_non_existent_read_requests_read_settled_failed() { + let read_requests = [ReadRequestContext { value: 10, counter: 50, contract_address: AztecAddress::zero() }]; + let (non_membership_hints, root) = get_non_membership_hints([3]); + let next_pending_value_indices = [1]; + reset_non_existent_read_requests( + read_requests, + non_membership_hints, + root, + sorted_pending_values, + next_pending_value_indices + ); + } + + #[test(should_fail_with="Key is not less than the next leaf")] + fn test_reset_non_existent_read_requests_invalid_non_membership_hint_failed() { + let read_requests = [ReadRequestContext { value: 10, counter: 50, contract_address: AztecAddress::zero() }]; + let (non_membership_hints, root) = get_non_membership_hints([0]); + let next_pending_value_indices = [1]; + reset_non_existent_read_requests( + read_requests, + non_membership_hints, + root, + sorted_pending_values, + next_pending_value_indices + ); + } + + #[test(should_fail_with="Value exists in pending set")] + fn test_reset_non_existent_read_requests_read_pending_value_failed() { + let read_requests = [ReadRequestContext { value: 25, counter: 50, contract_address: AztecAddress::zero() }]; + let (non_membership_hints, root) = get_non_membership_hints([1]); + let next_pending_value_indices = [2]; + reset_non_existent_read_requests( + read_requests, + non_membership_hints, + root, + sorted_pending_values, + next_pending_value_indices + ); + } + + #[test(should_fail_with="Invalid next pending value index")] + fn test_reset_non_existent_read_requests_wrong_next_pending_index_failed() { + let read_requests = [ReadRequestContext { value: 21, counter: 50, contract_address: AztecAddress::zero() }]; + let (non_membership_hints, root) = get_non_membership_hints([1]); + let next_pending_value_indices = [1]; + reset_non_existent_read_requests( + read_requests, + non_membership_hints, + root, + sorted_pending_values, + next_pending_value_indices + ); + } + + #[test(should_fail_with="Invalid next pending value index")] + fn test_reset_non_existent_read_requests_wrong_max_next_pending_index_failed() { + let read_requests = [ReadRequestContext { value: 21, counter: 50, contract_address: AztecAddress::zero() }]; + let (non_membership_hints, root) = get_non_membership_hints([1]); + let next_pending_value_indices = [3]; + reset_non_existent_read_requests( + read_requests, + non_membership_hints, + root, + sorted_pending_values, + next_pending_value_indices + ); + } + + #[test(should_fail_with="Next pending value index out of bounds")] + fn test_reset_non_existent_read_requests_overflown_index_failed() { + let read_requests = [ReadRequestContext { value: 21, counter: 50, contract_address: AztecAddress::zero() }]; + let (non_membership_hints, root) = get_non_membership_hints([1]); + let next_pending_value_indices = [4]; + reset_non_existent_read_requests( + read_requests, + non_membership_hints, + root, + sorted_pending_values, + next_pending_value_indices + ); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_non_existent_read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_non_existent_read_request_reset.nr new file mode 100644 index 00000000000..cc76145b18e --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_non_existent_read_request_reset.nr @@ -0,0 +1,28 @@ +use crate::non_existent_read_request_reset::{NonMembershipHint}; +use dep::types::{ + abis::{nullifier_leaf_preimage::NullifierLeafPreimage, side_effect::SideEffectLinkedToNoteHash}, + merkle_tree::{MembershipWitness}, + constants::{MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT} +}; + +struct NullifierNonMembershipHint { + low_leaf_preimage: NullifierLeafPreimage, + membership_witness: MembershipWitness, +} + +impl NonMembershipHint for NullifierNonMembershipHint { + fn low_leaf_preimage(self) -> NullifierLeafPreimage { + self.low_leaf_preimage + } + + fn membership_witness(self) -> MembershipWitness { + self.membership_witness + } +} + +struct NullifierNonExistentReadRequestHints { + non_membership_hints: [NullifierNonMembershipHint; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX], + sorted_pending_values: [SideEffectLinkedToNoteHash; MAX_NEW_NULLIFIERS_PER_TX], + sorted_pending_value_index_hints: [u64; MAX_NEW_NULLIFIERS_PER_TX], + next_pending_value_indices: [u64; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX], +} diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr index 6524089d74a..6a122e57a2d 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr @@ -2,8 +2,9 @@ use crate::read_request_reset::{PendingReadHint, ReadRequestStatus, ReadValueHint, SettledReadHint}; use dep::std::unsafe; use dep::types::{ - abis::{membership_witness::MembershipWitness, nullifier_leaf_preimage::NullifierLeafPreimage}, - constants::{MAX_NULLIFIER_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT} + abis::{nullifier_leaf_preimage::NullifierLeafPreimage}, + constants::{MAX_NULLIFIER_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT}, + merkle_tree::MembershipWitness }; struct NullifierSettledReadHint { @@ -36,49 +37,22 @@ impl SettledReadHint for Nullifier } } -struct NullifierReadRequestResetHints { +struct NullifierReadRequestHints { read_request_statuses: [ReadRequestStatus; MAX_NULLIFIER_READ_REQUESTS_PER_TX], pending_read_hints: [PendingReadHint; MAX_NULLIFIER_READ_REQUESTS_PER_TX], settled_read_hints: [NullifierSettledReadHint; MAX_NULLIFIER_READ_REQUESTS_PER_TX], } -struct NullifierReadRequestResetHintsBuilder { - read_request_statuses: [ReadRequestStatus; MAX_NULLIFIER_READ_REQUESTS_PER_TX], - pending_read_hints: BoundedVec, - settled_read_hints: BoundedVec, -} - -impl NullifierReadRequestResetHintsBuilder { - pub fn new(read_request_len: u64) -> Self { - NullifierReadRequestResetHintsBuilder { - read_request_statuses: [ReadRequestStatus::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_TX], - pending_read_hints: BoundedVec { storage: [PendingReadHint::nada(read_request_len); MAX_NULLIFIER_READ_REQUESTS_PER_TX], len: 0 }, - settled_read_hints: BoundedVec { - storage: [NullifierSettledReadHint::nada(read_request_len); MAX_NULLIFIER_READ_REQUESTS_PER_TX], - len: 0 - } - } - } - - pub fn to_hints(self) -> NullifierReadRequestResetHints { - NullifierReadRequestResetHints { - read_request_statuses: self.read_request_statuses, - pending_read_hints: self.pending_read_hints.storage, - settled_read_hints: self.settled_read_hints.storage - } - } -} - mod tests { use crate::nullifier_read_request_reset::NullifierSettledReadHint; use crate::read_request_reset::{PendingReadHint, ReadRequestState, ReadRequestStatus, reset_read_requests}; use dep::types::{ address::AztecAddress, abis::{ - membership_witness::MembershipWitness, nullifier_leaf_preimage::NullifierLeafPreimage, - read_request::ReadRequestContext, side_effect::SideEffect + nullifier_leaf_preimage::NullifierLeafPreimage, read_request::ReadRequestContext, + side_effect::SideEffect }, - constants::NULLIFIER_TREE_HEIGHT, hash::silo_nullifier, + constants::NULLIFIER_TREE_HEIGHT, hash::silo_nullifier, merkle_tree::MembershipWitness, tests::merkle_tree_utils::NonEmptyMerkleTree }; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/read_request_reset.nr index 2c50bcd46d7..1432df9ef18 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/read_request_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/read_request_reset.nr @@ -1,8 +1,7 @@ // This will be moved to a separate Read Request Reset Circuit. use dep::types::{ - abis::{membership_witness::MembershipWitness, read_request::ReadRequestContext, side_effect::OrderedValue}, - hash::{silo_nullifier, root_from_sibling_path}, merkle_tree::leaf_preimage::LeafPreimage, - traits::{Empty, is_empty} + abis::{read_request::ReadRequestContext, side_effect::OrderedValue}, hash::{silo_nullifier}, + merkle_tree::{assert_check_membership, LeafPreimage, MembershipWitness}, traits::{Empty, is_empty} }; struct ReadRequestStateEnum { @@ -84,7 +83,7 @@ fn validate_pending_read_requests( read_requests: [ReadRequestContext; READ_REQUEST_LEN], hints: [H; NUM_SETTLED_READS], - historical_tree_root: Field + tree_root: Field ) where H: SettledReadHint + ReadValueHint, LEAF_PREIMAGE: LeafPreimage { @@ -99,8 +98,7 @@ fn validate_settled_read_requests BoundedVec where P: OrderedValue, H: SettledReadHint + ReadValueHint, LEAF_PREIMAGE: LeafPreimage { validate_pending_read_requests(read_requests, pending_values, pending_read_hints); - validate_settled_read_requests(read_requests, settled_read_hints, historical_tree_root); + validate_settled_read_requests(read_requests, settled_read_hints, tree_root); propagate_unverified_read_requests( read_requests, @@ -163,9 +161,8 @@ mod tests { }; use dep::std::{hash::pedersen_hash, unsafe}; use dep::types::{ - address::AztecAddress, - abis::{membership_witness::MembershipWitness, read_request::ReadRequestContext, side_effect::SideEffect}, - merkle_tree::leaf_preimage::LeafPreimage, hash::silo_nullifier, + address::AztecAddress, abis::{read_request::ReadRequestContext, side_effect::SideEffect}, + merkle_tree::{LeafPreimage, MembershipWitness}, hash::silo_nullifier, tests::merkle_tree_utils::NonEmptyMerkleTree }; @@ -309,7 +306,7 @@ mod tests { validate_settled_read_requests(read_requests, hints, tree_root); } - #[test(should_fail_with="Tree root mismatch for read request")] + #[test(should_fail_with="membership check failed")] fn test_validate_settled_read_requests_wrong_witness_fails() { let (settled_hints, tree_root) = get_settled_read_hints(); let mut hint = settled_hints[0]; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests.nr new file mode 100644 index 00000000000..9ecd400c180 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests.nr @@ -0,0 +1,2 @@ +mod nullifier_non_existent_read_request_hints_builder; +mod nullifier_read_request_hints_builder; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_non_existent_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_non_existent_read_request_hints_builder.nr new file mode 100644 index 00000000000..d4de21463a7 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_non_existent_read_request_hints_builder.nr @@ -0,0 +1,80 @@ +use crate::nullifier_non_existent_read_request_reset::{NullifierNonMembershipHint, NullifierNonExistentReadRequestHints}; +use dep::types::{ + abis::{nullifier_leaf_preimage::NullifierLeafPreimage, side_effect::SideEffectLinkedToNoteHash}, + constants::{ + MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT, + NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_HEIGHT +}, + merkle_tree::MembershipWitness, + tests::{merkle_tree_utils::NonEmptyMerkleTree, sort::sort_get_sorted_hints}, + utils::{arrays::find_index, field::full_field_greater_than} +}; +use dep::std::unsafe; + +struct NullifierNonExistentReadRequestHintsBuilder { + nullifier_tree: NonEmptyMerkleTree, + non_membership_hints: BoundedVec, + read_values: BoundedVec, + pending_nullifiers: [SideEffectLinkedToNoteHash; MAX_NEW_NULLIFIERS_PER_TX], +} + +impl NullifierNonExistentReadRequestHintsBuilder { + pub fn new() -> Self { + NullifierNonExistentReadRequestHintsBuilder { + nullifier_tree: unsafe::zeroed(), + non_membership_hints: BoundedVec::new(), + read_values: BoundedVec::new(), + pending_nullifiers: [SideEffectLinkedToNoteHash::empty(); MAX_NEW_NULLIFIERS_PER_TX] + } + } + + pub fn set_nullifier_tree( + &mut self, + tree: NonEmptyMerkleTree + ) { + self.nullifier_tree = tree; + } + + pub fn set_nullifiers( + &mut self, + nullifiers: [SideEffectLinkedToNoteHash; MAX_NEW_NULLIFIERS_PER_TX] + ) { + self.pending_nullifiers = nullifiers; + } + + pub fn add_value_read(&mut self, siloed_value: Field) { + self.read_values.push(siloed_value); + + // There are only two pre-existing nullifiers in the tree: [0, 100], generated in public_kernel_tail::tests. + // Assuming the siloed_value is always greater than 100. + let hint = NullifierNonMembershipHint { + low_leaf_preimage: NullifierLeafPreimage { nullifier: 100, next_nullifier: 0, next_index: 0 }, + membership_witness: MembershipWitness { leaf_index: 1, sibling_path: self.nullifier_tree.get_sibling_path(1) } + }; + self.non_membership_hints.push(hint); + } + + pub fn to_hints(self) -> NullifierNonExistentReadRequestHints { + let sorted_result = sort_get_sorted_hints( + self.pending_nullifiers, + |a: SideEffectLinkedToNoteHash, b: SideEffectLinkedToNoteHash| a.value.lt(b.value) + ); + let sorted_pending_values = sorted_result.sorted_array; + let sorted_pending_value_index_hints = sorted_result.sorted_index_hints; + + let mut next_pending_value_indices = [0; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX]; + for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX { + if i < self.read_values.len() { + let value = self.read_values.get_unchecked(i); + next_pending_value_indices[i] = find_index(sorted_pending_values, |v: SideEffectLinkedToNoteHash| !v.value.lt(value)); + } + } + + NullifierNonExistentReadRequestHints { + non_membership_hints: self.non_membership_hints.storage, + sorted_pending_values, + sorted_pending_value_index_hints, + next_pending_value_indices + } + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr new file mode 100644 index 00000000000..355106e7978 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr @@ -0,0 +1,32 @@ +use crate::{ + nullifier_read_request_reset::{NullifierSettledReadHint, NullifierReadRequestHints}, + read_request_reset::{PendingReadHint, ReadRequestStatus} +}; +use dep::types::constants::MAX_NULLIFIER_READ_REQUESTS_PER_TX; + +struct NullifierReadRequestHintsBuilder { + read_request_statuses: [ReadRequestStatus; MAX_NULLIFIER_READ_REQUESTS_PER_TX], + pending_read_hints: BoundedVec, + settled_read_hints: BoundedVec, +} + +impl NullifierReadRequestHintsBuilder { + pub fn new(read_request_len: u64) -> Self { + NullifierReadRequestHintsBuilder { + read_request_statuses: [ReadRequestStatus::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_TX], + pending_read_hints: BoundedVec { storage: [PendingReadHint::nada(read_request_len); MAX_NULLIFIER_READ_REQUESTS_PER_TX], len: 0 }, + settled_read_hints: BoundedVec { + storage: [NullifierSettledReadHint::nada(read_request_len); MAX_NULLIFIER_READ_REQUESTS_PER_TX], + len: 0 + } + } + } + + pub fn to_hints(self) -> NullifierReadRequestHints { + NullifierReadRequestHints { + read_request_statuses: self.read_request_statuses, + pending_read_hints: self.pending_read_hints.storage, + settled_read_hints: self.settled_read_hints.storage + } + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr index 9b5f2037b1f..b06afdce361 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr @@ -9,18 +9,14 @@ use crate::{ use dep::types::{ abis::{ append_only_tree_snapshot::AppendOnlyTreeSnapshot, - membership_witness::{ - ArchiveRootMembershipWitness, MembershipWitness, NullifierMembershipWitness, - PublicDataMembershipWitness -}, + membership_witness::{ArchiveRootMembershipWitness, NullifierMembershipWitness, PublicDataMembershipWitness}, nullifier_leaf_preimage::NullifierLeafPreimage, public_data_update_request::PublicDataUpdateRequest, public_data_read::PublicDataRead, kernel_data::RollupKernelData, side_effect::{SideEffect, SideEffectLinkedToNoteHash}, accumulated_data::CombinedAccumulatedData }, constants::{ NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, - CONTRACT_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_TREE_HEIGHT, MAX_NEW_CONTRACTS_PER_TX, - NOTE_HASH_SUBTREE_HEIGHT, CONTRACT_SUBTREE_HEIGHT, NUM_FIELDS_PER_SHA256, + PUBLIC_DATA_TREE_HEIGHT, NOTE_HASH_SUBTREE_HEIGHT, NUM_FIELDS_PER_SHA256, MAX_NEW_NOTE_HASHES_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, NUM_ENCRYPTED_LOGS_HASHES_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, NUM_UNENCRYPTED_LOGS_HASHES_PER_TX, NULLIFIER_SUBTREE_HEIGHT, NULLIFIER_TREE_HEIGHT, @@ -30,8 +26,10 @@ use dep::types::{ MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX, MAX_REVERTIBLE_NULLIFIERS_PER_TX, MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX }, - hash::assert_check_membership, - merkle_tree::{append_only_tree, calculate_empty_tree_root, calculate_subtree, indexed_tree}, + merkle_tree::{ + append_only_tree, assert_check_membership, calculate_empty_tree_root, calculate_subtree_root, + indexed_tree, MembershipWitness +}, mocked::{AggregationObject, Proof}, partial_state_reference::PartialStateReference, public_data_tree_leaf::PublicDataTreeLeaf, public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, @@ -73,11 +71,6 @@ impl BaseRollupInputs { == self.constants.global_variables.version, "kernel version does not match the rollup version" ); - // First we compute the contract tree leaves - let contract_leaves = self.calculate_contract_leaves(); - - let contracts_tree_subroot = self.calculate_contract_subtree_root(contract_leaves); - let commitments_tree_subroot = self.calculate_commitments_subtree(); let empty_commitments_subtree_root = calculate_empty_tree_root(NOTE_HASH_SUBTREE_HEIGHT); @@ -90,16 +83,6 @@ impl BaseRollupInputs { NOTE_HASH_SUBTREE_HEIGHT as u8 ); - // Insert contract subtrees: - let empty_contracts_subtree_root = calculate_empty_tree_root(CONTRACT_SUBTREE_HEIGHT); - let end_contract_tree_snapshot = append_only_tree::insert_subtree_to_snapshot_tree( - self.start.contract_tree, - self.state_diff_hints.contract_subtree_sibling_path, - empty_contracts_subtree_root, - contracts_tree_subroot, - CONTRACT_SUBTREE_HEIGHT as u8 - ); - // Insert nullifiers: let end_nullifier_tree_snapshot = self.check_nullifier_tree_non_membership_and_insert_to_tree(); @@ -124,7 +107,6 @@ impl BaseRollupInputs { end: PartialStateReference { note_hash_tree: end_note_hash_tree_snapshot, nullifier_tree: end_nullifier_tree_snapshot, - contract_tree: end_contract_tree_snapshot, public_data_tree: end_public_data_tree_snapshot }, txs_effects_hash: tx_effects_hash, @@ -132,39 +114,10 @@ impl BaseRollupInputs { } } - fn calculate_contract_leaves(self) -> [Field; MAX_NEW_CONTRACTS_PER_TX] { - let mut contract_leaves = [0; MAX_NEW_CONTRACTS_PER_TX]; - let new_contracts = self.kernel_data.public_inputs.end.new_contracts; - - // loop over the new contracts - for i in 0..new_contracts.len() { - let leaf_preimage = new_contracts[i]; - // When there is no contract deployment, we should insert a zero leaf into the tree and ignore the - // member-ship check. This is to ensure that we don't hit "already deployed" errors when we are not - // deploying contracts. e.g., when we are only calling functions on existing contracts. - let to_push = if leaf_preimage.contract_address.to_field() == 0 { - 0 - } else { - leaf_preimage.hash() - }; - contract_leaves[i] = to_push; - } - - contract_leaves - } - - // Cpp code says calculate_contract_subtree, so I'm leaving it as is for now - fn calculate_contract_subtree_root(self, leaves: [Field; MAX_NEW_CONTRACTS_PER_TX]) -> Field { - // Silence warning for unused self, pending proper fix. - let _ = self; - assert_eq(leaves.len(), 1); - leaves[0] - } - // TODO(Kev): This should say calculate_commitments_subtree_root // Cpp code says calculate_commitments_subtree, so I'm leaving it as is for now fn calculate_commitments_subtree(self) -> Field { - calculate_subtree(self.kernel_data.public_inputs.end.new_note_hashes.map(|c: SideEffect| c.value)) + calculate_subtree_root(self.kernel_data.public_inputs.end.new_note_hashes.map(|c: SideEffect| c.value)) } fn check_nullifier_tree_non_membership_and_insert_to_tree(self) -> AppendOnlyTreeSnapshot { @@ -183,9 +136,6 @@ impl BaseRollupInputs { } } ), - |a: Field, b: Field| {a == b}, // Nullifier equals - |nullifier: Field| {nullifier == 0}, // Nullifier is zero - |leaf: NullifierLeafPreimage| {leaf.hash()}, // Hash leaf |low_leaf: NullifierLeafPreimage, nullifier: Field| { // Is valid low leaf let is_less_than_nullifier = full_field_less_than(low_leaf.nullifier, nullifier); let is_next_greater_than = full_field_less_than(nullifier, low_leaf.next_nullifier); @@ -215,7 +165,7 @@ impl BaseRollupInputs { } fn create_nullifier_subtree(leaves: [NullifierLeafPreimage; N]) -> Field { - calculate_subtree(leaves.map(|leaf:NullifierLeafPreimage| leaf.hash())) + calculate_subtree_root(leaves.map(|leaf:NullifierLeafPreimage| leaf.hash())) } fn validate_and_process_public_state(self) -> AppendOnlyTreeSnapshot { @@ -311,9 +261,6 @@ fn insert_public_data_update_requests( } } ), - |a: PublicDataTreeLeaf, b: PublicDataTreeLeaf| a.eq(b), // PublicDataTreeLeaf equals - |write: PublicDataTreeLeaf| write.is_empty(), // PublicDataTreeLeaf is_empty - |preimage: PublicDataTreeLeafPreimage| preimage.hash(), // Hash preimage |low_preimage: PublicDataTreeLeafPreimage, write: PublicDataTreeLeaf| { // Is valid low preimage let is_update = low_preimage.slot == write.slot; let is_low_empty = low_preimage.is_empty(); @@ -437,28 +384,26 @@ mod tests { abis::{ append_only_tree_snapshot::AppendOnlyTreeSnapshot, membership_witness::{ArchiveRootMembershipWitness, NullifierMembershipWitness, PublicDataMembershipWitness}, - new_contract_data::NewContractData, nullifier_leaf_preimage::NullifierLeafPreimage, - public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, + nullifier_leaf_preimage::NullifierLeafPreimage, public_data_read::PublicDataRead, + public_data_update_request::PublicDataUpdateRequest, kernel_data::{PublicKernelData, RollupKernelData}, side_effect::SideEffect, accumulated_data::CombinedAccumulatedData }, address::{AztecAddress, EthAddress}, constants::{ - CONTRACT_SUBTREE_SIBLING_PATH_LENGTH, CONTRACT_TREE_HEIGHT, CONTRACT_SUBTREE_HEIGHT, ARCHIVE_HEIGHT, MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NEW_CONTRACTS_PER_TX, - NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NOTE_HASH_TREE_HEIGHT, NOTE_HASH_SUBTREE_HEIGHT, - NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, NULLIFIER_SUBTREE_HEIGHT, - PUBLIC_DATA_TREE_HEIGHT, PUBLIC_DATA_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, - NUM_FIELDS_PER_SHA256, MAX_NEW_L2_TO_L1_MSGS_PER_TX + MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, + NOTE_HASH_TREE_HEIGHT, NOTE_HASH_SUBTREE_HEIGHT, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, + NULLIFIER_TREE_HEIGHT, NULLIFIER_SUBTREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT, + PUBLIC_DATA_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, NUM_FIELDS_PER_SHA256, + MAX_NEW_L2_TO_L1_MSGS_PER_TX }, contract_class_id::ContractClassId, partial_state_reference::PartialStateReference, - hash::assert_check_membership, merkle_tree::{calculate_empty_tree_root, calculate_subtree}, public_data_tree_leaf::PublicDataTreeLeaf, public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, tests::{ kernel_data_builder::PreviousKernelDataBuilder, - merkle_tree_utils::{NonEmptyMerkleTree, compute_zero_hashes} + merkle_tree_utils::{NonEmptyMerkleTree, compute_zero_hashes}, sort::sort_high_to_low }, utils::{field::full_field_less_than, uint256::U256} }; @@ -468,28 +413,10 @@ mod tests { value: Field, } - struct SortedTuple { - value: T, - original_index: u64, - } - global MAX_NEW_NULLIFIERS_PER_TEST = 4; global MAX_PUBLIC_DATA_WRITES_PER_TEST = 2; global MAX_PUBLIC_DATA_READS_PER_TEST = 2; - fn sort_high_to_low(values: [T; N], is_less_than: fn(T, T) -> bool) -> [SortedTuple; N] where T: Eq { - let mut sorted_tuples = [SortedTuple { value: values[0], original_index: 0 }; N]; - - for i in 0..N { - sorted_tuples[i] = SortedTuple { - value: values[i], - original_index: i, - }; - } - - sorted_tuples.sort_via(|a: SortedTuple, b: SortedTuple| (b.value == a.value) | is_less_than(b.value, a.value)) - } - fn update_public_data_tree( public_data_tree: &mut NonEmptyMerkleTree, kernel_data: &mut RollupKernelData, @@ -702,21 +629,6 @@ mod tests { next_available_leaf_index: start_nullifier_tree.get_next_available_index() as u32 }; - let start_contract_tree = NonEmptyMerkleTree::new( - self.pre_existing_contracts, - [0; CONTRACT_TREE_HEIGHT], - [0; CONTRACT_TREE_HEIGHT - 1], - [0; 1] - ); - let start_contract_tree_snapshot = AppendOnlyTreeSnapshot { - root: start_contract_tree.get_root(), - next_available_leaf_index: start_contract_tree.get_next_available_index() as u32 - }; - let contract_subtree_sibling_path = BaseRollupInputsBuilder::extract_subtree_sibling_path( - start_contract_tree.get_sibling_path(self.pre_existing_contracts.len()), - [0; CONTRACT_SUBTREE_SIBLING_PATH_LENGTH] - ); - let mut start_public_data_tree = NonEmptyMerkleTree::new( self.pre_existing_public_data.map(|preimage: PublicDataTreeLeafPreimage| preimage.hash()), [0; PUBLIC_DATA_TREE_HEIGHT], @@ -775,7 +687,6 @@ mod tests { let start = PartialStateReference { note_hash_tree: start_note_hash_tree_snapshot, nullifier_tree: start_nullifier_tree_snapshot, - contract_tree: start_contract_tree_snapshot, public_data_tree: start_public_data_tree_snapshot }; @@ -786,7 +697,6 @@ mod tests { sorted_nullifier_indexes, note_hash_subtree_sibling_path, nullifier_subtree_sibling_path, - contract_subtree_sibling_path, public_data_sibling_path }; @@ -818,75 +728,6 @@ mod tests { } } - #[test] - unconstrained fn no_new_contract_leaves() { - let outputs = BaseRollupInputsBuilder::new().execute(); - let expected_start_contract_tree_snapshot = AppendOnlyTreeSnapshot { root: test_compute_empty_root([0; CONTRACT_TREE_HEIGHT]), next_available_leaf_index: 2 }; - let expected_end_contract_tree_snapshot = AppendOnlyTreeSnapshot { root: test_compute_empty_root([0; CONTRACT_TREE_HEIGHT]), next_available_leaf_index: 3 }; - assert(outputs.start.contract_tree.eq(expected_start_contract_tree_snapshot)); - assert(outputs.end.contract_tree.eq(expected_end_contract_tree_snapshot)); - } - - #[test] - unconstrained fn contract_leaf_inserted() { - let new_contract = NewContractData { - contract_address: AztecAddress::from_field(1), - portal_contract_address: EthAddress::from_field(2), - contract_class_id: ContractClassId::from_field(3) - }; - - let mut builder = BaseRollupInputsBuilder::new(); - let mut new_contracts = builder.kernel_data.end.new_contracts; - new_contracts.push(new_contract); - builder.kernel_data.end.new_contracts = new_contracts; - let mut expected_contracts_tree = NonEmptyMerkleTree::new( - [0; 4], - [0; CONTRACT_TREE_HEIGHT], - [0; CONTRACT_TREE_HEIGHT - 2], - [0; 2] - ); - - let outputs = builder.execute(); - - let expected_start_contract_tree_snapshot = AppendOnlyTreeSnapshot { root: expected_contracts_tree.get_root(), next_available_leaf_index: 2 }; - assert(outputs.start.contract_tree.eq(expected_start_contract_tree_snapshot)); - - expected_contracts_tree.update_leaf(2, new_contract.hash()); - let expected_end_contract_tree_snapshot = AppendOnlyTreeSnapshot { root: expected_contracts_tree.get_root(), next_available_leaf_index: 3 }; - assert(outputs.end.contract_tree.eq(expected_end_contract_tree_snapshot)); - } - - #[test] - unconstrained fn contract_leaf_inserted_in_non_empty_snapshot_tree() { - let new_contract = NewContractData { - contract_address: AztecAddress::from_field(1), - portal_contract_address: EthAddress::from_field(2), - contract_class_id: ContractClassId::from_field(3) - }; - - let mut builder = BaseRollupInputsBuilder::new(); - - builder.pre_existing_contracts = [1,2]; - let mut new_contracts = builder.kernel_data.end.new_contracts; - new_contracts.push(new_contract); - builder.kernel_data.end.new_contracts = new_contracts; - let mut expected_contracts_tree = NonEmptyMerkleTree::new( - [1, 2, 0, 0], - [0; CONTRACT_TREE_HEIGHT], - [0; CONTRACT_TREE_HEIGHT - 2], - [0; 2] - ); - - let outputs = builder.execute(); - - let expected_start_contract_tree_snapshot = AppendOnlyTreeSnapshot { root: expected_contracts_tree.get_root(), next_available_leaf_index: 2 }; - assert(outputs.start.contract_tree.eq(expected_start_contract_tree_snapshot)); - - expected_contracts_tree.update_leaf(2, new_contract.hash()); - let expected_end_contract_tree_snapshot = AppendOnlyTreeSnapshot { root: expected_contracts_tree.get_root(), next_available_leaf_index: 3 }; - assert(outputs.end.contract_tree.eq(expected_end_contract_tree_snapshot)); - } - #[test] unconstrained fn new_note_hashes_tree() { let mut builder = BaseRollupInputsBuilder::new(); diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr index a15bb81021f..9c7dd03d70d 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr @@ -2,8 +2,7 @@ use dep::types::{ abis::{membership_witness::NullifierMembershipWitness, nullifier_leaf_preimage::NullifierLeafPreimage}, constants::{ MAX_NEW_NULLIFIERS_PER_TX, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, - NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, CONTRACT_SUBTREE_SIBLING_PATH_LENGTH, - PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH + NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH } }; @@ -19,6 +18,5 @@ struct StateDiffHints { // snapshots of the relevant trees are stored in partial state reference). note_hash_subtree_sibling_path: [Field; NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH], nullifier_subtree_sibling_path: [Field; NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH], - contract_subtree_sibling_path: [Field; CONTRACT_SUBTREE_SIBLING_PATH_LENGTH], public_data_sibling_path: [Field; PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH], } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr index aeb3b556855..63f7aff2ce1 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr @@ -5,7 +5,7 @@ use dep::types::{ constants::{ NUM_FIELDS_PER_SHA256, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, NUM_UNENCRYPTED_LOGS_HASHES_PER_TX, NUM_ENCRYPTED_LOGS_HASHES_PER_TX, - MAX_NEW_CONTRACTS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX }, utils::uint256::U256, abis::{append_only_tree_snapshot::AppendOnlyTreeSnapshot, accumulated_data::CombinedAccumulatedData} @@ -74,9 +74,6 @@ pub fn assert_prev_rollups_follow_on_from_each_other( assert( left.end.nullifier_tree.eq(right.start.nullifier_tree), "input proofs have different nullifier tree snapshots" ); - assert( - left.end.contract_tree.eq(right.start.contract_tree), "input proofs have different contract tree snapshots" - ); assert( left.end.public_data_tree.eq(right.start.public_data_tree), "input proofs have different public data tree snapshots" ); @@ -131,9 +128,9 @@ pub fn compute_txs_effects_hash(previous_rollup_data: [PreviousRollupData; 2]) - ) } -global TX_EFFECTS_HASH_FULL_FIELDS = 197; +global TX_EFFECTS_HASH_FULL_FIELDS = 194; global TX_EFFECTS_HASH_LOG_FIELDS = 4; -global TX_EFFECTS_HASH_INPUT_FIELDS = 201; // TX_EFFECTS_HASH_FULL_FIELDS + TX_EFFECTS_HASH_LOG_FIELDS +global TX_EFFECTS_HASH_INPUT_FIELDS = 198; // TX_EFFECTS_HASH_FULL_FIELDS + TX_EFFECTS_HASH_LOG_FIELDS // Computes the tx effects hash for a base rollup (a single transaction) // TODO(Alvaro): This is too slow for brillig without the array optimization @@ -181,17 +178,6 @@ pub fn compute_tx_effects_hash(combined: CombinedAccumulatedData) -> [Field; NUM } offset += MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2; - let contract_leaf = combined.new_contracts[0]; - txs_effects_hash_input[offset] = contract_leaf.hash(); - - offset += MAX_NEW_CONTRACTS_PER_TX; - - let new_contracts = combined.new_contracts; - txs_effects_hash_input[offset] = new_contracts[0].contract_address.to_field(); - txs_effects_hash_input[offset + 1] = new_contracts[0].portal_contract_address.to_field(); - - offset += MAX_NEW_CONTRACTS_PER_TX * 2; - for j in 0..NUM_FIELDS_PER_SHA256 { txs_effects_hash_input[offset + j] = encryptedLogsHash[j]; } @@ -230,7 +216,6 @@ fn consistent_TX_EFFECTS_HASH_INPUT_FIELDS() { + MAX_NEW_NULLIFIERS_PER_TX + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 + MAX_NEW_L2_TO_L1_MSGS_PER_TX - + MAX_NEW_CONTRACTS_PER_TX * 3 + NUM_ENCRYPTED_LOGS_HASHES_PER_TX * NUM_FIELDS_PER_SHA256 + NUM_UNENCRYPTED_LOGS_HASHES_PER_TX * NUM_FIELDS_PER_SHA256; assert(TX_EFFECTS_HASH_INPUT_FIELDS == expected_size, "tx effects hash input size is incorrect"); diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr index 9f094959573..f2b9e6557c2 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr @@ -98,14 +98,6 @@ mod tests { let _output = inputs.merge_rollup_circuit(); } - #[test(should_fail_with="input proofs have different contract tree snapshots")] - fn previous_rollups_dont_follow_contracts() { - let mut inputs = default_merge_rollup_inputs(); - inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.end.contract_tree.root = 0; - inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.start.contract_tree.root = 1; - let _output = inputs.merge_rollup_circuit(); - } - #[test] fn rollup_fields_are_set_correctly() { let mut inputs = default_merge_rollup_inputs(); diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root.nr index 0f38a84cde9..10de29dfc6c 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root.nr @@ -97,10 +97,6 @@ mod tests { outputs.header.state.partial.nullifier_tree.eq(inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.end.nullifier_tree) ); - assert( - outputs.header.state.partial.contract_tree.eq(inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.end.contract_tree) - ); - assert( outputs.header.state.partial.public_data_tree.eq(inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.end.public_data_tree) ); diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr index 623014f668c..508e4d9ed44 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr @@ -9,7 +9,7 @@ use dep::types::{ L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, ARCHIVE_HEIGHT }, header::Header, content_commitment::ContentCommitment, - merkle_tree::{append_only_tree, calculate_subtree, calculate_empty_tree_root}, + merkle_tree::{append_only_tree, calculate_subtree_root, calculate_empty_tree_root}, state_reference::StateReference }; @@ -41,7 +41,7 @@ impl RootRollupInputs { // Check correct l1 to l2 tree given // Compute subtree inserting l1 to l2 messages - let l1_to_l2_subtree_root = calculate_subtree(self.new_l1_to_l2_messages); + let l1_to_l2_subtree_root = calculate_subtree_root(self.new_l1_to_l2_messages); // Insert subtree into the l1 to l2 data tree let empty_l1_to_l2_subtree_root = calculate_empty_tree_root(L1_TO_L2_MSG_SUBTREE_HEIGHT); diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr index 90e4d16bfc2..a66ed609eef 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr @@ -39,23 +39,6 @@ pub fn default_previous_rollup_data() -> [PreviousRollupData; 2] { next_available_leaf_index: 2 }; - previous_rollup_data[0].base_or_merge_rollup_public_inputs.start.contract_tree = AppendOnlyTreeSnapshot { - root: 0, - next_available_leaf_index: 0 - }; - previous_rollup_data[0].base_or_merge_rollup_public_inputs.end.contract_tree = AppendOnlyTreeSnapshot { - root: 1, - next_available_leaf_index: 1 - }; - previous_rollup_data[1].base_or_merge_rollup_public_inputs.start.contract_tree = AppendOnlyTreeSnapshot { - root: 1, - next_available_leaf_index: 1 - }; - previous_rollup_data[1].base_or_merge_rollup_public_inputs.end.contract_tree = AppendOnlyTreeSnapshot { - root: 2, - next_available_leaf_index: 2 - }; - previous_rollup_data[0].base_or_merge_rollup_public_inputs.start.public_data_tree = AppendOnlyTreeSnapshot { root: 0, next_available_leaf_index: 1 diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr index 7736b8940f9..a4aac38d69b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr @@ -10,9 +10,7 @@ mod global_variables; mod membership_witness; -mod new_contract_data; mod nullifier_leaf_preimage; -mod contract_leaf_preimage; mod combined_constant_data; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/accumulated_non_revertible_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/accumulated_non_revertible_data_builder.nr index f138d7e1f26..3499620d06c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/accumulated_non_revertible_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/accumulated_non_revertible_data_builder.nr @@ -12,7 +12,8 @@ use crate::{ use crate::constants::{ MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX, MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX, MAX_NON_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, - MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX + MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX }; struct AccumulatedNonRevertibleDataBuilder { @@ -20,6 +21,7 @@ struct AccumulatedNonRevertibleDataBuilder { new_nullifiers: BoundedVec, public_call_stack: BoundedVec, nullifier_read_requests: BoundedVec, + nullifier_non_existent_read_requests: BoundedVec, public_data_update_requests: BoundedVec, public_data_reads: BoundedVec, } @@ -38,6 +40,7 @@ impl AccumulatedNonRevertibleDataBuilder { new_nullifiers: self.new_nullifiers.storage, public_call_stack: self.public_call_stack.storage, nullifier_read_requests: self.nullifier_read_requests.storage, + nullifier_non_existent_read_requests: self.nullifier_non_existent_read_requests.storage, public_data_update_requests: self.public_data_update_requests.storage, public_data_reads: self.public_data_reads.storage } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/accumulated_revertible_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/accumulated_revertible_data_builder.nr index 5ecd302a8a8..3c54520db42 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/accumulated_revertible_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/accumulated_revertible_data_builder.nr @@ -4,8 +4,7 @@ use crate::{ private_accumulated_revertible_data::PrivateAccumulatedRevertibleData, public_accumulated_revertible_data::PublicAccumulatedRevertibleData }, - call_request::CallRequest, new_contract_data::NewContractData, - nullifier_key_validation_request::NullifierKeyValidationRequestContext, + call_request::CallRequest, nullifier_key_validation_request::NullifierKeyValidationRequestContext, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequestContext, side_effect::{SideEffect, SideEffectLinkedToNoteHash} } @@ -13,10 +12,9 @@ use crate::{ use crate::constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NEW_CONTRACTS_PER_TX, NUM_FIELDS_PER_SHA256, - MAX_REVERTIBLE_NOTE_HASHES_PER_TX, MAX_REVERTIBLE_NULLIFIERS_PER_TX, - MAX_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, - MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX, NUM_FIELDS_PER_SHA256, MAX_REVERTIBLE_NOTE_HASHES_PER_TX, + MAX_REVERTIBLE_NULLIFIERS_PER_TX, MAX_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, + MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX }; struct AccumulatedRevertibleDataBuilder { @@ -39,8 +37,6 @@ struct AccumulatedRevertibleDataBuilder { encrypted_log_preimages_length: Field, unencrypted_log_preimages_length: Field, - new_contracts: BoundedVec, - public_data_update_requests: BoundedVec, public_data_reads: BoundedVec, } @@ -56,8 +52,7 @@ impl AccumulatedRevertibleDataBuilder { encrypted_logs_hash: self.encrypted_logs_hash, unencrypted_logs_hash: self.unencrypted_logs_hash, encrypted_log_preimages_length: self.encrypted_log_preimages_length, - unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, - new_contracts: self.new_contracts.storage + unencrypted_log_preimages_length: self.unencrypted_log_preimages_length } } @@ -75,7 +70,6 @@ impl AccumulatedRevertibleDataBuilder { unencrypted_logs_hash: self.unencrypted_logs_hash, encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, - new_contracts: self.new_contracts.storage, public_data_update_requests: self.public_data_update_requests.storage, public_data_reads: self.public_data_reads.storage } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr index 7ce04e9e935..bd66210b29a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr @@ -4,7 +4,7 @@ use crate::{ public_accumulated_non_revertible_data::PublicAccumulatedNonRevertibleData, public_accumulated_revertible_data::PublicAccumulatedRevertibleData }, - call_request::CallRequest, caller_context::CallerContext, new_contract_data::NewContractData, + call_request::CallRequest, caller_context::CallerContext, nullifier_key_validation_request::NullifierKeyValidationRequestContext, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequestContext, side_effect::{SideEffect, SideEffectLinkedToNoteHash} @@ -14,13 +14,12 @@ use crate::constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NEW_CONTRACTS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_PUBLIC_DATA_READS_PER_TX, NUM_FIELDS_PER_SHA256, MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX, - MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX, MAX_NON_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, - MAX_REVERTIBLE_NOTE_HASHES_PER_TX, MAX_REVERTIBLE_NULLIFIERS_PER_TX, - MAX_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, - MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, - MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, + NUM_FIELDS_PER_SHA256, MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX, MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX, + MAX_NON_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_REVERTIBLE_NOTE_HASHES_PER_TX, + MAX_REVERTIBLE_NULLIFIERS_PER_TX, MAX_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, + MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX }; use dep::std::unsafe; @@ -48,8 +47,6 @@ struct CombinedAccumulatedData { encrypted_log_preimages_length: Field, unencrypted_log_preimages_length: Field, - new_contracts: [NewContractData; MAX_NEW_CONTRACTS_PER_TX], - public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], public_data_reads: [PublicDataRead; MAX_PUBLIC_DATA_READS_PER_TX], @@ -81,7 +78,6 @@ impl CombinedAccumulatedData { unencrypted_logs_hash: revertible.unencrypted_logs_hash, encrypted_log_preimages_length: revertible.encrypted_log_preimages_length, unencrypted_log_preimages_length: revertible.unencrypted_log_preimages_length, - new_contracts: revertible.new_contracts, public_data_update_requests: array_concat( non_revertible.public_data_update_requests, revertible.public_data_update_requests @@ -97,7 +93,7 @@ impl CombinedAccumulatedData { mod tests { use crate::abis::{ accumulated_data::combined_accumulated_data_builder::CombinedAccumulatedDataBuilder, - call_request::CallRequest, caller_context::CallerContext, new_contract_data::NewContractData, + call_request::CallRequest, caller_context::CallerContext, nullifier_key_validation_request::NullifierKeyValidationRequestContext, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, side_effect::{SideEffect, SideEffectLinkedToNoteHash} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data_builder.nr index d949da09d6a..fedfdfe9b5f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data_builder.nr @@ -9,8 +9,7 @@ use crate::{ public_accumulated_revertible_data::PublicAccumulatedRevertibleData, public_accumulated_non_revertible_data::PublicAccumulatedNonRevertibleData }, - call_request::CallRequest, new_contract_data::NewContractData, - nullifier_key_validation_request::NullifierKeyValidationRequestContext, + call_request::CallRequest, nullifier_key_validation_request::NullifierKeyValidationRequestContext, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequestContext, side_effect::{SideEffect, SideEffectLinkedToNoteHash} } @@ -19,13 +18,12 @@ use crate::constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NEW_CONTRACTS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_PUBLIC_DATA_READS_PER_TX, NUM_FIELDS_PER_SHA256, MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX, - MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX, MAX_NON_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, - MAX_REVERTIBLE_NOTE_HASHES_PER_TX, MAX_REVERTIBLE_NULLIFIERS_PER_TX, - MAX_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, - MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, - MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, + NUM_FIELDS_PER_SHA256, MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX, MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX, + MAX_NON_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_REVERTIBLE_NOTE_HASHES_PER_TX, + MAX_REVERTIBLE_NULLIFIERS_PER_TX, MAX_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, + MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX }; use dep::std::unsafe; @@ -53,8 +51,6 @@ struct CombinedAccumulatedDataBuilder { encrypted_log_preimages_length: Field, unencrypted_log_preimages_length: Field, - new_contracts: BoundedVec, - public_data_update_requests: BoundedVec, public_data_reads: BoundedVec, @@ -83,7 +79,6 @@ impl CombinedAccumulatedDataBuilder { unencrypted_logs_hash: revertible.unencrypted_logs_hash, encrypted_log_preimages_length: revertible.encrypted_log_preimages_length, unencrypted_log_preimages_length: revertible.unencrypted_log_preimages_length, - new_contracts: array_to_bounded_vec(revertible.new_contracts), public_data_update_requests: array_to_bounded_vec( array_concat( non_revertible.public_data_update_requests, @@ -113,7 +108,6 @@ impl CombinedAccumulatedDataBuilder { unencrypted_logs_hash: self.unencrypted_logs_hash, encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, - new_contracts: self.new_contracts.storage, public_data_update_requests: self.public_data_update_requests.storage, public_data_reads: self.public_data_reads.storage } @@ -129,8 +123,7 @@ impl CombinedAccumulatedDataBuilder { encrypted_logs_hash: self.encrypted_logs_hash, unencrypted_logs_hash: self.unencrypted_logs_hash, encrypted_log_preimages_length: self.encrypted_log_preimages_length, - unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, - new_contracts: self.new_contracts.storage + unencrypted_log_preimages_length: self.unencrypted_log_preimages_length } } @@ -148,7 +141,6 @@ impl CombinedAccumulatedDataBuilder { unencrypted_logs_hash: self.unencrypted_logs_hash, encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, - new_contracts: self.new_contracts.storage, public_data_update_requests: array_cp(self.public_data_update_requests.storage), public_data_reads: array_cp(self.public_data_reads.storage) } @@ -201,7 +193,6 @@ impl CombinedAccumulatedDataBuilder { revertible_builder.unencrypted_logs_hash = self.unencrypted_logs_hash; revertible_builder.encrypted_log_preimages_length = self.encrypted_log_preimages_length; revertible_builder.unencrypted_log_preimages_length= self.unencrypted_log_preimages_length; - revertible_builder.new_contracts = self.new_contracts; (non_revertible_builder.to_private(), revertible_builder.to_private()) } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_revertible_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_revertible_data.nr index 16d6028d74f..be3c470d77e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_revertible_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_revertible_data.nr @@ -1,13 +1,8 @@ -use crate::{ - abis::{ - call_request::CallRequest, new_contract_data::NewContractData, - side_effect::{SideEffect, SideEffectLinkedToNoteHash} -} -}; +use crate::{abis::{call_request::CallRequest, side_effect::{SideEffect, SideEffectLinkedToNoteHash}}}; use crate::constants::{ MAX_REVERTIBLE_NOTE_HASHES_PER_TX, MAX_REVERTIBLE_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, NUM_FIELDS_PER_SHA256, MAX_NEW_CONTRACTS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX, NUM_FIELDS_PER_SHA256 }; struct PrivateAccumulatedRevertibleData { @@ -25,8 +20,6 @@ struct PrivateAccumulatedRevertibleData { // variable-length data. encrypted_log_preimages_length: Field, unencrypted_log_preimages_length: Field, - - new_contracts: [NewContractData; MAX_NEW_CONTRACTS_PER_TX], } impl PrivateAccumulatedRevertibleData { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_non_revertible_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_non_revertible_data.nr index 697c307e656..c8175fbd7c0 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_non_revertible_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_non_revertible_data.nr @@ -8,7 +8,8 @@ use crate::{ use crate::constants::{ MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX, MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX, MAX_NON_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, - MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX + MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX }; use dep::std::unsafe; @@ -21,6 +22,7 @@ struct PublicAccumulatedNonRevertibleData { new_nullifiers: [SideEffectLinkedToNoteHash; MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX], public_call_stack: [CallRequest; MAX_NON_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX], nullifier_read_requests: [ReadRequestContext; MAX_NULLIFIER_READ_REQUESTS_PER_TX], + nullifier_non_existent_read_requests: [ReadRequestContext; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX], public_data_update_requests: [PublicDataUpdateRequest; MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], public_data_reads: [PublicDataRead; MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX], } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_revertible_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_revertible_data.nr index 1f64f37bb3f..2b310a2ae87 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_revertible_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_revertible_data.nr @@ -1,7 +1,6 @@ use crate::{ abis::{ - call_request::CallRequest, new_contract_data::NewContractData, - nullifier_key_validation_request::NullifierKeyValidationRequestContext, + call_request::CallRequest, nullifier_key_validation_request::NullifierKeyValidationRequestContext, public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest, read_request::ReadRequestContext, side_effect::{SideEffect, SideEffectLinkedToNoteHash} } @@ -11,10 +10,10 @@ use crate::constants::{ MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, MAX_REVERTIBLE_NOTE_HASHES_PER_TX, MAX_REVERTIBLE_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, NUM_FIELDS_PER_SHA256, - MAX_NEW_CONTRACTS_PER_TX, MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX + MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX }; +// TODO - Requests for checking data should not be revertible. struct PublicAccumulatedRevertibleData { note_hash_read_requests: [SideEffect; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], nullifier_read_requests: [ReadRequestContext; MAX_NULLIFIER_READ_REQUESTS_PER_TX], @@ -35,8 +34,6 @@ struct PublicAccumulatedRevertibleData { encrypted_log_preimages_length: Field, unencrypted_log_preimages_length: Field, - new_contracts: [NewContractData; MAX_NEW_CONTRACTS_PER_TX], - public_data_update_requests: [PublicDataUpdateRequest; MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], public_data_reads: [PublicDataRead; MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX], } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr index 9f1cd659fef..d312ea1c23c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr @@ -14,7 +14,6 @@ struct CallContext { is_delegate_call : bool, is_static_call : bool, - is_contract_deployment : bool, start_side_effect_counter : u32, } @@ -29,7 +28,6 @@ impl CallContext { assert(self.function_selector.to_field() == 0); assert(self.is_delegate_call == false); assert(self.is_static_call == false); - assert(self.is_contract_deployment == false); assert(self.start_side_effect_counter == 0); } } @@ -43,7 +41,6 @@ impl Eq for CallContext { & call_context.function_selector.eq(self.function_selector) & (call_context.is_delegate_call == self.is_delegate_call) & (call_context.is_static_call == self.is_static_call) - & (call_context.is_contract_deployment == self.is_contract_deployment) & (call_context.start_side_effect_counter == self.start_side_effect_counter) } } @@ -63,7 +60,6 @@ impl Serialize for CallContext { self.function_selector.to_field(), self.is_delegate_call as Field, self.is_static_call as Field, - self.is_contract_deployment as Field, self.start_side_effect_counter as Field, ] } @@ -78,8 +74,7 @@ impl Deserialize for CallContext { function_selector: FunctionSelector::from_field(serialized[3]), is_delegate_call: serialized[4] as bool, is_static_call: serialized[5] as bool, - is_contract_deployment: serialized[6] as bool, - start_side_effect_counter: serialized[7] as u32, + start_side_effect_counter: serialized[6] as u32, } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/contract_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/contract_leaf_preimage.nr deleted file mode 100644 index 8a0b726de5c..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/contract_leaf_preimage.nr +++ /dev/null @@ -1,9 +0,0 @@ -// TODO(David): The cpp code uses a typename. I've used a new module -// to make it more obvious that we have NewContractData being aliased -// as ContractLeafPreimage. -// It may make sense to only use `ContractLeafPreimage` in the codebase. -// -// This is not actually being used anywhere due to Noir not -// resolving import path aliases and re-exports properly. -// If you grep for `ContractLeafPreimage` you can see its usage. -use crate::abis::new_contract_data::NewContractData as ContractLeafPreimage; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/membership_witness.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/membership_witness.nr index 443efeaf108..d23cfb0f19a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/membership_witness.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/membership_witness.nr @@ -1,13 +1,8 @@ use crate::constants::{ - CONTRACT_TREE_HEIGHT, FUNCTION_TREE_HEIGHT, NULLIFIER_TREE_HEIGHT, NOTE_HASH_TREE_HEIGHT, - ROLLUP_VK_TREE_HEIGHT, ARCHIVE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT + FUNCTION_TREE_HEIGHT, NULLIFIER_TREE_HEIGHT, NOTE_HASH_TREE_HEIGHT, ROLLUP_VK_TREE_HEIGHT, + ARCHIVE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT }; -struct MembershipWitness { - leaf_index: Field, - sibling_path: [Field; N] -} - // TODO(Kev): Instead of doing `MembershipWitness` we are forced // to do this new struct because the typescript bindings generator // does not have logic to monomorphize these properly. See the file named @@ -17,11 +12,6 @@ struct FunctionLeafMembershipWitness{ sibling_path: [Field; FUNCTION_TREE_HEIGHT] } -struct ContractLeafMembershipWitness{ - leaf_index: Field, - sibling_path: [Field; CONTRACT_TREE_HEIGHT] -} - struct VKMembershipWitness{ leaf_index: Field, sibling_path: [Field; ROLLUP_VK_TREE_HEIGHT] diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/new_contract_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/new_contract_data.nr deleted file mode 100644 index 735d7329776..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/new_contract_data.nr +++ /dev/null @@ -1,110 +0,0 @@ -use crate::address::{AztecAddress, EthAddress}; -use crate::contract_class_id::ContractClassId; -use crate::constants::{GENERATOR_INDEX__CONTRACT_LEAF, NEW_CONTRACT_DATA_LENGTH}; -use dep::std::cmp::Eq; -use crate::traits::{Empty, Serialize, Hash, Deserialize}; -use crate::hash::pedersen_hash; - -struct NewContractData { - contract_address: AztecAddress, - portal_contract_address: EthAddress, - contract_class_id: ContractClassId, -} - -impl Eq for NewContractData { - fn eq(self, data: NewContractData) -> bool { - data.contract_address.eq(self.contract_address) - & data.portal_contract_address.eq(self.portal_contract_address) - & data.contract_class_id.eq(self.contract_class_id) - } -} - -impl Serialize for NewContractData { - fn serialize(self) -> [Field; NEW_CONTRACT_DATA_LENGTH] { - [ - self.contract_address.to_field(), - self.portal_contract_address.to_field(), - self.contract_class_id.to_field(), - ] - } -} - -impl Deserialize for NewContractData { - fn deserialize(serialized: [Field; NEW_CONTRACT_DATA_LENGTH]) -> Self { - Self { - contract_address: AztecAddress::from_field(serialized[0]), - portal_contract_address: EthAddress::from_field(serialized[1]), - contract_class_id: ContractClassId::from_field(serialized[2]), - } - } -} - -impl Empty for NewContractData { - fn empty() -> Self { - Self { - contract_address : AztecAddress::empty(), - portal_contract_address : EthAddress::empty(), - contract_class_id: ContractClassId::from_field(0), - } - } -} - -impl Hash for NewContractData { - fn hash(self) -> Field { - if self.is_empty() { - 0 // We want to return 0 here since the contract_address is zero - } else { - pedersen_hash(self.serialize(), GENERATOR_INDEX__CONTRACT_LEAF) - } - } -} - -impl NewContractData { - pub fn is_empty(self) -> bool { - (self.contract_address.to_field() == 0) - & (self.portal_contract_address.to_field() == 0) - & (self.contract_class_id.to_field() == 0) - } -} - -mod tests { - use crate::{ - abis::new_contract_data::NewContractData, address::{AztecAddress, EthAddress}, - contract_class_id::ContractClassId - }; - - // Matches makeNewContractData in factories.ts - fn make_new_contract_data(seed: Field) -> NewContractData { - NewContractData { - contract_address: AztecAddress::from_field(seed), - portal_contract_address: EthAddress::from_field(seed + 1), - contract_class_id: ContractClassId::from_field(seed + 2) - } - } - - #[test] - fn serialization_of_empty() { - let data: NewContractData = dep::std::unsafe::zeroed(); - let serialized = data.serialize(); - let deserialized = NewContractData::deserialize(serialized); - assert(data.eq(deserialized)); - } - - #[test] - fn empty_hash_is_zero() { - let data: NewContractData = dep::std::unsafe::zeroed(); - let hash = data.hash(); - - // Value from new_contract_data.test.ts "computes empty hash" test - assert_eq(hash, 0x0000000000000000000000000000000000000000000000000000000000000000); - } - - #[test] - fn hash_matches() { - let data = make_new_contract_data(5); - let hash = data.hash(); - - // Value from new_contract_data.test.ts "hash matches" test - assert_eq(hash, 0x2359862482fb58cf5a5ddab56eb6d49908bc811353f3fd6fe9fd057c525cbf0b); - } -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr index 6eb484e5d66..895196567a0 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr @@ -1,6 +1,6 @@ global NULLIFIER_LEAF_PREIMAGE_LENGTH: u64 = 3; -use crate::{merkle_tree::leaf_preimage::LeafPreimage, traits::{Empty, Hash}}; +use crate::{merkle_tree::leaf_preimage::{LeafPreimage, IndexedTreeLeafPreimage}, traits::{Empty, Hash}}; struct NullifierLeafPreimage { nullifier : Field, @@ -38,6 +38,20 @@ impl LeafPreimage for NullifierLeafPreimage { } } +impl IndexedTreeLeafPreimage for NullifierLeafPreimage { + fn get_key(self) -> Field { + self.nullifier + } + + fn get_next_key(self) -> Field { + self.next_nullifier + } + + fn as_leaf(self) -> Field { + self.hash() + } +} + impl NullifierLeafPreimage { pub fn is_empty(self) -> bool { (self.nullifier == 0) & (self.next_nullifier == 0) & (self.next_index == 0) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr index cdf79b46085..7b287d20ed6 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr @@ -75,5 +75,6 @@ fn empty_hash() { let hash = item.hash(); // Value from private_call_stack_item.test.ts "computes empty item hash" test - assert_eq(hash, 0x19ee1f10c5c0508a8d727da00c97b8198522d7a17fab73eb804f24183177b798); + let test_data_empty_hash = 0x1c3b67cab2bc3dc2106cfeddd8ea68b8d445849f20ed3b9286ad684542aae25d; + assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr index a36c0e4d4bd..e89c6dc8b31 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr @@ -11,9 +11,8 @@ use crate::{ RETURN_VALUES_LENGTH, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS }, - contrakt::contract_deployment_data::ContractDeploymentData, header::Header, hash::pedersen_hash, - messaging::l2_to_l1_message::L2ToL1Message, traits::{Deserialize, Hash, Serialize}, - utils::reader::Reader + header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message, + traits::{Deserialize, Hash, Serialize}, utils::reader::Reader }; struct PrivateCircuitPublicInputs { @@ -46,8 +45,6 @@ struct PrivateCircuitPublicInputs { // Header of a block whose state is used during private execution (not the block the transaction is included in). historical_header: Header, - contract_deployment_data: ContractDeploymentData, - // Note: The following 2 values are not redundant to the values in self.historical_header.global_variables because // they can be different in case of a protocol upgrade. In such a situation we could be using header from a block // before the upgrade took place but be using the updated protocol to execute and prove the transaction. @@ -74,7 +71,6 @@ impl Eq for PrivateCircuitPublicInputs { (self.encrypted_log_preimages_length == other.encrypted_log_preimages_length) & (self.unencrypted_log_preimages_length == other.unencrypted_log_preimages_length) & self.historical_header.eq(other.historical_header) & - self.contract_deployment_data.eq(other.contract_deployment_data) & self.chain_id.eq(other.chain_id) & self.version.eq(other.version) } @@ -115,7 +111,6 @@ impl Serialize for PrivateCircuitPublicInp fields.push(self.encrypted_log_preimages_length); fields.push(self.unencrypted_log_preimages_length); fields.extend_from_array(self.historical_header.serialize()); - fields.extend_from_array(self.contract_deployment_data.serialize()); fields.push(self.chain_id); fields.push(self.version); @@ -148,7 +143,6 @@ impl Deserialize for PrivateCircuitPublicI encrypted_log_preimages_length: reader.read(), unencrypted_log_preimages_length: reader.read(), historical_header: reader.read_struct(Header::deserialize), - contract_deployment_data: reader.read_struct(ContractDeploymentData::deserialize), chain_id: reader.read(), version: reader.read(), }; @@ -178,5 +172,6 @@ fn empty_hash() { let hash = inputs.hash(); // Value from private_circuit_public_inputs.test.ts "computes empty item hash" test - assert_eq(hash, 0x13ba2af75e4afaa4e52dd1afa083e87706cdbab1a33442025dc3a9bbb546d207); + let test_data_empty_hash = 0x2745ec62624afeb19b86af3d440db1f8c3432e1d17a074c75cb8f44999fd3fae; + assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr index 4d8c8aeef2d..40ffa87a975 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr @@ -1,6 +1,6 @@ use crate::abis::{ call_request::CallRequest, private_call_stack_item::PrivateCallStackItem, - membership_witness::{ContractLeafMembershipWitness, FunctionLeafMembershipWitness, NoteHashReadRequestMembershipWitness} + membership_witness::{FunctionLeafMembershipWitness, NoteHashReadRequestMembershipWitness} }; use crate::address::{SaltedInitializationHash, PublicKeysHash, EthAddress}; use crate::contract_class_id::ContractClassId; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr index 51ee94e817b..3a9181be985 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr @@ -69,7 +69,8 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item request hash" test - assert_eq(call_stack_item.hash(), 0x10017014b5fd719261c575bd7acd1e604c0dd3e86d8c6af80294eadfc6d174a7); + let test_data_call_stack_item_request_hash = 0x1a1194c14f229b72d31669b06e3984d6f0f5edd4d5204ceda0ff30f25e910e83; + assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash); } #[test] @@ -86,6 +87,7 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item hash" test - assert_eq(call_stack_item.hash(), 0x182201ec06be2dc7eddaa8b828eb293eab9938c4d41cde1e2b1b766ee21d2a54); + let test_data_call_stack_item_hash = 0x187836686ed01f12180ef08c419e4ac8514d9c60e6a38b4a56d893fa90c83a5d; + assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr index a1a1667fdd1..e364c3b49d8 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr @@ -6,10 +6,10 @@ use crate::{ address::AztecAddress, constants::{ MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, - MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, NUM_FIELDS_PER_SHA256, - RETURN_VALUES_LENGTH, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS, - PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH + MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, NUM_FIELDS_PER_SHA256, RETURN_VALUES_LENGTH, + GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS, PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH }, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, hash::pedersen_hash, header::Header, messaging::l2_to_l1_message::L2ToL1Message, @@ -23,6 +23,7 @@ struct PublicCircuitPublicInputs{ return_values: [Field; RETURN_VALUES_LENGTH], nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL], + nullifier_non_existent_read_requests: [ReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL], contract_storage_update_requests: [StorageUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL], contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL], @@ -62,6 +63,9 @@ impl Serialize for PublicCircuitPublicInput for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL { fields.extend_from_array(self.nullifier_read_requests[i].serialize()); } + for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL { + fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize()); + } for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL { fields.extend_from_array(self.contract_storage_update_requests[i].serialize()); } @@ -97,6 +101,7 @@ impl Deserialize for PublicCircuitPublicInp args_hash: reader.read(), return_values: reader.read_array([0; RETURN_VALUES_LENGTH]), nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]), + nullifier_non_existent_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL]), contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]), contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]), public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]), @@ -135,5 +140,6 @@ fn empty_hash() { let hash = inputs.hash(); // Value from public_circuit_public_inputs.test.ts "computes empty item hash" test - assert_eq(hash, 0x01fcd6e2480909d55f03f4ee87924cbabb0b4706cb742c70422e423b2db5f4eb); + let test_data_empty_hash = 0x1c9942cee14a4f84b3e606f553b2ab3151c395822ee7ffd51759d5822375d6c9; + assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 00e295c50b1..1c765a0bc7e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -32,6 +32,7 @@ global MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL: u64 = 16; global MAX_PUBLIC_DATA_READS_PER_CALL: u64 = 16; global MAX_NOTE_HASH_READ_REQUESTS_PER_CALL: u64 = 32; global MAX_NULLIFIER_READ_REQUESTS_PER_CALL: u64 = 2; // Change it to a larger value when there's a seperate reset circuit. +global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL: u64 = 2; global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL: u64 = 1; // "PER TRANSACTION" CONSTANTS @@ -58,9 +59,9 @@ global MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX: u64 = 16; global MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX: u64 = 16; global MAX_NEW_L2_TO_L1_MSGS_PER_TX: u64 = 2; -global MAX_NEW_CONTRACTS_PER_TX: u64 = 1; global MAX_NOTE_HASH_READ_REQUESTS_PER_TX: u64 = 128; global MAX_NULLIFIER_READ_REQUESTS_PER_TX: u64 = 8; // Change it to a larger value when there's a seperate reset circuit. +global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX: u64 = 8; global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX: u64 = 4; global NUM_ENCRYPTED_LOGS_HASHES_PER_TX: u64 = 1; global NUM_UNENCRYPTED_LOGS_HASHES_PER_TX: u64 = 1; @@ -72,17 +73,19 @@ global NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP: u64 = 16; // TREES RELATED CONSTANTS global VK_TREE_HEIGHT: u64 = 3; global FUNCTION_TREE_HEIGHT: u64 = 5; -global CONTRACT_TREE_HEIGHT: u64 = 16; global NOTE_HASH_TREE_HEIGHT: u64 = 32; global PUBLIC_DATA_TREE_HEIGHT: u64 = 40; global NULLIFIER_TREE_HEIGHT: u64 = 20; global L1_TO_L2_MSG_TREE_HEIGHT: u64 = 16; global ROLLUP_VK_TREE_HEIGHT: u64 = 8; global ARTIFACT_FUNCTION_TREE_MAX_HEIGHT = 5; +global NULLIFIER_TREE_ID = 0; +global NOTE_HASH_TREE_ID = 1; +global PUBLIC_DATA_TREE_ID = 2; +global L1_TO_L2_MESSAGE_TREE_ID = 3; +global ARCHIVE_TREE_ID = 4; // SUB-TREES RELATED CONSTANTS -global CONTRACT_SUBTREE_HEIGHT: u64 = 0; -global CONTRACT_SUBTREE_SIBLING_PATH_LENGTH: u64 = 16; global NOTE_HASH_SUBTREE_HEIGHT: u64 = 6; global NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH: u64 = 26; global NULLIFIER_SUBTREE_HEIGHT: u64 = 6; @@ -109,7 +112,7 @@ global INITIAL_L2_BLOCK_NUM: Field = 1; global BLOB_SIZE_IN_BYTES: Field = 126976; // CONTRACT CLASS CONSTANTS -global MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS: u64 = 9000; +global MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS: u64 = 15000; // Bytecode size for private functions is per function, not for the entire contract. // Note that private functions bytecode includes a mix of acir and brillig. global MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS: u64 = 500; @@ -145,9 +148,8 @@ global VIEW_NOTE_ORACLE_RETURN_LENGTH: u64 = 212; // LENGTH OF STRUCTS SERIALIZED TO FIELDS global AZTEC_ADDRESS_LENGTH = 1; -global CALL_CONTEXT_LENGTH: u64 = 8; +global CALL_CONTEXT_LENGTH: u64 = 7; global CONTENT_COMMITMENT_LENGTH: u64 = 7; -global CONTRACT_DEPLOYMENT_DATA_LENGTH: u64 = 6; global CONTRACT_INSTANCE_LENGTH: u64 = 6; global CONTRACT_STORAGE_READ_LENGTH: u64 = 2; global CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH: u64 = 2; @@ -155,24 +157,24 @@ global ETH_ADDRESS_LENGTH = 1; global FUNCTION_DATA_LENGTH: u64 = 4; global FUNCTION_LEAF_PREIMAGE_LENGTH: u64 = 5; global GLOBAL_VARIABLES_LENGTH: u64 = 6; -global HEADER_LENGTH: u64 = 25; // 2 for last_archive, 7 for content commitment, 10 for state reference, 6 for global vars +global HEADER_LENGTH: u64 = 23; // 2 for last_archive, 7 for content commitment, 8 for state reference, 6 for global vars global L1_TO_L2_MESSAGE_LENGTH: u64 = 8; global L2_TO_L1_MESSAGE_LENGTH: u64 = 2; -global NEW_CONTRACT_DATA_LENGTH: u64 = 3; global NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 4; global NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 5; -global PARTIAL_STATE_REFERENCE_LENGTH: u64 = 8; -global PRIVATE_CALL_STACK_ITEM_LENGTH: u64 = 223; +global PARTIAL_STATE_REFERENCE_LENGTH: u64 = 6; +global PRIVATE_CALL_STACK_ITEM_LENGTH: u64 = 214; // Change this ONLY if you have changed the PrivateCircuitPublicInputs structure. // In other words, if the structure/size of the public inputs of a function call changes then we should change this // constant as well PRIVATE_CALL_STACK_ITEM_LENGTH -global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = 218; +global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = 209; // Change this ONLY if you have changed the PublicCircuitPublicInputs structure. -global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = 199; -global STATE_REFERENCE_LENGTH: u64 = 10; // 2 for snap + 8 for partial -global TX_CONTEXT_DATA_LENGTH: u64 = 11; -global TX_REQUEST_LENGTH: u64 = 17; +global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = 200; +global STATE_REFERENCE_LENGTH: u64 = 8; // 2 for snap + 8 for partial +global TX_CONTEXT_DATA_LENGTH: u64 = 4; +global TX_REQUEST_LENGTH: u64 = 10; +global ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH: Field = 13; // 2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH global GET_NOTES_ORACLE_RETURN_LENGTH: u64 = 674; global NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP: Field = 2048; global NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP: Field = 2048; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt.nr index 75c7324eb40..1a84b4f0a76 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt.nr @@ -1,3 +1,2 @@ -mod contract_deployment_data; mod storage_read; mod storage_update_request; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/contract_deployment_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/contract_deployment_data.nr deleted file mode 100644 index 29e87193e9a..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/contract_deployment_data.nr +++ /dev/null @@ -1,86 +0,0 @@ -use crate::{ - address::EthAddress, contract_class_id::ContractClassId, - constants::{CONTRACT_DEPLOYMENT_DATA_LENGTH, GENERATOR_INDEX__CONTRACT_DEPLOYMENT_DATA}, - grumpkin_point::GrumpkinPoint, hash::pedersen_hash, traits::{Deserialize, Hash, Serialize} -}; - -// docs:start:contract-deployment-data -struct ContractDeploymentData { - public_key : GrumpkinPoint, - initialization_hash : Field, - contract_class_id : ContractClassId, - contract_address_salt : Field, - portal_contract_address : EthAddress, -} -// docs:end:contract-deployment-data - -impl Eq for ContractDeploymentData { - fn eq(self, other: Self) -> bool { - self.public_key.eq(other.public_key) & - self.initialization_hash.eq(other.initialization_hash) & - self.contract_class_id.eq(other.contract_class_id) & - self.contract_address_salt.eq(other.contract_address_salt) & - self.portal_contract_address.eq(other.portal_contract_address) - } -} - -impl Hash for ContractDeploymentData { - fn hash(self) -> Field { - pedersen_hash(self.serialize(), GENERATOR_INDEX__CONTRACT_DEPLOYMENT_DATA) - } -} - -impl Serialize for ContractDeploymentData { - fn serialize(self) -> [Field; CONTRACT_DEPLOYMENT_DATA_LENGTH] { - [ - self.public_key.x, - self.public_key.y, - self.initialization_hash, - self.contract_class_id.to_field(), - self.contract_address_salt, - self.portal_contract_address.to_field(), - ] - } -} - -impl Deserialize for ContractDeploymentData { - fn deserialize(serialized: [Field; CONTRACT_DEPLOYMENT_DATA_LENGTH]) -> Self { - Self { - public_key: GrumpkinPoint { - x: serialized[0], - y: serialized[1], - }, - initialization_hash: serialized[2], - contract_class_id: ContractClassId::from_field(serialized[3]), - contract_address_salt: serialized[4], - portal_contract_address: EthAddress::from_field(serialized[5]), - } - } -} - -impl ContractDeploymentData { - fn assert_is_zero(self) { - self.public_key.assert_is_zero(); - assert(self.initialization_hash == 0); - self.contract_class_id.assert_is_zero(); - assert(self.contract_address_salt == 0); - self.portal_contract_address.assert_is_zero(); - } -} - -#[test] -fn serialization_of_empty() { - let data: ContractDeploymentData = dep::std::unsafe::zeroed(); - let serialized = data.serialize(); - let deserialized = ContractDeploymentData::deserialize(serialized); - assert(data.eq(deserialized)); -} - -#[test] -fn empty_hash() { - let data: ContractDeploymentData = dep::std::unsafe::zeroed(); - let hash = data.hash(); - - // Value from contract_deployment_data.test.ts "computes empty item hash" test - assert_eq(hash, 0x0e7babf59de8dfc7f5992cd34fb0066105d07ce67f68fc33d4a0a6a933a30405); -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr index 14c5deba67d..7de5fa7d536 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -4,18 +4,17 @@ use crate::abis::function_selector::FunctionSelector; use crate::abis::function_leaf_preimage::FunctionLeafPreimage; use crate::abis::contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage; use crate::contract_class_id::ContractClassId; -use crate::abis::new_contract_data::NewContractData as ContractLeafPreimage; use crate::abis::function_data::FunctionData; use crate::abis::side_effect::{SideEffect}; use crate::utils::uint256::U256; use crate::constants::{ - ARGS_HASH_CHUNK_COUNT, ARGS_HASH_CHUNK_LENGTH, CONTRACT_TREE_HEIGHT, FUNCTION_TREE_HEIGHT, - NUM_FIELDS_PER_SHA256, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER, - GENERATOR_INDEX__VK, GENERATOR_INDEX__CONSTRUCTOR, GENERATOR_INDEX__PARTIAL_ADDRESS, - GENERATOR_INDEX__CONTRACT_ADDRESS, GENERATOR_INDEX__NOTE_HASH_NONCE, - GENERATOR_INDEX__UNIQUE_NOTE_HASH, GENERATOR_INDEX__FUNCTION_ARGS + ARGS_HASH_CHUNK_COUNT, ARGS_HASH_CHUNK_LENGTH, FUNCTION_TREE_HEIGHT, NUM_FIELDS_PER_SHA256, + GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER, GENERATOR_INDEX__VK, + GENERATOR_INDEX__CONSTRUCTOR, GENERATOR_INDEX__PARTIAL_ADDRESS, GENERATOR_INDEX__CONTRACT_ADDRESS, + GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH, GENERATOR_INDEX__FUNCTION_ARGS }; use crate::messaging::l2_to_l1_message::L2ToL1Message; +use crate::merkle_tree::root::root_from_sibling_path; use dep::std::hash::{pedersen_hash_with_separator, sha256}; @@ -63,38 +62,6 @@ pub fn hash_args(args: [Field; N]) -> Field { } } -// Checks that `value` is a member of a merkle tree with root `root` at position `index` -// The witness being the `sibling_path` -pub fn assert_check_membership(value: Field, index: Field, sibling_path: [Field; N], root: Field) { - let calculated_root = root_from_sibling_path(value, index, sibling_path); - assert(calculated_root == root, "membership check failed"); -} - -// Calculate the Merkle tree root from the sibling path and leaf. -// -// The leaf is hashed with its sibling, and then the result is hashed -// with the next sibling etc in the path. The last hash is the root. -// -// TODO(David/Someone): The cpp code is using a uint256, whereas its -// TODO a bit simpler in Noir to just have a bit array. -// TODO: I'd generally like to avoid u256 for algorithms like -// this because it means we never even need to consider cases where -// the index is greater than p. -pub fn root_from_sibling_path(leaf: Field, leaf_index: Field, sibling_path: [Field; N]) -> Field { - let mut node = leaf; - let indices = leaf_index.to_le_bits(N); - - for i in 0..N { - let (hash_left, hash_right) = if indices[i] == 1 { - (sibling_path[i], node) - } else { - (node, sibling_path[i]) - }; - node = merkle_hash(hash_left, hash_right); - } - node -} - // Calculate the function tree root from the sibling path and leaf preimage. // // TODO: The cpp code passes in components of the FunctionLeafPreimage and then @@ -119,25 +86,6 @@ pub fn function_tree_root_from_siblings( function_tree_root } -// Calculate the contract tree root from the sibling path and leaf preimage. -pub fn contract_tree_root_from_siblings( - contract_class_id: ContractClassId, - storage_contract_address: AztecAddress, - portal_contract_address: EthAddress, - contract_leaf_index: Field, - contract_leaf_sibling_path: [Field; CONTRACT_TREE_HEIGHT] -) -> Field { - //TODO(Kev): if we use shorthand syntax here, we get an error as expected, - // since variable name is `storage_contract_address` but the span is incorrect. - let contract_leaf_preimage = ContractLeafPreimage { contract_address: storage_contract_address, portal_contract_address, contract_class_id }; - - let contract_leaf = contract_leaf_preimage.hash(); - - let computed_contract_tree_root = root_from_sibling_path(contract_leaf, contract_leaf_index, contract_leaf_sibling_path); - - computed_contract_tree_root -} - pub fn private_functions_root_from_siblings( selector: FunctionSelector, vk_hash: Field, @@ -169,7 +117,7 @@ pub fn silo_nullifier(address: AztecAddress, nullifier: Field) -> Field { ) } -fn merkle_hash(left: Field, right: Field) -> Field { +pub fn merkle_hash(left: Field, right: Field) -> Field { pedersen_hash([left, right], 0) } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/header.nr b/noir-projects/noir-protocol-circuits/crates/types/src/header.nr index ece1d741a96..57ec93f228d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/header.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/header.nr @@ -103,5 +103,6 @@ fn empty_hash_is_zero() { let hash = header.hash(); // Value from new_contract_data.test.ts "computes empty hash" test - assert_eq(hash, 0x2df930cc7b9fc763e82ade72f7c4618834692b2a3d0936aff8d7bbfb27f59d6e); + let test_data_empty_hash = 0x124e8c40a6eca2e3ad10c04050b01a3fad00df3cea47b13592c7571b6914c7a7; + assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree.nr index ecd76abb5ff..67b23d3f449 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree.nr @@ -1,110 +1,14 @@ mod append_only_tree; mod indexed_tree; mod leaf_preimage; - -struct MerkleTree { - leaves: [Field; N], - nodes: [Field; N], -} - -impl MerkleTree { - pub fn new(leaves: [Field; N]) -> Self { - let mut nodes = [0; N]; - - // We need one less node than leaves, but we cannot have computed array lengths - let total_nodes = N - 1; - let half_size = N / 2; - - // hash base layer - for i in 0..half_size { - nodes[i] = dep::std::hash::pedersen_hash([leaves[2*i], leaves[2*i+1]]); - } - - // hash the other layers - for i in 0..(total_nodes - half_size) { - nodes[half_size+i] = dep::std::hash::pedersen_hash([nodes[2*i], nodes[2*i+1]]); - } - - MerkleTree { leaves, nodes } - } - - fn get_root(self) -> Field { - self.nodes[N - 2] - } -} - -pub fn calculate_subtree(leaves: [Field; N]) -> Field { - MerkleTree::new(leaves).get_root() -} - -// These values are precomputed and we run tests to ensure that they -// are correct. The values themselves were computed from the cpp code. -// -// Would be good if we could use width since the compute_subtree -// algorithm uses depth. -pub fn calculate_empty_tree_root(depth: u64) -> Field { - if depth == 0 { - 0 - } else if depth == 1 { - 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed - } else if depth == 2 { - 0x21dbfd1d029bf447152fcf89e355c334610d1632436ba170f738107266a71550 - } else if depth == 3 { - 0x0bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb - } else if depth == 4 { - 0x06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d - } else if depth == 5 { - 0x03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa0 - } else if depth == 6 { - 0x15d28cad4c0736decea8997cb324cf0a0e0602f4d74472cd977bce2c8dd9923f - } else if depth == 7 { - 0x268ed1e1c94c3a45a14db4108bc306613a1c23fab68e0466a002dfb0a3f8d2ab - } else if depth == 8 { - 0x0cd8d5695bc2dde99dd531671f76f1482f14ddba8eeca7cb9686d4a62359c257 - } else if depth == 9 { - 0x047fbb7eb974155702149e58ea6ad91f4c6e953e693db35e953e250d8ceac9a9 - } else if depth == 10 { - 0x00c5ae2526e665e2c7c698c11a06098b7159f720606d50e7660deb55758b0b02 - } else { - assert(false, "depth should be between 0 and 10"); - 0 - } -} - -#[test] -fn test_merkle_root_interop_test() { - // This is a test to ensure that we match the cpp implementation. - // You can grep for `TEST_F(root_rollup_tests, noir_interop_test)` - // to find the test that matches this. - let root = calculate_subtree([1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]); - assert(0x17e8bb70a11d0c946345950879484d2f4f9fef397ff6adbfdec3baab2d41faab == root); - - let empty_root = calculate_subtree([0; 16]); - assert(0x06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d == empty_root); -} - -#[test] -fn test_empty_subroot() { - assert(calculate_empty_tree_root(0) == 0); - - let expected_empty_root_2 = calculate_subtree([0; 2]); - assert(calculate_empty_tree_root(1) == expected_empty_root_2); - - let expected_empty_root_4 = calculate_subtree([0; 4]); - assert(calculate_empty_tree_root(2) == expected_empty_root_4); - - let expected_empty_root_8 = calculate_subtree([0; 8]); - assert(calculate_empty_tree_root(3) == expected_empty_root_8); - - let expected_empty_root_16 = calculate_subtree([0; 16]); - assert(calculate_empty_tree_root(4) == expected_empty_root_16); - - let expected_empty_root_32 = calculate_subtree([0; 32]); - assert(calculate_empty_tree_root(5) == expected_empty_root_32); - - let expected_empty_root_64 = calculate_subtree([0; 64]); - assert(calculate_empty_tree_root(6) == expected_empty_root_64); - - let expected_empty_root_128 = calculate_subtree([0; 128]); - assert(calculate_empty_tree_root(7) == expected_empty_root_128); -} +mod membership; +mod merkle_tree; +mod root; + +use leaf_preimage::{IndexedTreeLeafPreimage, LeafPreimage}; +use membership::{ + assert_check_membership, assert_check_non_membership, check_membership, check_non_membership, + MembershipWitness +}; +use merkle_tree::MerkleTree; +use root::{calculate_empty_tree_root, calculate_subtree_root, root_from_sibling_path}; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/append_only_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/append_only_tree.nr index 18145d3d233..b1faf2c06c7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/append_only_tree.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/append_only_tree.nr @@ -1,6 +1,6 @@ use crate::{ abis::{append_only_tree_snapshot::AppendOnlyTreeSnapshot}, - hash::{assert_check_membership, root_from_sibling_path} + merkle_tree::{membership::assert_check_membership, root::root_from_sibling_path} }; pub fn insert_subtree_to_snapshot_tree( diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/indexed_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/indexed_tree.nr index 9c291900061..6cfc75baaf6 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/indexed_tree.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/indexed_tree.nr @@ -1,53 +1,12 @@ use crate::{ - abis::{append_only_tree_snapshot::AppendOnlyTreeSnapshot, membership_witness::MembershipWitness}, - hash::{assert_check_membership, root_from_sibling_path}, - merkle_tree::{calculate_subtree, calculate_empty_tree_root} + abis::{append_only_tree_snapshot::AppendOnlyTreeSnapshot}, + merkle_tree::{ + membership::{assert_check_membership, MembershipWitness}, + root::{calculate_subtree_root, calculate_empty_tree_root, root_from_sibling_path} +}, + traits::{Empty, Hash, is_empty}, utils::arrays::check_permutation }; -fn check_permutation( - original_array: [T; N], - sorted_array: [T; N], - indexes: [u64; N], - is_equal: fn(T, T) -> bool -) { - let mut seen_value = [false; N]; - for i in 0..N { - let index = indexes[i]; - let sorted_value = sorted_array[i]; - let original_value = original_array[index]; - assert(is_equal(sorted_value, original_value), "Invalid index"); - assert(!seen_value[index], "Duplicated index"); - seen_value[index] = true; - } -} - -#[test] -fn check_permutation_basic_test() { - let original_array = [1, 2, 3]; - let sorted_array = [3, 1, 2]; - let indexes = [2, 0, 1]; - let is_equal = |a: Field, b: Field| a == b; - check_permutation(original_array, sorted_array, indexes, is_equal); -} - -#[test(should_fail_with = "Duplicated index")] -fn check_permutation_duplicated_index() { - let original_array = [0, 1, 0]; - let sorted_array = [1, 0, 0]; - let indexes = [1, 0, 0]; - let is_equal = |a: Field, b: Field| a == b; - check_permutation(original_array, sorted_array, indexes, is_equal); -} - -#[test(should_fail_with = "Invalid index")] -fn check_permutation_invalid_index() { - let original_array = [0, 1, 2]; - let sorted_array = [1, 0, 0]; - let indexes = [1, 0, 2]; - let is_equal = |a: Field, b: Field| a == b; - check_permutation(original_array, sorted_array, indexes, is_equal); -} - pub fn batch_insert( start_snapshot: AppendOnlyTreeSnapshot, values_to_insert: [Value; SubtreeWidth], @@ -56,22 +15,14 @@ pub fn batch_insert; SubtreeWidth], - is_equal: fn(Value, Value) -> bool, - is_empty_value: fn(Value) -> bool, - hash_leaf: fn(Leaf) -> Field, is_valid_low_leaf: fn(Leaf, Value) -> bool, update_low_leaf: fn(Leaf, Value, u64) -> Leaf, build_insertion_leaf: fn(Value, Leaf) -> Leaf, _subtree_height: [Field; SubtreeHeight], _tree_height: [Field; TreeHeight] -) -> AppendOnlyTreeSnapshot { +) -> AppendOnlyTreeSnapshot where Value: Eq + Empty, Leaf: Hash { // A permutation to the values is provided to make the insertion use only one insertion strategy - check_permutation( - values_to_insert, - sorted_values, - sorted_values_indexes, - is_equal - ); + check_permutation(values_to_insert, sorted_values, sorted_values_indexes); // Now, update the existing leaves with the new leaves let mut current_tree_root = start_snapshot.root; @@ -80,7 +31,7 @@ pub fn batch_insert Field; fn as_leaf(self) -> Field; } + +trait IndexedTreeLeafPreimage { + fn get_key(self) -> Field; + fn get_next_key(self) -> Field; + fn as_leaf(self) -> Field; +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/membership.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/membership.nr new file mode 100644 index 00000000000..6fc8d91d13b --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/membership.nr @@ -0,0 +1,343 @@ +use crate::{merkle_tree::{leaf_preimage::IndexedTreeLeafPreimage, root::root_from_sibling_path}}; + +struct MembershipWitness { + leaf_index: Field, + sibling_path: [Field; N] +} + +pub fn check_membership(leaf: Field, index: Field, sibling_path: [Field; N], root: Field) -> bool { + let calculated_root = root_from_sibling_path(leaf, index, sibling_path); + calculated_root == root +} + +pub fn assert_check_membership(leaf: Field, index: Field, sibling_path: [Field; N], root: Field) { + assert(check_membership(leaf, index, sibling_path, root), "membership check failed"); +} + +struct NonMembershipCheckErrorCodeEnum { + NADA: u64, + IS_EMPTY: u64, + NOT_EXISTS: u64, + NOT_GREATER_THAN_LOW: u64, + NOT_LESS_THAN_NEXT: u64, +} + +global NonMembershipCheckErrorCode = NonMembershipCheckErrorCodeEnum { + NADA: 0, + IS_EMPTY: 1, + NOT_EXISTS: 2, + NOT_GREATER_THAN_LOW: 3, + NOT_LESS_THAN_NEXT: 4, +}; + +fn check_non_membership_internal( + key: Field, + low_leaf_preimage: LEAF_PREIMAGE, + low_leaf_membership_witness: MembershipWitness, + tree_root: Field +) -> u64 where + LEAF_PREIMAGE: IndexedTreeLeafPreimage { + let low_key = low_leaf_preimage.get_key(); + let next_key = low_leaf_preimage.get_next_key(); + let is_empty_leaf = (low_key == 0) & (next_key == 0); + + let low_leaf_exists = check_membership( + low_leaf_preimage.as_leaf(), + low_leaf_membership_witness.leaf_index, + low_leaf_membership_witness.sibling_path, + tree_root + ); + + if is_empty_leaf { + NonMembershipCheckErrorCode.IS_EMPTY + } else if !low_leaf_exists { + NonMembershipCheckErrorCode.NOT_EXISTS + } else if !low_key.lt(key) { + NonMembershipCheckErrorCode.NOT_GREATER_THAN_LOW + } else if !key.lt(next_key) & (next_key != 0) { + NonMembershipCheckErrorCode.NOT_LESS_THAN_NEXT + } else { + NonMembershipCheckErrorCode.NADA + } +} + +pub fn check_non_membership( + key: Field, + low_leaf_preimage: LEAF_PREIMAGE, + low_leaf_membership_witness: MembershipWitness, + tree_root: Field +) -> bool where + LEAF_PREIMAGE: IndexedTreeLeafPreimage { + let error = check_non_membership_internal(key, low_leaf_preimage, low_leaf_membership_witness, tree_root); + error == NonMembershipCheckErrorCode.NADA +} + +pub fn assert_check_non_membership( + key: Field, + low_leaf_preimage: LEAF_PREIMAGE, + low_leaf_membership_witness: MembershipWitness, + tree_root: Field +) where + LEAF_PREIMAGE: IndexedTreeLeafPreimage { + let error = check_non_membership_internal(key, low_leaf_preimage, low_leaf_membership_witness, tree_root); + if error != NonMembershipCheckErrorCode.NADA { + assert( + error != NonMembershipCheckErrorCode.IS_EMPTY, "Cannot check non membership against empty leaf" + ); + assert(error != NonMembershipCheckErrorCode.NOT_EXISTS, "Low leaf does not exist"); + assert( + error != NonMembershipCheckErrorCode.NOT_GREATER_THAN_LOW, "Key is not greater than the low leaf" + ); + assert( + error != NonMembershipCheckErrorCode.NOT_LESS_THAN_NEXT, "Key is not less than the next leaf" + ); + assert(false, "Unknown error"); + } +} + +mod tests { + use crate::{ + merkle_tree::{ + leaf_preimage::{IndexedTreeLeafPreimage, LeafPreimage}, + membership::{ + assert_check_membership, assert_check_non_membership, check_membership, check_non_membership, + MembershipWitness + } + }, + tests::merkle_tree_utils::NonEmptyMerkleTree + }; + use dep::std::hash::pedersen_hash; + + struct TestLeafPreimage { + value: Field, + next_value: Field, + } + + impl LeafPreimage for TestLeafPreimage { + fn get_key(self) -> Field { + self.value + } + + fn as_leaf(self) -> Field { + pedersen_hash([self.value]) + } + } + + impl IndexedTreeLeafPreimage for TestLeafPreimage { + fn get_key(self) -> Field { + self.value + } + + fn get_next_key(self) -> Field { + self.next_value + } + + fn as_leaf(self) -> Field { + pedersen_hash([self.value]) + } + } + + global leaf_preimages = [ + TestLeafPreimage { value: 20, next_value: 30 }, + TestLeafPreimage { value: 40, next_value: 0 }, + TestLeafPreimage { value: 10, next_value: 20 }, + TestLeafPreimage { value: 30, next_value: 40 }, + ]; + + fn build_tree() -> NonEmptyMerkleTree<4, 3, 1, 2> { + NonEmptyMerkleTree::new( + leaf_preimages.map(|leaf_preimage: TestLeafPreimage| leaf_preimage.as_leaf()), + [0; 3], + [0; 1], + [0; 2] + ) + } + + fn check_membership_at_index(leaf_index: Field, leaf: Field) -> bool { + let tree = build_tree(); + let tree_root = tree.get_root(); + + check_membership( + leaf, + leaf_index, + tree.get_sibling_path(leaf_index as u64), + tree_root + ) + } + + fn assert_check_membership_at_index(leaf_index: Field, leaf: Field) { + let tree = build_tree(); + let tree_root = tree.get_root(); + + assert_check_membership( + leaf, + leaf_index, + tree.get_sibling_path(leaf_index as u64), + tree_root + ); + } + + fn check_non_membership_at_index(low_leaf_index: u64, leaf: Field) -> bool { + let tree = build_tree(); + let tree_root = tree.get_root(); + let leaf_preimage = if low_leaf_index < leaf_preimages.len() { + leaf_preimages[low_leaf_index] + } else { + TestLeafPreimage { value: 0, next_value: 0 } + }; + + check_non_membership( + leaf, + leaf_preimage, + MembershipWitness { leaf_index: low_leaf_index as Field, sibling_path: tree.get_sibling_path(low_leaf_index) } , + tree_root + ) + } + + fn assert_check_non_membership_at_index(low_leaf_index: u64, leaf: Field) { + let tree = build_tree(); + let tree_root = tree.get_root(); + let leaf_preimage = if low_leaf_index < leaf_preimages.len() { + leaf_preimages[low_leaf_index] + } else { + TestLeafPreimage { value: 0, next_value: 0 } + }; + + assert_check_non_membership( + leaf, + leaf_preimage, + MembershipWitness { leaf_index: low_leaf_index as Field, sibling_path: tree.get_sibling_path(low_leaf_index) } , + tree_root + ); + } + + #[test] + fn test_check_membership() { + assert_eq(check_membership_at_index(0, leaf_preimages[0].as_leaf()), true); + assert_eq(check_membership_at_index(2, leaf_preimages[2].as_leaf()), true); + } + + #[test] + fn test_assert_check_membership() { + assert_check_membership_at_index(0, leaf_preimages[0].as_leaf()); + assert_check_membership_at_index(2, leaf_preimages[2].as_leaf()); + } + + #[test] + fn test_check_membership_false_wrong_leaf() { + assert_eq(check_membership_at_index(0, leaf_preimages[1].as_leaf()), false); + assert_eq(check_membership_at_index(2, leaf_preimages[0].as_leaf()), false); + } + + #[test(should_fail_with="membership check failed")] + fn test_assert_check_membership_failed_wrong_leaf() { + assert_check_membership_at_index(0, leaf_preimages[1].as_leaf()); + } + + #[test] + fn test_check_membership_false_wrong_root() { + let tree = build_tree(); + let tree_root = 56; + + let res = check_membership( + leaf_preimages[0].as_leaf(), + 0, + tree.get_sibling_path(0), + tree_root + ); + assert_eq(res, false); + } + + #[test(should_fail_with="membership check failed")] + fn test_assert_check_membership_false_wrong_root() { + let tree = build_tree(); + let tree_root = 56; + + assert_check_membership( + leaf_preimages[0].as_leaf(), + 0, + tree.get_sibling_path(0), + tree_root + ); + } + + #[test] + fn test_check_non_membership() { + assert_eq(check_non_membership_at_index(0, 25), true); + } + + #[test] + fn test_assert_check_non_membership() { + assert_check_non_membership_at_index(0, 25); + } + + #[test] + fn test_check_non_membership_greater_than_max() { + assert_eq(check_non_membership_at_index(1, 45), true); + } + + #[test] + fn test_assert_check_non_membership_greater_than_max() { + assert_check_non_membership_at_index(1, 45); + } + + #[test] + fn test_check_non_membership_false_empty_leaf() { + assert_eq(check_non_membership_at_index(4, 25), false); + } + + #[test(should_fail_with="Cannot check non membership against empty leaf")] + fn test_assert_check_non_membership_failed_empty_leaf() { + assert_check_non_membership_at_index(4, 25); + } + + #[test] + fn test_check_non_membership_false_wrong_low_leaf() { + assert_eq(check_non_membership_at_index(3, 25), false); + } + + #[test(should_fail_with="Key is not greater than the low leaf")] + fn test_assert_check_non_membership_failed_wrong_low_leaf() { + assert_check_non_membership_at_index(3, 25); + } + + #[test] + fn test_check_non_membership_false_wrong_next_key() { + assert_eq(check_non_membership_at_index(2, 25), false); + } + + #[test(should_fail_with="Key is not less than the next leaf")] + fn test_assert_check_non_membership_failed_wrong_next_key() { + assert_check_non_membership_at_index(2, 25); + } + + #[test] + fn test_check_non_membership_false_invalid_leaf() { + let tree = build_tree(); + let tree_root = tree.get_root(); + + let fake_leaf = TestLeafPreimage { value: 50, next_value: 60 }; + assert_eq( + check_non_membership( + 55, + fake_leaf, + MembershipWitness { leaf_index: 1, sibling_path: tree.get_sibling_path(1) } , + tree_root + ), false + ); + } + + #[test(should_fail_with="Low leaf does not exist")] + fn test_assert_check_non_membership_failed_invalid_leaf() { + let tree = build_tree(); + let tree_root = tree.get_root(); + + let fake_leaf = TestLeafPreimage { value: 50, next_value: 60 }; + assert_check_non_membership( + 55, + fake_leaf, + MembershipWitness { leaf_index: 1, sibling_path: tree.get_sibling_path(1) } , + tree_root + ); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/merkle_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/merkle_tree.nr new file mode 100644 index 00000000000..f1cacb956ac --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/merkle_tree.nr @@ -0,0 +1,31 @@ +struct MerkleTree { + leaves: [Field; N], + nodes: [Field; N], +} + +impl MerkleTree { + pub fn new(leaves: [Field; N]) -> Self { + let mut nodes = [0; N]; + + // We need one less node than leaves, but we cannot have computed array lengths + let total_nodes = N - 1; + let half_size = N / 2; + + // hash base layer + for i in 0..half_size { + nodes[i] = dep::std::hash::pedersen_hash([leaves[2*i], leaves[2*i+1]]); + } + + // hash the other layers + for i in 0..(total_nodes - half_size) { + nodes[half_size+i] = dep::std::hash::pedersen_hash([nodes[2*i], nodes[2*i+1]]); + } + + MerkleTree { leaves, nodes } + } + + fn get_root(self) -> Field { + self.nodes[N - 2] + } +} + diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/root.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/root.nr new file mode 100644 index 00000000000..e659261fbdd --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/root.nr @@ -0,0 +1,102 @@ +use crate::{hash::merkle_hash, merkle_tree::merkle_tree::MerkleTree}; + +// Calculate the Merkle tree root from the sibling path and leaf. +// +// The leaf is hashed with its sibling, and then the result is hashed +// with the next sibling etc in the path. The last hash is the root. +// +// TODO(David/Someone): The cpp code is using a uint256, whereas its +// TODO a bit simpler in Noir to just have a bit array. +// TODO: I'd generally like to avoid u256 for algorithms like +// this because it means we never even need to consider cases where +// the index is greater than p. +pub fn root_from_sibling_path(leaf: Field, leaf_index: Field, sibling_path: [Field; N]) -> Field { + let mut node = leaf; + let indices = leaf_index.to_le_bits(N); + + for i in 0..N { + let (hash_left, hash_right) = if indices[i] == 1 { + (sibling_path[i], node) + } else { + (node, sibling_path[i]) + }; + node = merkle_hash(hash_left, hash_right); + } + node +} + +pub fn calculate_subtree_root(leaves: [Field; N]) -> Field { + MerkleTree::new(leaves).get_root() +} + +// These values are precomputed and we run tests to ensure that they +// are correct. The values themselves were computed from the cpp code. +// +// Would be good if we could use width since the compute_subtree +// algorithm uses depth. +pub fn calculate_empty_tree_root(depth: u64) -> Field { + if depth == 0 { + 0 + } else if depth == 1 { + 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed + } else if depth == 2 { + 0x21dbfd1d029bf447152fcf89e355c334610d1632436ba170f738107266a71550 + } else if depth == 3 { + 0x0bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb + } else if depth == 4 { + 0x06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d + } else if depth == 5 { + 0x03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa0 + } else if depth == 6 { + 0x15d28cad4c0736decea8997cb324cf0a0e0602f4d74472cd977bce2c8dd9923f + } else if depth == 7 { + 0x268ed1e1c94c3a45a14db4108bc306613a1c23fab68e0466a002dfb0a3f8d2ab + } else if depth == 8 { + 0x0cd8d5695bc2dde99dd531671f76f1482f14ddba8eeca7cb9686d4a62359c257 + } else if depth == 9 { + 0x047fbb7eb974155702149e58ea6ad91f4c6e953e693db35e953e250d8ceac9a9 + } else if depth == 10 { + 0x00c5ae2526e665e2c7c698c11a06098b7159f720606d50e7660deb55758b0b02 + } else { + assert(false, "depth should be between 0 and 10"); + 0 + } +} + +#[test] +fn test_merkle_root_interop_test() { + // This is a test to ensure that we match the cpp implementation. + // You can grep for `TEST_F(root_rollup_tests, noir_interop_test)` + // to find the test that matches this. + let root = calculate_subtree_root([1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]); + assert(0x17e8bb70a11d0c946345950879484d2f4f9fef397ff6adbfdec3baab2d41faab == root); + + let empty_root = calculate_subtree_root([0; 16]); + assert(0x06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d == empty_root); +} + +#[test] +fn test_empty_subroot() { + assert(calculate_empty_tree_root(0) == 0); + + let expected_empty_root_2 = calculate_subtree_root([0; 2]); + assert(calculate_empty_tree_root(1) == expected_empty_root_2); + + let expected_empty_root_4 = calculate_subtree_root([0; 4]); + assert(calculate_empty_tree_root(2) == expected_empty_root_4); + + let expected_empty_root_8 = calculate_subtree_root([0; 8]); + assert(calculate_empty_tree_root(3) == expected_empty_root_8); + + let expected_empty_root_16 = calculate_subtree_root([0; 16]); + assert(calculate_empty_tree_root(4) == expected_empty_root_16); + + let expected_empty_root_32 = calculate_subtree_root([0; 32]); + assert(calculate_empty_tree_root(5) == expected_empty_root_32); + + let expected_empty_root_64 = calculate_subtree_root([0; 64]); + assert(calculate_empty_tree_root(6) == expected_empty_root_64); + + let expected_empty_root_128 = calculate_subtree_root([0; 128]); + assert(calculate_empty_tree_root(7) == expected_empty_root_128); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr b/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr index 245294969c0..10761f02f22 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr @@ -6,7 +6,6 @@ use crate::{ struct PartialStateReference { note_hash_tree: AppendOnlyTreeSnapshot, nullifier_tree: AppendOnlyTreeSnapshot, - contract_tree: AppendOnlyTreeSnapshot, public_data_tree: AppendOnlyTreeSnapshot, } @@ -14,7 +13,6 @@ impl Eq for PartialStateReference { fn eq(self, other: PartialStateReference) -> bool { self.note_hash_tree.eq(other.note_hash_tree) & self.nullifier_tree.eq(other.nullifier_tree) & - self.contract_tree.eq(other.contract_tree) & self.public_data_tree.eq(other.public_data_tree) } } @@ -23,16 +21,13 @@ impl Serialize for PartialStateReference { fn serialize(self) -> [Field; PARTIAL_STATE_REFERENCE_LENGTH] { let serialized_note_hash_tree = self.note_hash_tree.serialize(); let serialized_nullifier_tree = self.nullifier_tree.serialize(); - let serialized_contract_tree = self.contract_tree.serialize(); let serialized_public_data_tree = self.public_data_tree.serialize(); [ - serialized_note_hash_tree[0], + serialized_note_hash_tree[0], serialized_note_hash_tree[1], serialized_nullifier_tree[0], serialized_nullifier_tree[1], - serialized_contract_tree[0], - serialized_contract_tree[1], serialized_public_data_tree[0], serialized_public_data_tree[1], ] @@ -48,11 +43,8 @@ impl Deserialize for PartialStateReference { nullifier_tree: AppendOnlyTreeSnapshot::deserialize( [serialized[2], serialized[3]] ), - contract_tree: AppendOnlyTreeSnapshot::deserialize( - [serialized[4], serialized[5]] - ), public_data_tree: AppendOnlyTreeSnapshot::deserialize( - [serialized[6], serialized[7]] + [serialized[4], serialized[5]] ), } } @@ -63,7 +55,6 @@ impl Empty for PartialStateReference { Self { note_hash_tree: AppendOnlyTreeSnapshot::zero(), nullifier_tree: AppendOnlyTreeSnapshot::zero(), - contract_tree: AppendOnlyTreeSnapshot::zero(), public_data_tree: AppendOnlyTreeSnapshot::zero(), } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests.nr index c02eefc2353..77f7f32bc6d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests.nr @@ -6,3 +6,4 @@ mod private_call_data_builder; mod private_circuit_public_inputs_builder; mod public_call_data_builder; mod public_circuit_public_inputs_builder; +mod sort; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr index 1a39d338404..37f30d7216c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr @@ -1,5 +1,4 @@ mod contract_functions; -mod contract_tree; mod contracts; mod note_hash_tree; mod note_hash_read_requests; @@ -46,10 +45,6 @@ global HEADER = Header { next_available_leaf_index: 0, // TODO: should this be populated? }, nullifier_tree: empty_append_only_tree(), - contract_tree: AppendOnlyTreeSnapshot { - root: fixtures::contract_tree::ROOT, - next_available_leaf_index: 0, // TODO: should this be populated? - }, public_data_tree: empty_append_only_tree() } }, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contract_functions.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contract_functions.nr index ecee58edac1..2b4692bcaa2 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contract_functions.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contract_functions.nr @@ -10,18 +10,6 @@ struct ContractFunction { membership_witness: FunctionLeafMembershipWitness, } -global default_constructor = ContractFunction { - data: FunctionData { - selector: FunctionSelector { inner: 999 }, - is_internal: false, - is_private: true, - is_constructor: true, - }, - vk_hash: 0, - acir_hash: 43214321, - membership_witness: dep::std::unsafe::zeroed(), -}; - // sibling_path taken from __snapshots__/noir_test_gen.test.ts.snap global default_private_function = ContractFunction { data: FunctionData { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contract_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contract_tree.nr deleted file mode 100644 index 867f28adbe1..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contract_tree.nr +++ /dev/null @@ -1,40 +0,0 @@ -// Constants taken from __snapshots__/noir_test_gen.test.ts.snap -global ROOT = 0x2d541f5813387a5f4b32d1b3b103447ae142927457a60d00c779a5eeaead471d; -global SIBLING_PATHS = [ - [ - 0x0c58a1ae52142f3369f9c46e6717bbef5aa55f9fc0e901a7d8cc860d9467021e, - 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed, - 0x21dbfd1d029bf447152fcf89e355c334610d1632436ba170f738107266a71550, - 0x0bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb, - 0x06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d, - 0x03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa0, - 0x15d28cad4c0736decea8997cb324cf0a0e0602f4d74472cd977bce2c8dd9923f, - 0x268ed1e1c94c3a45a14db4108bc306613a1c23fab68e0466a002dfb0a3f8d2ab, - 0x0cd8d5695bc2dde99dd531671f76f1482f14ddba8eeca7cb9686d4a62359c257, - 0x047fbb7eb974155702149e58ea6ad91f4c6e953e693db35e953e250d8ceac9a9, - 0x00c5ae2526e665e2c7c698c11a06098b7159f720606d50e7660deb55758b0b02, - 0x2ced19489ab456b8b6c424594cdbbae59c36dfdd4c4621c4032da2d8a9674be5, - 0x1df5a245ffc1da14b46fe56a605f2a47b1cff1592bab4f66cfe5dfe990af6ab5, - 0x2871d090615d14eadb52228c635c90e0adf31176f0814f6525c23e7d7b318c93, - 0x1a2b85ff013d4b2b25074297c7e44aa61f4836d0862b36db2e6ce2b5542f9ea9, - 0x177b9a10bbee32f77c719c6f8d071a18476cbeb021e155c642bbf93c716ce943, - ], - [ - 0x1ec6c50dc972349d72602ec6887f7accd3174d912ea58629447937865cb88a4d, - 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed, - 0x21dbfd1d029bf447152fcf89e355c334610d1632436ba170f738107266a71550, - 0x0bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb, - 0x06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d, - 0x03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa0, - 0x15d28cad4c0736decea8997cb324cf0a0e0602f4d74472cd977bce2c8dd9923f, - 0x268ed1e1c94c3a45a14db4108bc306613a1c23fab68e0466a002dfb0a3f8d2ab, - 0x0cd8d5695bc2dde99dd531671f76f1482f14ddba8eeca7cb9686d4a62359c257, - 0x047fbb7eb974155702149e58ea6ad91f4c6e953e693db35e953e250d8ceac9a9, - 0x00c5ae2526e665e2c7c698c11a06098b7159f720606d50e7660deb55758b0b02, - 0x2ced19489ab456b8b6c424594cdbbae59c36dfdd4c4621c4032da2d8a9674be5, - 0x1df5a245ffc1da14b46fe56a605f2a47b1cff1592bab4f66cfe5dfe990af6ab5, - 0x2871d090615d14eadb52228c635c90e0adf31176f0814f6525c23e7d7b318c93, - 0x1a2b85ff013d4b2b25074297c7e44aa61f4836d0862b36db2e6ce2b5542f9ea9, - 0x177b9a10bbee32f77c719c6f8d071a18476cbeb021e155c642bbf93c716ce943, - ], -]; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr index 7d62ee738f5..96166f5be41 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr @@ -1,4 +1,3 @@ -use crate::abis::membership_witness::ContractLeafMembershipWitness; use crate::address::{AztecAddress, EthAddress, PublicKeysHash, SaltedInitializationHash, PartialAddress}; use crate::tests::fixtures; use crate::contract_class_id::ContractClassId; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/kernel_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/kernel_data_builder.nr index ef17cc8e565..50769bbfbb4 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/kernel_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/kernel_data_builder.nr @@ -54,7 +54,7 @@ impl PreviousKernelDataBuilder { end.new_nullifiers.push(tx_nullifier); } - let tx_context = build_tx_context(false, 0); + let tx_context = build_tx_context(); PreviousKernelDataBuilder { contract_address: fixtures::contracts::parent_contract.address, @@ -146,6 +146,16 @@ impl PreviousKernelDataBuilder { value_offset + nullifier_index as Field } + pub fn add_nullifier(&mut self, unsiloed_nullifier: Field) { + let value = silo_nullifier(self.storage_contract_address, unsiloed_nullifier); + self.end.new_nullifiers.push(SideEffectLinkedToNoteHash { value, note_hash: 0, counter: self.next_sideffect_counter() }); + } + + pub fn add_nullifier_non_revertible(&mut self, unsiloed_nullifier: Field) { + let value = silo_nullifier(self.storage_contract_address, unsiloed_nullifier); + self.end_non_revertible.new_nullifiers.push(SideEffectLinkedToNoteHash { value, note_hash: 0, counter: self.next_sideffect_counter() }); + } + pub fn append_new_nullifiers_from_private(&mut self, num_extra_nullifier: u64) { // in private kernel, the nullifiers have not yet been partitioned // (that is part of the job of the private kernel tail) @@ -154,13 +164,7 @@ impl PreviousKernelDataBuilder { for i in 0..MAX_NEW_NULLIFIERS_PER_TX { if i < num_extra_nullifier { let mock_value = self.get_mock_nullifier_value(index_offset + i); - self.end.new_nullifiers.push( - SideEffectLinkedToNoteHash { - value: silo_nullifier(self.storage_contract_address, mock_value), - note_hash: 0, - counter: self.next_sideffect_counter() - } - ); + self.add_nullifier(mock_value); } } } @@ -170,13 +174,7 @@ impl PreviousKernelDataBuilder { for i in 0..MAX_NEW_NULLIFIERS_PER_TX { if i < num_extra_nullifier { let mock_value = self.get_mock_nullifier_value(index_offset + i); - self.end.new_nullifiers.push( - SideEffectLinkedToNoteHash { - value: silo_nullifier(self.storage_contract_address, mock_value), - note_hash: 0, - counter: self.next_sideffect_counter() - } - ); + self.add_nullifier(mock_value); } } } @@ -186,13 +184,7 @@ impl PreviousKernelDataBuilder { for i in 0..MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX { if i < num_extra_nullifier { let mock_value = self.get_mock_nullifier_value_non_revertible(index_offset + i); - self.end_non_revertible.new_nullifiers.push( - SideEffectLinkedToNoteHash { - value: silo_nullifier(self.storage_contract_address, mock_value), - note_hash: 0, - counter: self.next_sideffect_counter() - } - ); + self.add_nullifier_non_revertible(mock_value); } } } @@ -221,6 +213,15 @@ impl PreviousKernelDataBuilder { read_request_index } + pub fn add_non_existent_read_request_for_nullifier(&mut self, unsiloed_nullifier: Field) { + let read_request = ReadRequestContext { + value: unsiloed_nullifier, + counter: self.next_sideffect_counter(), + contract_address: self.storage_contract_address + }; + self.end_non_revertible.nullifier_non_existent_read_requests.push(read_request); + } + // snapshot the side effects // this is useful in the private tail circuit to test side effect splitting pub fn capture_min_revertible_side_effect_counter(&mut self) { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr index f86b5767eeb..19cf0d270c8 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr @@ -2,7 +2,7 @@ use crate::{ abis::{ call_request::{CallerContext, CallRequest}, private_call_stack_item::PrivateCallStackItem, function_data::FunctionData, - membership_witness::{ContractLeafMembershipWitness, FunctionLeafMembershipWitness, NoteHashReadRequestMembershipWitness}, + membership_witness::{FunctionLeafMembershipWitness, NoteHashReadRequestMembershipWitness}, private_circuit_public_inputs::{PrivateCircuitPublicInputs}, private_kernel::private_call_data::PrivateCallData }, @@ -41,15 +41,11 @@ struct PrivateCallDataBuilder { } impl PrivateCallDataBuilder { - pub fn new(is_constructor: bool) -> Self { - let public_inputs = PrivateCircuitPublicInputsBuilder::new(is_constructor); + pub fn new() -> Self { + let public_inputs = PrivateCircuitPublicInputsBuilder::new(); let contract_data = fixtures::contracts::default_contract; - let contract_function = if is_constructor { - fixtures::contract_functions::default_constructor - } else { - fixtures::contract_functions::default_private_function - }; + let contract_function = fixtures::contract_functions::default_private_function; let function_data = contract_function.data; PrivateCallDataBuilder { @@ -96,10 +92,7 @@ impl PrivateCallDataBuilder { } pub fn build_tx_request(self) -> TxRequest { - let tx_context = build_tx_context( - self.public_inputs.call_context.is_contract_deployment, - self.public_inputs.args_hash - ); + let tx_context = build_tx_context(); TxRequest { origin: self.contract_address, args_hash: self.public_inputs.args_hash, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr index 2f23306a1c0..46df32f7940 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr @@ -4,11 +4,8 @@ use crate::{ private_circuit_public_inputs::PrivateCircuitPublicInputs, read_request::ReadRequest, side_effect::{SideEffect, SideEffectLinkedToNoteHash} }, - address::{AztecAddress, compute_initialization_hash}, - contrakt::contract_deployment_data::ContractDeploymentData, - hash::{compute_constructor_hash, hash_args}, header::Header, - messaging::l2_to_l1_message::L2ToL1Message, - tests::{fixtures, testing_harness::build_contract_deployment_data} + address::{AztecAddress, compute_initialization_hash}, hash::{compute_constructor_hash, hash_args}, + header::Header, messaging::l2_to_l1_message::L2ToL1Message, tests::fixtures }; use crate::constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, @@ -45,14 +42,12 @@ struct PrivateCircuitPublicInputsBuilder { historical_header: Header, - contract_deployment_data: ContractDeploymentData, - chain_id: Field, version: Field, } impl PrivateCircuitPublicInputsBuilder { - pub fn new(is_constructor: bool) -> Self { + pub fn new() -> Self { let mut public_inputs: PrivateCircuitPublicInputsBuilder = dep::std::unsafe::zeroed(); let args_hash = hash_args([]); @@ -60,28 +55,10 @@ impl PrivateCircuitPublicInputsBuilder { let contract_data = fixtures::contracts::default_contract; let portal_contract_address = contract_data.portal_contract_address; - let contract_function = if is_constructor { - fixtures::contract_functions::default_constructor - } else { - fixtures::contract_functions::default_private_function - }; + let contract_function = fixtures::contract_functions::default_private_function; let function_data = contract_function.data; - let contract_deployment_data = build_contract_deployment_data(is_constructor, args_hash); - - let contract_address = if is_constructor { - let constructor = fixtures::contract_functions::default_constructor; - let initialization_hash = compute_initialization_hash(constructor.data.selector.to_field(), args_hash); - AztecAddress::compute_from_public_key( - contract_deployment_data.public_key, - contract_deployment_data.contract_class_id, - contract_deployment_data.contract_address_salt, - initialization_hash, - portal_contract_address - ) - } else { - contract_data.address - }; + let contract_address = contract_data.address; let call_context = CallContext { msg_sender: fixtures::contracts::parent_contract.address, @@ -90,12 +67,10 @@ impl PrivateCircuitPublicInputsBuilder { function_selector: function_data.selector, is_delegate_call: false, is_static_call: false, - is_contract_deployment: is_constructor, start_side_effect_counter: 0 }; public_inputs.call_context = call_context; public_inputs.args_hash = args_hash; - public_inputs.contract_deployment_data = contract_deployment_data; public_inputs.historical_header = fixtures::HEADER; public_inputs.chain_id = 0; public_inputs.version = 1; @@ -123,7 +98,6 @@ impl PrivateCircuitPublicInputsBuilder { encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, historical_header: self.historical_header, - contract_deployment_data: self.contract_deployment_data, chain_id: self.chain_id, version: self.version } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr index 9350c46ce10..264fc98b614 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr @@ -42,7 +42,6 @@ impl PublicCallDataBuilder { function_selector: function_data.selector, is_delegate_call: false, is_static_call: false, - is_contract_deployment: false, start_side_effect_counter: 0, // needed? }; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr index ae74ec6bb73..d4bf5c3d294 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr @@ -9,9 +9,9 @@ use crate::{ }; use crate::constants::{ MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, - MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, - MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, NUM_FIELDS_PER_SHA256, - RETURN_VALUES_LENGTH + MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, NUM_FIELDS_PER_SHA256, RETURN_VALUES_LENGTH }; struct PublicCircuitPublicInputsBuilder { @@ -19,6 +19,7 @@ struct PublicCircuitPublicInputsBuilder { args_hash: Field, return_values: BoundedVec, nullifier_read_requests: BoundedVec, + nullifier_non_existent_read_requests: BoundedVec, contract_storage_update_requests: BoundedVec, contract_storage_reads: BoundedVec, public_call_stack_hashes: BoundedVec, @@ -46,6 +47,7 @@ impl PublicCircuitPublicInputsBuilder { args_hash: self.args_hash, return_values: self.return_values.storage, nullifier_read_requests: self.nullifier_read_requests.storage, + nullifier_non_existent_read_requests: self.nullifier_non_existent_read_requests.storage, contract_storage_update_requests: self.contract_storage_update_requests.storage, contract_storage_reads: self.contract_storage_reads.storage, public_call_stack_hashes: self.public_call_stack_hashes.storage, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/sort.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/sort.nr new file mode 100644 index 00000000000..d067eb1a2d9 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/sort.nr @@ -0,0 +1,87 @@ +use crate::traits::{Empty, is_empty}; + +struct SortedTuple { + value: T, + original_index: u64, +} + +pub fn sort_high_to_low( + values: [T; N], + is_less_than: fn(T, T) -> bool +) -> [SortedTuple; N] where T: Eq { + let mut sorted_tuples = [SortedTuple { value: values[0], original_index: 0 }; N]; + + for i in 0..N { + sorted_tuples[i] = SortedTuple { + value: values[i], + original_index: i, + }; + } + + sorted_tuples.sort_via(|a: SortedTuple, b: SortedTuple| (b.value == a.value) | is_less_than(b.value, a.value)) +} + +struct SortedResult { + sorted_array: [T; N], + sorted_index_hints: [u64; N], +} + +pub fn sort_get_sorted_hints( + values: [T; N], + ordering: fn(T, T) -> bool +) -> SortedResult where T: Eq + Empty { + let mut tuples = [SortedTuple { value: values[0], original_index: 0 }; N]; + for i in 0..N { + tuples[i] = SortedTuple { + value: values[i], + original_index: i, + }; + } + + let sorted_tuples = tuples.sort_via( + |a: SortedTuple, b: SortedTuple| is_empty(b.value) | (!is_empty(a.value) & !is_empty(b.value) & ordering(a.value, b.value)) + ); + + let sorted_array = sorted_tuples.map(|t: SortedTuple| t.value); + let mut sorted_index_hints = [0; N]; + for i in 0..N { + if !is_empty(sorted_tuples[i].value) { + let original_index = sorted_tuples[i].original_index; + sorted_index_hints[original_index] = i; + } + } + + SortedResult { sorted_array, sorted_index_hints } +} + +#[test] +fn sort_get_sorted_hints_asc_non_padded() { + let values = [40, 60, 20, 50]; + let res = sort_get_sorted_hints(values, |a: Field, b: Field| a.lt(b)); + assert_eq(res.sorted_array, [20, 40, 50, 60]); + assert_eq(res.sorted_index_hints, [1, 3, 0, 2]); +} + +#[test] +fn sort_get_sorted_hints_desc_non_padded() { + let values = [40, 20, 60, 50]; + let res = sort_get_sorted_hints(values, |a: Field, b: Field| b.lt(a)); + assert_eq(res.sorted_array, [60, 50, 40, 20]); + assert_eq(res.sorted_index_hints, [2, 3, 0, 1]); +} + +#[test] +fn sort_get_sorted_hints_asc_padded() { + let values = [40, 60, 20, 50, 0, 0]; + let res = sort_get_sorted_hints(values, |a: Field, b: Field| a.lt(b)); + assert_eq(res.sorted_array, [20, 40, 50, 60, 0, 0]); + assert_eq(res.sorted_index_hints, [1, 3, 0, 2, 0, 0]); +} + +#[test] +fn sort_get_sorted_hints_desc_padded() { + let values = [40, 20, 60, 50, 0, 0]; + let res = sort_get_sorted_hints(values, |a: Field, b: Field| b.lt(a)); + assert_eq(res.sorted_array, [60, 50, 40, 20, 0, 0]); + assert_eq(res.sorted_index_hints, [2, 3, 0, 1, 0, 0]); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/testing_harness.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/testing_harness.nr index 08afb981fba..9f03462c7d9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/testing_harness.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/testing_harness.nr @@ -1,32 +1,5 @@ -use crate::{ - contrakt::contract_deployment_data::ContractDeploymentData, tests::fixtures, - transaction::tx_context::TxContext, address::compute_initialization_hash -}; +use crate::{tests::fixtures, transaction::tx_context::TxContext, address::compute_initialization_hash}; -pub fn build_contract_deployment_data(is_constructor: bool, args_hash: Field) -> ContractDeploymentData { - let mut contract_deployment_data: ContractDeploymentData = dep::std::unsafe::zeroed(); - if is_constructor { - let contract_data = fixtures::contracts::default_contract; - let constructor = fixtures::contract_functions::default_constructor; - contract_deployment_data = ContractDeploymentData { - public_key: fixtures::PUBLIC_KEY, - initialization_hash: compute_initialization_hash(constructor.data.selector.to_field(), args_hash), - contract_class_id: contract_data.contract_class_id, - contract_address_salt: contract_data.contract_address_salt, - portal_contract_address: contract_data.portal_contract_address, - }; - } - contract_deployment_data -} - -pub fn build_tx_context(is_constructor: bool, args_hash: Field) -> TxContext { - let contract_deployment_data = build_contract_deployment_data(is_constructor, args_hash); - TxContext { - is_fee_payment_tx: false, - is_rebate_payment_tx: false, - is_contract_deployment_tx: is_constructor, - contract_deployment_data, - chain_id: 1, - version: 0 - } +pub fn build_tx_context() -> TxContext { + TxContext { is_fee_payment_tx: false, is_rebate_payment_tx: false, chain_id: 1, version: 0 } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr b/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr index d33ee842c3a..a0655fa6250 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr @@ -1,15 +1,11 @@ use crate::{ - constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_DATA_LENGTH}, - contrakt::contract_deployment_data::ContractDeploymentData, hash::pedersen_hash, + constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_DATA_LENGTH}, hash::pedersen_hash, traits::{Deserialize, Hash, Serialize}, utils::reader::Reader }; struct TxContext { is_fee_payment_tx : bool, is_rebate_payment_tx : bool, - is_contract_deployment_tx : bool, - - contract_deployment_data : ContractDeploymentData, chain_id : Field, version : Field, @@ -19,8 +15,6 @@ impl Eq for TxContext { fn eq(self, other: Self) -> bool { (self.is_fee_payment_tx == other.is_fee_payment_tx) & (self.is_rebate_payment_tx == other.is_rebate_payment_tx) & - (self.is_contract_deployment_tx == other.is_contract_deployment_tx) & - self.contract_deployment_data.eq(other.contract_deployment_data) & (self.chain_id == other.chain_id) & (self.version == other.version) } @@ -32,8 +26,6 @@ impl Serialize for TxContext { fields.push(self.is_fee_payment_tx as Field); fields.push(self.is_rebate_payment_tx as Field); - fields.push(self.is_contract_deployment_tx as Field); - fields.extend_from_array(self.contract_deployment_data.serialize()); fields.push(self.chain_id); fields.push(self.version); @@ -51,8 +43,6 @@ impl Deserialize for TxContext { let context = Self { is_fee_payment_tx: reader.read() as bool, is_rebate_payment_tx: reader.read() as bool, - is_contract_deployment_tx: reader.read() as bool, - contract_deployment_data: reader.read_struct(ContractDeploymentData::deserialize), chain_id: reader.read(), version: reader.read(), }; @@ -81,6 +71,7 @@ fn empty_hash() { let inputs: TxContext = dep::std::unsafe::zeroed(); let hash = inputs.hash(); - // Value from contract_deployment_data.test.ts "computes empty item hash" test - assert_eq(hash, 0x2e7ff14389eef3dc51597529149e01b49cb33829f7089438c8c145c8f352c17b); + // Value from tx_context.test.ts "computes empty item hash" test + let test_data_empty_hash = 0x200569267c0f73ac89aaa414239398db9445dd4ad3a8cf37015cd55b8d4c5e8d; + assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr index 17b604530f4..ef9fad8bfb5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr @@ -62,8 +62,7 @@ mod tests { use crate::{ abis::{function_selector::FunctionSelector, function_data::FunctionData}, address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, - contrakt::contract_deployment_data::ContractDeploymentData, grumpkin_point::GrumpkinPoint, - transaction::{tx_request::TxRequest, tx_context::TxContext} + grumpkin_point::GrumpkinPoint, transaction::{tx_request::TxRequest, tx_context::TxContext} }; #[test] @@ -80,23 +79,11 @@ mod tests { let tx_request = TxRequest { origin: AztecAddress::from_field(1), args_hash: 3, - tx_context: TxContext { - is_fee_payment_tx: false, - is_rebate_payment_tx: false, - is_contract_deployment_tx: true, - contract_deployment_data: ContractDeploymentData { - public_key: GrumpkinPoint { x: 1, y: 2 }, - initialization_hash: 1, - contract_class_id: ContractClassId::from_field(2), - contract_address_salt: 3, - portal_contract_address: EthAddress::from_field(1) - }, - chain_id: 0, - version: 0 - }, + tx_context: TxContext { is_fee_payment_tx: false, is_rebate_payment_tx: false, chain_id: 0, version: 0 }, function_data: FunctionData { selector: FunctionSelector::from_u32(2), is_internal: false, is_private: true, is_constructor: true } }; // Value from tx_request.test.ts "compute hash" test - assert(tx_request.hash() == 0x05e3f67a5e787faf63c85c28169a9d616b594c9799d9785b4f167d9cd7a71e9e); + let test_data_tx_request_hash = 0x0ab4eaebf540be2999b50051b3c272b5bf7be23d59233b6d453272a42c3c08e5; + assert(tx_request.hash() == test_data_tx_request_hash); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr index ec5e186d412..73af12d2969 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr @@ -57,6 +57,16 @@ pub fn array_eq(array: [T; N], expected: [T; S]) -> bool where T: Empty eq } +pub fn find_index(array: [T; N], find: fn[Env](T) -> bool) -> u64 { + let mut index = N; + for i in 0..N { + if (index == N) & find(array[i]) { + index = i; + } + } + index +} + pub fn array_cp(array: [T; N]) -> [T; S] where T: Empty { let mut result: [T; S] = [T::empty(); S]; for i in 0..S { @@ -102,6 +112,45 @@ pub fn array_merge(array1: [T; N], array2: [T; N]) -> [T; N] where T: Empt result } +pub fn check_permutation( + original_array: [T; N], + permuted_array: [T; N], + original_indexes: [u64; N] +) where T: Eq + Empty { + let mut seen_value = [false; N]; + for i in 0..N { + let index = original_indexes[i]; + let original_value = original_array[index]; + assert(permuted_array[i].eq(original_value), "Invalid index"); + assert(!seen_value[index], "Duplicated index"); + seen_value[index] = true; + } +} + +pub fn assert_sorted_array( + original_array: [T; N], + sorted_array: [T; N], + sorted_indexes: [u64; N], + ordering: fn[Env](T, T) -> bool +) where T: Eq + Empty { + let mut seen_empty = false; + for i in 0..N { + let original_value = original_array[i]; + if is_empty(original_value) { + seen_empty = true; + assert(is_empty(sorted_array[i]), "Empty values must not be mixed with sorted values"); + } else { + assert(!seen_empty, "Empty values must be padded to the right"); + + let index = sorted_indexes[i]; + assert(sorted_array[index].eq(original_value), "Invalid index"); + if i != 0 { + assert(ordering(sorted_array[i - 1], sorted_array[i]), "Values not sorted"); + } + } + } +} + #[test] fn smoke_validate_array() { let valid_array = []; @@ -147,3 +196,107 @@ fn test_array_length() { assert_eq(array_length([123, 0, 456]), 1); assert_eq(array_length([0, 123, 0, 456]), 0); } + +#[test] +fn find_index_greater_than_min() { + let values = [10, 20, 30, 40]; + let min = 22; + let index = find_index(values, |v: Field| min.lt(v)); + assert_eq(index, 2); +} + +#[test] +fn find_index_not_found() { + let values = [10, 20, 30, 40]; + let min = 100; + let index = find_index(values, |v: Field| min.lt(v)); + assert_eq(index, 4); +} + +#[test] +fn check_permutation_basic_test() { + let original_array = [1, 2, 3]; + let permuted_array = [3, 1, 2]; + let indexes = [2, 0, 1]; + check_permutation(original_array, permuted_array, indexes); +} + +#[test(should_fail_with = "Duplicated index")] +fn check_permutation_duplicated_index() { + let original_array = [0, 1, 0]; + let permuted_array = [1, 0, 0]; + let indexes = [1, 0, 0]; + check_permutation(original_array, permuted_array, indexes); +} + +#[test(should_fail_with = "Invalid index")] +fn check_permutation_invalid_index() { + let original_array = [0, 1, 2]; + let permuted_array = [1, 0, 0]; + let indexes = [1, 0, 2]; + check_permutation(original_array, permuted_array, indexes); +} + +#[test] +fn assert_sorted_array_asc() { + let original = [30, 20, 90, 50, 0, 0]; + let sorted = [20, 30, 50, 90, 0, 0]; + let indexes = [1, 0, 3, 2, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); +} + +#[test] +fn assert_sorted_array_desc() { + let original = [30, 20, 90, 50, 0, 0]; + let sorted = [90, 50, 30, 20, 0, 0]; + let indexes = [2, 3, 0, 1, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| b.lt(a)); +} + +#[test] +fn assert_sorted_array_all_empty() { + let original = [0, 0, 0, 0, 0, 0]; + let sorted = [0, 0, 0, 0, 0, 0]; + let indexes = [0, 0, 0, 0, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); +} + +#[test(should_fail_with="Values not sorted")] +fn assert_sorted_array_failed_ordering() { + let original = [30, 20, 90, 50, 0, 0]; + let sorted = [20, 30, 90, 50, 0, 0]; + let indexes = [1, 0, 2, 3, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); +} + +#[test(should_fail_with="Values not sorted")] +fn assert_sorted_array_failed_misplaced_sorted() { + let original = [30, 20, 90, 50, 0, 0]; + let sorted = [20, 30, 50, 0, 0, 90]; + let indexes = [1, 0, 5, 2, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); +} + +#[test(should_fail_with="Invalid index")] +fn assert_sorted_array_failed_wrong_index() { + let original = [30, 20, 90, 50, 0, 0]; + let sorted = [20, 30, 50, 90, 0, 0]; + let indexes = [1, 1, 2, 3, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); +} + +#[test(should_fail_with="Empty values must be padded to the right")] +fn assert_sorted_array_failed_not_padded() { + let original = [30, 20, 90, 0, 50, 0]; + let sorted = [20, 30, 90, 0, 0, 0]; + let indexes = [1, 0, 2, 0, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); +} + +#[test(should_fail_with="Empty values must not be mixed with sorted values")] +fn assert_sorted_array_failed_mixed_empty() { + let original = [30, 20, 90, 0, 0, 0]; + let sorted = [20, 30, 90, 0, 0, 10]; + let indexes = [1, 0, 2, 0, 0, 0]; + assert_sorted_array(original, sorted, indexes, |a: Field, b: Field| a.lt(b)); +} diff --git a/noir/noir-repo/.github/JS_PUBLISH_FAILED.md b/noir/noir-repo/.github/JS_PUBLISH_FAILED.md index 5b9f79aac1f..9adba2776c8 100644 --- a/noir/noir-repo/.github/JS_PUBLISH_FAILED.md +++ b/noir/noir-repo/.github/JS_PUBLISH_FAILED.md @@ -1,6 +1,6 @@ --- title: "JS packages failed to publish" -assignees: TomAFrench kevaundray savio-sou +assignees: TomAFrench kevaundray Savio-Sou labels: js --- diff --git a/noir/noir-repo/.github/workflows/publish-es-packages.yml b/noir/noir-repo/.github/workflows/publish-es-packages.yml index f72a97b2684..470db3b78f7 100644 --- a/noir/noir-repo/.github/workflows/publish-es-packages.yml +++ b/noir/noir-repo/.github/workflows/publish-es-packages.yml @@ -20,7 +20,9 @@ jobs: steps: - name: Checkout Noir repo uses: actions/checkout@v4 - + with: + ref: ${{ inputs.noir-ref }} + - name: Setup toolchain uses: dtolnay/rust-toolchain@1.73.0 @@ -87,6 +89,8 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v4 + with: + ref: ${{ inputs.noir-ref }} - name: Setup toolchain uses: dtolnay/rust-toolchain@1.73.0 @@ -164,4 +168,4 @@ jobs: WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} with: update_existing: true - filename: .github/JS_PUBLISH_FAILED.md \ No newline at end of file + filename: .github/JS_PUBLISH_FAILED.md diff --git a/noir/noir-repo/.release-please-manifest.json b/noir/noir-repo/.release-please-manifest.json index 8916585d7f1..b38234ca0b9 100644 --- a/noir/noir-repo/.release-please-manifest.json +++ b/noir/noir-repo/.release-please-manifest.json @@ -1,4 +1,4 @@ { - ".": "0.24.0", - "acvm-repo": "0.40.0" + ".": "0.25.0", + "acvm-repo": "0.41.0" } \ No newline at end of file diff --git a/noir/noir-repo/CHANGELOG.md b/noir/noir-repo/CHANGELOG.md index e9b2dfb48a5..cdbccf768ca 100644 --- a/noir/noir-repo/CHANGELOG.md +++ b/noir/noir-repo/CHANGELOG.md @@ -1,5 +1,82 @@ # Changelog +## [0.25.0](https://github.com/noir-lang/noir/compare/v0.24.0...v0.25.0) (2024-03-11) + + +### ⚠ BREAKING CHANGES + +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) +* reserve `unchecked` keyword ([#4432](https://github.com/noir-lang/noir/issues/4432)) +* Remove empty value from bounded vec ([#4431](https://github.com/noir-lang/noir/issues/4431)) +* Ban Fields in for loop indices and bitwise ops ([#4376](https://github.com/noir-lang/noir/issues/4376)) +* bump msrv to 1.73.0 ([#4406](https://github.com/noir-lang/noir/issues/4406)) +* **ci:** Bump MSRV to 1.72.1 and enforce that ACVM can be published using updated lockfile ([#4385](https://github.com/noir-lang/noir/issues/4385)) +* Restrict bit sizes ([#4235](https://github.com/noir-lang/noir/issues/4235)) +* move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) +* note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) + +### Features + +* Add eddsa_poseidon_to_pub function to stdlib with test + docs ([#4473](https://github.com/noir-lang/noir/issues/4473)) ([00d2c32](https://github.com/noir-lang/noir/commit/00d2c32e58176cc5de3574c8435a54d415c4a5fa)) +* Add HashMap to the stdlib ([#4242](https://github.com/noir-lang/noir/issues/4242)) ([650ffc5](https://github.com/noir-lang/noir/commit/650ffc5053cdca4b6ad2e027fa1f4fd90ef64871)) +* Add option to set max memory for bb.js ([#4227](https://github.com/noir-lang/noir/issues/4227)) ([8a6b131](https://github.com/noir-lang/noir/commit/8a6b131402892a570bc2de6f5869de73b0bd979e)) +* Add overflow and underflow checks for unsigned integers in brillig ([#4445](https://github.com/noir-lang/noir/issues/4445)) ([21fc4b8](https://github.com/noir-lang/noir/commit/21fc4b85763dccae6dce0a46a318718c3c913471)) +* Add poseidon2 opcode implementation for acvm/brillig, and Noir ([#4398](https://github.com/noir-lang/noir/issues/4398)) ([10e8292](https://github.com/noir-lang/noir/commit/10e82920798380f50046e52db4a20ca205191ab7)) +* Added cast opcode and cast calldata (https://github.com/AztecProtocol/aztec-packages/pull/4423) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Allow type aliases to reference other aliases ([#4353](https://github.com/noir-lang/noir/issues/4353)) ([c44ef14](https://github.com/noir-lang/noir/commit/c44ef14847a436733206b6dd9590a7ab214ecd97)) +* Backpropagate constants in ACIR during optimization ([#3926](https://github.com/noir-lang/noir/issues/3926)) ([aad0da0](https://github.com/noir-lang/noir/commit/aad0da024c69663f42e6913e674682d5864b26ae)) +* **ci:** Use wasm-opt when compiling wasm packages ([#4334](https://github.com/noir-lang/noir/issues/4334)) ([e382921](https://github.com/noir-lang/noir/commit/e3829213d8411f84e117a14b43816967925095e0)) +* DAP Preflight and debugger compilation options ([#4185](https://github.com/noir-lang/noir/issues/4185)) ([e0ad0b2](https://github.com/noir-lang/noir/commit/e0ad0b2b31f6d46be75d23aec6a82850a9c4bd75)) +* Expose separate functions to compile programs vs contracts in `noir_wasm` ([#4413](https://github.com/noir-lang/noir/issues/4413)) ([7cd5fdb](https://github.com/noir-lang/noir/commit/7cd5fdb3d2a53475b7c8681231d517cab30f9f9b)) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* Note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Restrict bit sizes ([#4235](https://github.com/noir-lang/noir/issues/4235)) ([1048f81](https://github.com/noir-lang/noir/commit/1048f815abb1f27e9c84ab5b9568a3673c12a50a)) +* Run tests in parallel in `nargo test` ([#4484](https://github.com/noir-lang/noir/issues/4484)) ([761734e](https://github.com/noir-lang/noir/commit/761734e6cb3ff5911aa85d0cee96ad26092b4905)) +* Skip redundant range checks in brillig ([#4460](https://github.com/noir-lang/noir/issues/4460)) ([cb4c1c5](https://github.com/noir-lang/noir/commit/cb4c1c5264b95d01f69d99f916ced71ad9cdc9d1)) +* Sync from aztec-packages ([#4483](https://github.com/noir-lang/noir/issues/4483)) ([fe8f277](https://github.com/noir-lang/noir/commit/fe8f2776ccfde29209a2c3fc162311c99e4f59be)) +* Track stack frames and their variables in the debugger ([#4188](https://github.com/noir-lang/noir/issues/4188)) ([ae1a9d9](https://github.com/noir-lang/noir/commit/ae1a9d923998177516919bbba6ff4b0584fa1e9f)) +* TypeVariableKind for just Integers ([#4118](https://github.com/noir-lang/noir/issues/4118)) ([c956be8](https://github.com/noir-lang/noir/commit/c956be870fb47403a6da6585fce6bea2d40ee268)) +* Update error message when trying to load workspace as dependency ([#4393](https://github.com/noir-lang/noir/issues/4393)) ([d2585e7](https://github.com/noir-lang/noir/commit/d2585e738a63208fca3c9e26242e896d7f1df1e4)) + + +### Bug Fixes + +* **acir:** Array dynamic flatten ([#4351](https://github.com/noir-lang/noir/issues/4351)) ([b2aaeab](https://github.com/noir-lang/noir/commit/b2aaeab319a0c66c431a7db6852f743eccde8e98)) +* **acir:** Use types on dynamic arrays ([#4364](https://github.com/noir-lang/noir/issues/4364)) ([ba2c541](https://github.com/noir-lang/noir/commit/ba2c541ec45de92bba98de34771b73cbb7865c93)) +* Add `follow_bindings` to follow `Type::Alias` links ([#4521](https://github.com/noir-lang/noir/issues/4521)) ([b94adb9](https://github.com/noir-lang/noir/commit/b94adb92657e2b4a51dc7216a88e080aed1cf8b0)) +* Add handling to `noir_wasm` for projects without dependencies ([#4344](https://github.com/noir-lang/noir/issues/4344)) ([4982251](https://github.com/noir-lang/noir/commit/49822511710a7f1c42b8ed343e80456f8e6db2d9)) +* Allow type aliases in main ([#4505](https://github.com/noir-lang/noir/issues/4505)) ([8a5359c](https://github.com/noir-lang/noir/commit/8a5359c012579e54c2766de1074482a36ecada32)) +* Ban Fields in for loop indices and bitwise ops ([#4376](https://github.com/noir-lang/noir/issues/4376)) ([601fd9a](https://github.com/noir-lang/noir/commit/601fd9afc502236af1db0c4492698ba2298c7501)) +* Brillig range check with consistent bit size ([#4357](https://github.com/noir-lang/noir/issues/4357)) ([ea47d4a](https://github.com/noir-lang/noir/commit/ea47d4a67c6a18e4a7d3a49079d9eb24a1026a25)) +* Build noir_codegen when publishing ([#4448](https://github.com/noir-lang/noir/issues/4448)) ([cb1ceee](https://github.com/noir-lang/noir/commit/cb1ceee58b11b0ce6f8845361af3418d13c506bd)) +* Consistent bit size for truncate ([#4370](https://github.com/noir-lang/noir/issues/4370)) ([dcd7a1e](https://github.com/noir-lang/noir/commit/dcd7a1e561a68504b9038ffbb3c80f5c981f9f0c)) +* Correct formatting for databus visibility types ([#4423](https://github.com/noir-lang/noir/issues/4423)) ([cd796de](https://github.com/noir-lang/noir/commit/cd796dea4937dd1a261f154e5f2e599bbc649165)) +* Correct invalid brillig codegen for `EmbeddedCurvePoint.add` ([#4382](https://github.com/noir-lang/noir/issues/4382)) ([5051ec4](https://github.com/noir-lang/noir/commit/5051ec4d434a9e5cf405c68357faaf213e68de9e)) +* **docs:** Update install versions ([#4396](https://github.com/noir-lang/noir/issues/4396)) ([b283637](https://github.com/noir-lang/noir/commit/b283637e092038eb296c468168aec2d41e1c2734)) +* **docs:** Update noirjs_app for 0.23 ([#4378](https://github.com/noir-lang/noir/issues/4378)) ([f77f702](https://github.com/noir-lang/noir/commit/f77f702e0cfb81dcce4dd97e274b831e887ba5d2)) +* Enforce matching types of binary ops in SSA ([#4391](https://github.com/noir-lang/noir/issues/4391)) ([70866ae](https://github.com/noir-lang/noir/commit/70866aea976d59dbcbd4af34067fdd8f46555673)) +* Fix brillig slowdown when assigning arrays in loops ([#4472](https://github.com/noir-lang/noir/issues/4472)) ([2a53545](https://github.com/noir-lang/noir/commit/2a53545f4238c9b8535e6bc5b0720fa15f44f946)) +* **flake:** Stop flake.nix removing ignored-tests.txt ([#4455](https://github.com/noir-lang/noir/issues/4455)) ([ebaf05a](https://github.com/noir-lang/noir/commit/ebaf05ab10834dd10e04c7ea5130f96c6cdf98ed)) +* Force src impl for == on slices ([#4507](https://github.com/noir-lang/noir/issues/4507)) ([1691274](https://github.com/noir-lang/noir/commit/169127444e8b16a8aad4acfe29ba812894fd897c)) +* Handling of gh deps in noir_wasm ([#4499](https://github.com/noir-lang/noir/issues/4499)) ([1d65370](https://github.com/noir-lang/noir/commit/1d653704715bf9999eb6a40ed7500e752e2c73b7)) +* Iterative flattening pass ([#4492](https://github.com/noir-lang/noir/issues/4492)) ([33c1ef7](https://github.com/noir-lang/noir/commit/33c1ef70e7859fdee7babfb5d38191f53e73a0df)) +* Noir test incorrect reporting (https://github.com/AztecProtocol/aztec-packages/pull/4925) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* Only add `.nr` files to file manager ([#4380](https://github.com/noir-lang/noir/issues/4380)) ([8536c7c](https://github.com/noir-lang/noir/commit/8536c7c8ea8fc6b740b2ae6d1aef3bc7e1907b8c)) +* Remove panic when generic array length is not resolvable ([#4408](https://github.com/noir-lang/noir/issues/4408)) ([00ab3db](https://github.com/noir-lang/noir/commit/00ab3db86b06111d144516e862902b8604284611)) +* Remove print from monomorphization pass ([#4417](https://github.com/noir-lang/noir/issues/4417)) ([27c66b3](https://github.com/noir-lang/noir/commit/27c66b3d0741e68ed591ae8a16b47b30bc87175f)) +* **ssa:** Handle mergers of slices returned from calls ([#4496](https://github.com/noir-lang/noir/issues/4496)) ([f988d02](https://github.com/noir-lang/noir/commit/f988d020e43cdf36a38613f2052d4518de39193a)) +* Use correct type for numeric generics ([#4386](https://github.com/noir-lang/noir/issues/4386)) ([0a1d109](https://github.com/noir-lang/noir/commit/0a1d109f478c997da5c43876fd12464af638bb15)) +* Variables from trait constraints being permanently bound over when used within a trait impl ([#4450](https://github.com/noir-lang/noir/issues/4450)) ([ac60ef5](https://github.com/noir-lang/noir/commit/ac60ef5e12fcfb907fbdcff709d7cbad05f2b939)) + + +### Miscellaneous Chores + +* Bump msrv to 1.73.0 ([#4406](https://github.com/noir-lang/noir/issues/4406)) ([b5e5c30](https://github.com/noir-lang/noir/commit/b5e5c30f4db52c79ef556e80660f39db369b1911)) +* **ci:** Bump MSRV to 1.72.1 and enforce that ACVM can be published using updated lockfile ([#4385](https://github.com/noir-lang/noir/issues/4385)) ([2fc95d2](https://github.com/noir-lang/noir/commit/2fc95d2d82b3220267ce7d5815e7073e00ef1360)) +* Move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove empty value from bounded vec ([#4431](https://github.com/noir-lang/noir/issues/4431)) ([b9384fb](https://github.com/noir-lang/noir/commit/b9384fb23abf4ab15e880fb7e03c21509a9fa8a6)) +* Reserve `unchecked` keyword ([#4432](https://github.com/noir-lang/noir/issues/4432)) ([9544813](https://github.com/noir-lang/noir/commit/9544813fabbd18a87dd88456e6a5b781bd0cf008)) + ## [0.24.0](https://github.com/noir-lang/noir/compare/v0.23.0...v0.24.0) (2024-02-12) diff --git a/noir/noir-repo/Cargo.lock b/noir/noir-repo/Cargo.lock index 83ac3744274..d5ce8a10509 100644 --- a/noir/noir-repo/Cargo.lock +++ b/noir/noir-repo/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "acir" -version = "0.40.0" +version = "0.41.0" dependencies = [ "acir_field", "base64 0.21.2", @@ -23,7 +23,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "0.40.0" +version = "0.41.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -37,7 +37,7 @@ dependencies = [ [[package]] name = "acvm" -version = "0.40.0" +version = "0.41.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -53,7 +53,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "0.40.0" +version = "0.41.0" dependencies = [ "acir", "blake2", @@ -88,7 +88,7 @@ dependencies = [ [[package]] name = "acvm_js" -version = "0.40.0" +version = "0.41.0" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -232,7 +232,7 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arena" -version = "0.24.0" +version = "0.25.0" [[package]] name = "ark-bls12-381" @@ -411,7 +411,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138985dd8aefbefeaa66b01b7f5b2b6b4c333fcef1cc5f32c63a2aabe37d6de3" dependencies = [ - "futures 0.3.28", + "futures 0.3.30", "lsp-types 0.94.1", "pin-project-lite", "rustix", @@ -433,7 +433,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "aztec_macros" -version = "0.24.0" +version = "0.25.0" dependencies = [ "convert_case 0.6.0", "iter-extended", @@ -541,9 +541,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bitmaps" @@ -622,7 +622,7 @@ dependencies = [ [[package]] name = "brillig" -version = "0.40.0" +version = "0.41.0" dependencies = [ "acir_field", "serde", @@ -630,7 +630,7 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "0.40.0" +version = "0.41.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -967,14 +967,14 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" [[package]] name = "console" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" dependencies = [ "encode_unicode 0.3.6", "lazy_static", "libc", - "windows-sys 0.45.0", + "windows-sys 0.52.0", ] [[package]] @@ -1605,12 +1605,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1726,7 +1726,7 @@ dependencies = [ [[package]] name = "fm" -version = "0.24.0" +version = "0.25.0" dependencies = [ "codespan-reporting", "iter-extended", @@ -1763,9 +1763,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -1778,9 +1778,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1788,15 +1788,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -1806,15 +1806,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", @@ -1823,21 +1823,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures 0.1.31", "futures-channel", @@ -2096,9 +2096,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -2111,7 +2111,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2", "tokio", "tower-service", "tracing", @@ -2120,9 +2120,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http", @@ -2318,7 +2318,7 @@ dependencies = [ [[package]] name = "iter-extended" -version = "0.24.0" +version = "0.25.0" [[package]] name = "itertools" @@ -2363,7 +2363,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" dependencies = [ "derive_more", - "futures 0.3.28", + "futures 0.3.30", "jsonrpc-core", "jsonrpc-pubsub", "log", @@ -2378,7 +2378,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ - "futures 0.3.28", + "futures 0.3.30", "futures-executor", "futures-util", "log", @@ -2393,7 +2393,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" dependencies = [ - "futures 0.3.28", + "futures 0.3.30", "jsonrpc-client-transports", ] @@ -2415,7 +2415,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ - "futures 0.3.28", + "futures 0.3.30", "hyper", "jsonrpc-core", "jsonrpc-server-utils", @@ -2431,7 +2431,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" dependencies = [ - "futures 0.3.28", + "futures 0.3.30", "jsonrpc-core", "lazy_static", "log", @@ -2447,7 +2447,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ "bytes", - "futures 0.3.28", + "futures 0.3.30", "globset", "jsonrpc-core", "lazy_static", @@ -2505,9 +2505,9 @@ checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" [[package]] name = "linux-raw-sys" -version = "0.4.3" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -2671,7 +2671,7 @@ checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" [[package]] name = "nargo" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "codespan-reporting", @@ -2698,7 +2698,7 @@ dependencies = [ [[package]] name = "nargo_cli" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "assert_cmd", @@ -2750,7 +2750,7 @@ dependencies = [ [[package]] name = "nargo_fmt" -version = "0.24.0" +version = "0.25.0" dependencies = [ "bytecount", "noirc_frontend", @@ -2762,7 +2762,7 @@ dependencies = [ [[package]] name = "nargo_toml" -version = "0.24.0" +version = "0.25.0" dependencies = [ "dirs", "fm", @@ -2835,7 +2835,7 @@ dependencies = [ [[package]] name = "noir_debugger" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "assert_cmd", @@ -2870,7 +2870,7 @@ dependencies = [ [[package]] name = "noir_lsp" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "async-lsp", @@ -2896,7 +2896,7 @@ dependencies = [ [[package]] name = "noir_wasm" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "build-data", @@ -2919,7 +2919,7 @@ dependencies = [ [[package]] name = "noirc_abi" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "iter-extended", @@ -2936,7 +2936,7 @@ dependencies = [ [[package]] name = "noirc_abi_wasm" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "build-data", @@ -2953,7 +2953,7 @@ dependencies = [ [[package]] name = "noirc_driver" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "aztec_macros", @@ -2966,7 +2966,6 @@ dependencies = [ "noirc_errors", "noirc_evaluator", "noirc_frontend", - "noirc_macros", "rust-embed", "serde", "thiserror", @@ -2975,7 +2974,7 @@ dependencies = [ [[package]] name = "noirc_errors" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "base64 0.21.2", @@ -2993,7 +2992,7 @@ dependencies = [ [[package]] name = "noirc_evaluator" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "fxhash", @@ -3009,7 +3008,7 @@ dependencies = [ [[package]] name = "noirc_frontend" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "arena", @@ -3032,17 +3031,9 @@ dependencies = [ "tracing", ] -[[package]] -name = "noirc_macros" -version = "0.24.0" -dependencies = [ - "iter-extended", - "noirc_frontend", -] - [[package]] name = "noirc_printable_type" -version = "0.24.0" +version = "0.25.0" dependencies = [ "acvm", "iter-extended", @@ -3480,7 +3471,7 @@ checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.3.3", + "bitflags 2.4.2", "lazy_static", "num-traits", "rand 0.8.5", @@ -3942,15 +3933,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.4" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -4321,9 +4312,9 @@ dependencies = [ [[package]] name = "shared-buffer" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cf61602ee61e2f83dd016b3e6387245291cf728ea071c378b35088125b4d995" +checksum = "f6c99835bad52957e7aa241d3975ed17c1e5f8c92026377d117a606f36b84b16" dependencies = [ "bytes", "memmap2 0.6.2", @@ -4441,16 +4432,6 @@ dependencies = [ "serde", ] -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.5.5" @@ -4762,7 +4743,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2 0.5.5", + "socket2", "tokio-macros", "windows-sys 0.48.0", ] @@ -5278,9 +5259,9 @@ dependencies = [ [[package]] name = "wasmer" -version = "4.2.4" +version = "4.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce45cc009177ca345a6d041f9062305ad467d15e7d41494f5b81ab46d62d7a58" +checksum = "5c15724dc25d1ee57962334aea8e41ade2675e5ea2ac6b8d42da6051b0face66" dependencies = [ "bytes", "cfg-if 1.0.0", @@ -5294,23 +5275,23 @@ dependencies = [ "shared-buffer", "target-lexicon", "thiserror", + "tracing", "wasm-bindgen", "wasmer-compiler", "wasmer-compiler-cranelift", "wasmer-derive", "wasmer-types", "wasmer-vm", - "wasmparser 0.83.0", - "wasmparser 0.95.0", + "wasmparser", "wat", "winapi", ] [[package]] name = "wasmer-compiler" -version = "4.2.4" +version = "4.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e044f6140c844602b920deb4526aea3cc9c0d7cf23f00730bb9b2034669f522a" +checksum = "55a7f3b3a96f8d844c25e2c032af9572306dd63fa93dc17bcca4c5458ac569bd" dependencies = [ "backtrace", "bytes", @@ -5329,15 +5310,15 @@ dependencies = [ "thiserror", "wasmer-types", "wasmer-vm", - "wasmparser 0.95.0", + "wasmparser", "winapi", ] [[package]] name = "wasmer-compiler-cranelift" -version = "4.2.4" +version = "4.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ce02358eb44a149d791c1d6648fb7f8b2f99cd55e3c4eef0474653ec8cc889" +checksum = "102e2c5bacac69495c4025767e2fa26797ffb27f242dccb7cf57d9cefd944386" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -5354,9 +5335,9 @@ dependencies = [ [[package]] name = "wasmer-derive" -version = "4.2.4" +version = "4.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c782d80401edb08e1eba206733f7859db6c997fc5a7f5fb44edc3ecd801468f6" +checksum = "0ea737fa08f95d6abc4459f42a70a9833e8974b814e74971d77ef473814f4d4c" dependencies = [ "proc-macro-error", "proc-macro2", @@ -5366,9 +5347,9 @@ dependencies = [ [[package]] name = "wasmer-types" -version = "4.2.4" +version = "4.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd09e80d4d74bb9fd0ce6c3c106b1ceba1a050f9948db9d9b78ae53c172d6157" +checksum = "b0689110e291b0f07fc665f2824e5ff81df120848e8a9acfbf1a9bf7990773f9" dependencies = [ "bytecheck", "enum-iterator", @@ -5382,9 +5363,9 @@ dependencies = [ [[package]] name = "wasmer-vm" -version = "4.2.4" +version = "4.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdcd8a4fd36414a7b6a003dbfbd32393bce3e155d715dd877c05c1b7a41d224d" +checksum = "4cd41f822a1ac4242d478754e8ceba2806a00ea5072803622e1fe91e8e28b2a1" dependencies = [ "backtrace", "cc", @@ -5410,18 +5391,13 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.83.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" - -[[package]] -name = "wasmparser" -version = "0.95.0" +version = "0.121.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ea896273ea99b15132414be1da01ab0d8836415083298ecaffbe308eaac87a" +checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" dependencies = [ - "indexmap 1.9.3", - "url 2.4.0", + "bitflags 2.4.2", + "indexmap 2.0.0", + "semver", ] [[package]] @@ -5514,15 +5490,6 @@ dependencies = [ "windows_x86_64_msvc 0.33.0", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -5533,18 +5500,12 @@ dependencies = [ ] [[package]] -name = "windows-targets" -version = "0.42.2" +name = "windows-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets 0.52.4", ] [[package]] @@ -5563,10 +5524,19 @@ dependencies = [ ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" +name = "windows-targets" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", +] [[package]] name = "windows_aarch64_gnullvm" @@ -5574,6 +5544,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + [[package]] name = "windows_aarch64_msvc" version = "0.33.0" @@ -5582,15 +5558,15 @@ checksum = "cd761fd3eb9ab8cc1ed81e56e567f02dd82c4c837e48ac3b2181b9ffc5060807" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -5600,15 +5576,15 @@ checksum = "cab0cf703a96bab2dc0c02c0fa748491294bf9b7feb27e1f4f96340f208ada0e" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -5618,15 +5594,15 @@ checksum = "8cfdbe89cc9ad7ce618ba34abc34bbb6c36d99e96cae2245b7943cd75ee773d0" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -5636,27 +5612,27 @@ checksum = "b4dd9b0c0e9ece7bb22e84d70d01b71c6d6248b81a3c60d11869451b4cb24784" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -5666,15 +5642,15 @@ checksum = "ff1e4aa646495048ec7f3ffddc411e1d829c026a2ec62b39da15c1055e406eaa" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" diff --git a/noir/noir-repo/Cargo.toml b/noir/noir-repo/Cargo.toml index 572042f1a6a..b8f9b9ceacc 100644 --- a/noir/noir-repo/Cargo.toml +++ b/noir/noir-repo/Cargo.toml @@ -1,9 +1,8 @@ [workspace] members = [ - # Macros crates for metaprogramming + # Aztec Macro crate for metaprogramming "aztec_macros", - "noirc_macros", # Compiler crates "compiler/noirc_evaluator", "compiler/noirc_frontend", @@ -42,7 +41,7 @@ resolver = "2" [workspace.package] # x-release-please-start-version -version = "0.24.0" +version = "0.25.0" # x-release-please-end authors = ["The Noir Team "] edition = "2021" @@ -53,12 +52,12 @@ repository = "https://github.com/noir-lang/noir/" [workspace.dependencies] # ACVM workspace dependencies -acir_field = { version = "0.40.0", path = "acvm-repo/acir_field", default-features = false } -acir = { version = "0.40.0", path = "acvm-repo/acir", default-features = false } -acvm = { version = "0.40.0", path = "acvm-repo/acvm" } -brillig = { version = "0.40.0", path = "acvm-repo/brillig", default-features = false } -brillig_vm = { version = "0.40.0", path = "acvm-repo/brillig_vm", default-features = false } -acvm_blackbox_solver = { version = "0.40.0", path = "acvm-repo/blackbox_solver", default-features = false } +acir_field = { version = "0.41.0", path = "acvm-repo/acir_field", default-features = false } +acir = { version = "0.41.0", path = "acvm-repo/acir", default-features = false } +acvm = { version = "0.41.0", path = "acvm-repo/acvm" } +brillig = { version = "0.41.0", path = "acvm-repo/brillig", default-features = false } +brillig_vm = { version = "0.41.0", path = "acvm-repo/brillig_vm", default-features = false } +acvm_blackbox_solver = { version = "0.41.0", path = "acvm-repo/blackbox_solver", default-features = false } bn254_blackbox_solver = { version = "0.39.0", path = "acvm-repo/bn254_blackbox_solver", default-features = false } # Noir compiler workspace dependencies diff --git a/noir/noir-repo/acvm-repo/CHANGELOG.md b/noir/noir-repo/acvm-repo/CHANGELOG.md index acb465e5cc9..4f220d6eeba 100644 --- a/noir/noir-repo/acvm-repo/CHANGELOG.md +++ b/noir/noir-repo/acvm-repo/CHANGELOG.md @@ -5,6 +5,70 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.41.0](https://github.com/noir-lang/noir/compare/v0.40.0...v0.41.0) (2024-03-11) + + +### ⚠ BREAKING CHANGES + +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) +* move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) +* note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) +* rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) +* init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) +* Sync commits from `aztec-packages` ([#4144](https://github.com/noir-lang/noir/issues/4144)) +* Breaking changes from aztec-packages ([#3955](https://github.com/noir-lang/noir/issues/3955)) +* Rename Arithmetic opcode to AssertZero ([#3840](https://github.com/noir-lang/noir/issues/3840)) +* Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) +* Remove partial backend feature ([#3805](https://github.com/noir-lang/noir/issues/3805)) + +### Features + +* Add bit size to const opcode (https://github.com/AztecProtocol/aztec-packages/pull/4385) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add instrumentation for tracking variables in debugging ([#4122](https://github.com/noir-lang/noir/issues/4122)) ([c58d691](https://github.com/noir-lang/noir/commit/c58d69141b54a918cd1675400c00bfd48720f896)) +* Add poseidon2 opcode implementation for acvm/brillig, and Noir ([#4398](https://github.com/noir-lang/noir/issues/4398)) ([10e8292](https://github.com/noir-lang/noir/commit/10e82920798380f50046e52db4a20ca205191ab7)) +* Add support for overriding expression width ([#4117](https://github.com/noir-lang/noir/issues/4117)) ([c8026d5](https://github.com/noir-lang/noir/commit/c8026d557d535b10fe455165d6445076df7a03de)) +* Added cast opcode and cast calldata (https://github.com/AztecProtocol/aztec-packages/pull/4423) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Allow brillig to read arrays directly from memory (https://github.com/AztecProtocol/aztec-packages/pull/4460) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow nested arrays and vectors in Brillig foreign calls (https://github.com/AztecProtocol/aztec-packages/pull/4478) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow variables and stack trace inspection in the debugger ([#4184](https://github.com/noir-lang/noir/issues/4184)) ([bf263fc](https://github.com/noir-lang/noir/commit/bf263fc8d843940f328a90f6366edd2671fb2682)) +* **avm:** Back in avm context with macro - refactor context (https://github.com/AztecProtocol/aztec-packages/pull/4438) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* **aztec-nr:** Initial work for aztec public vm macro (https://github.com/AztecProtocol/aztec-packages/pull/4400) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Aztec-packages ([#3754](https://github.com/noir-lang/noir/issues/3754)) ([c043265](https://github.com/noir-lang/noir/commit/c043265e550b59bd4296504826fe15d3ce3e9ad2)) +* Backpropagate constants in ACIR during optimization ([#3926](https://github.com/noir-lang/noir/issues/3926)) ([aad0da0](https://github.com/noir-lang/noir/commit/aad0da024c69663f42e6913e674682d5864b26ae)) +* Breaking changes from aztec-packages ([#3955](https://github.com/noir-lang/noir/issues/3955)) ([5be049e](https://github.com/noir-lang/noir/commit/5be049eee6c342649462282ee04f6411e6ea392c)) +* Evaluation of dynamic assert messages ([#4101](https://github.com/noir-lang/noir/issues/4101)) ([c284e01](https://github.com/noir-lang/noir/commit/c284e01bfe20ceae4414dc123624b5cbb8b66d09)) +* Init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* Note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove range constraints from witnesses which are constrained to be constants ([#3928](https://github.com/noir-lang/noir/issues/3928)) ([afe9c7a](https://github.com/noir-lang/noir/commit/afe9c7a38bb9d4245205d3aa46d4ce23d70a5671)) +* Remove replacement of boolean range opcodes with `AssertZero` opcodes ([#4107](https://github.com/noir-lang/noir/issues/4107)) ([dac0e87](https://github.com/noir-lang/noir/commit/dac0e87ee3be3446b92bbb12ef4832fd493fcee3)) +* Speed up transformation of debug messages ([#3815](https://github.com/noir-lang/noir/issues/3815)) ([2a8af1e](https://github.com/noir-lang/noir/commit/2a8af1e4141ffff61547ee1c2837a6392bd5db48)) +* Sync `aztec-packages` ([#4011](https://github.com/noir-lang/noir/issues/4011)) ([fee2452](https://github.com/noir-lang/noir/commit/fee24523c427c27f0bdaf98ea09a852a2da3e94c)) +* Sync commits from `aztec-packages` ([#4068](https://github.com/noir-lang/noir/issues/4068)) ([7a8f3a3](https://github.com/noir-lang/noir/commit/7a8f3a33b57875e681e3d81e667e3570a1cdbdcc)) +* Sync commits from `aztec-packages` ([#4144](https://github.com/noir-lang/noir/issues/4144)) ([0205d3b](https://github.com/noir-lang/noir/commit/0205d3b4ad0cf5ffd775a43eb5af273a772cf138)) +* Sync from aztec-packages ([#4483](https://github.com/noir-lang/noir/issues/4483)) ([fe8f277](https://github.com/noir-lang/noir/commit/fe8f2776ccfde29209a2c3fc162311c99e4f59be)) + + +### Bug Fixes + +* Deserialize odd length hex literals ([#3747](https://github.com/noir-lang/noir/issues/3747)) ([4000fb2](https://github.com/noir-lang/noir/commit/4000fb279221eb07187d657bfaa7f1c7b311abf2)) +* Noir test incorrect reporting (https://github.com/AztecProtocol/aztec-packages/pull/4925) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* Remove panic from `init_log_level` in `acvm_js` ([#4195](https://github.com/noir-lang/noir/issues/4195)) ([2e26530](https://github.com/noir-lang/noir/commit/2e26530bf53006c1ed4fee310bcaa905c95dd95b)) +* Return error rather instead of panicking on invalid circuit ([#3976](https://github.com/noir-lang/noir/issues/3976)) ([67201bf](https://github.com/noir-lang/noir/commit/67201bfc21a9c8858aa86be9cd47d463fb78d925)) + + +### Miscellaneous Chores + +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove partial backend feature ([#3805](https://github.com/noir-lang/noir/issues/3805)) ([0383100](https://github.com/noir-lang/noir/commit/0383100853a80a5b28b797cdfeae0d271f1b7805)) +* Remove unused methods on ACIR opcodes ([#3841](https://github.com/noir-lang/noir/issues/3841)) ([9e5d0e8](https://github.com/noir-lang/noir/commit/9e5d0e813d61a0bfb5ee68174ed287c5a20f1579)) +* Rename Arithmetic opcode to AssertZero ([#3840](https://github.com/noir-lang/noir/issues/3840)) ([836f171](https://github.com/noir-lang/noir/commit/836f17145c2901060706294461c2d282dd121b3e)) +* Rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) + ## [0.40.0](https://github.com/noir-lang/noir/compare/v0.39.0...v0.40.0) (2024-02-12) diff --git a/noir/noir-repo/acvm-repo/acir/Cargo.toml b/noir/noir-repo/acvm-repo/acir/Cargo.toml index 7021333486f..be859d7d054 100644 --- a/noir/noir-repo/acvm-repo/acir/Cargo.toml +++ b/noir/noir-repo/acvm-repo/acir/Cargo.toml @@ -2,7 +2,7 @@ name = "acir" description = "ACIR is the IR that the VM processes, it is analogous to LLVM IR" # x-release-please-start-version -version = "0.40.0" +version = "0.41.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/acir_field/Cargo.toml b/noir/noir-repo/acvm-repo/acir_field/Cargo.toml index 6f4971770bd..c2056b73277 100644 --- a/noir/noir-repo/acvm-repo/acir_field/Cargo.toml +++ b/noir/noir-repo/acvm-repo/acir_field/Cargo.toml @@ -2,7 +2,7 @@ name = "acir_field" description = "The field implementation being used by ACIR." # x-release-please-start-version -version = "0.40.0" +version = "0.41.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/acvm/Cargo.toml b/noir/noir-repo/acvm-repo/acvm/Cargo.toml index fce9a8e8e8b..d585850170a 100644 --- a/noir/noir-repo/acvm-repo/acvm/Cargo.toml +++ b/noir/noir-repo/acvm-repo/acvm/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm" description = "The virtual machine that processes ACIR given a backend/proof system." # x-release-please-start-version -version = "0.40.0" +version = "0.41.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/acvm_js/Cargo.toml b/noir/noir-repo/acvm-repo/acvm_js/Cargo.toml index 7ec814a72e5..63fca2bd32a 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/Cargo.toml +++ b/noir/noir-repo/acvm-repo/acvm_js/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm_js" description = "Typescript wrapper around the ACVM allowing execution of ACIR code" # x-release-please-start-version -version = "0.40.0" +version = "0.41.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/acvm_js/package.json b/noir/noir-repo/acvm-repo/acvm_js/package.json index 876db9ccb62..0a9cd7235f5 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/package.json +++ b/noir/noir-repo/acvm-repo/acvm_js/package.json @@ -1,6 +1,6 @@ { "name": "@noir-lang/acvm_js", - "version": "0.40.0", + "version": "0.41.0", "publishConfig": { "access": "public" }, diff --git a/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml b/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml index 0794b2dbe7e..a783193edba 100644 --- a/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml +++ b/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm_blackbox_solver" description = "A solver for the blackbox functions found in ACIR and Brillig" # x-release-please-start-version -version = "0.40.0" +version = "0.41.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/blackbox_solver/src/ecdsa/mod.rs b/noir/noir-repo/acvm-repo/blackbox_solver/src/ecdsa/mod.rs new file mode 100644 index 00000000000..cb3134bf0ab --- /dev/null +++ b/noir/noir-repo/acvm-repo/blackbox_solver/src/ecdsa/mod.rs @@ -0,0 +1,22 @@ +use crate::BlackBoxResolutionError; + +mod secp256k1; +mod secp256r1; + +pub fn ecdsa_secp256k1_verify( + hashed_msg: &[u8], + public_key_x: &[u8; 32], + public_key_y: &[u8; 32], + signature: &[u8; 64], +) -> Result { + Ok(secp256k1::verify_signature(hashed_msg, public_key_x, public_key_y, signature)) +} + +pub fn ecdsa_secp256r1_verify( + hashed_msg: &[u8], + public_key_x: &[u8; 32], + public_key_y: &[u8; 32], + signature: &[u8; 64], +) -> Result { + Ok(secp256r1::verify_signature(hashed_msg, public_key_x, public_key_y, signature)) +} diff --git a/noir/noir-repo/acvm-repo/blackbox_solver/src/ecdsa/secp256k1.rs b/noir/noir-repo/acvm-repo/blackbox_solver/src/ecdsa/secp256k1.rs new file mode 100644 index 00000000000..17c51353f7f --- /dev/null +++ b/noir/noir-repo/acvm-repo/blackbox_solver/src/ecdsa/secp256k1.rs @@ -0,0 +1,137 @@ +use k256::elliptic_curve::sec1::FromEncodedPoint; +use k256::elliptic_curve::PrimeField; + +use blake2::digest::generic_array::GenericArray; +use k256::{ecdsa::Signature, Scalar}; +use k256::{ + elliptic_curve::{ + sec1::{Coordinates, ToEncodedPoint}, + IsHigh, + }, + AffinePoint, EncodedPoint, ProjectivePoint, PublicKey, +}; + +pub(super) fn verify_signature( + hashed_msg: &[u8], + public_key_x_bytes: &[u8; 32], + public_key_y_bytes: &[u8; 32], + signature: &[u8; 64], +) -> bool { + // Convert the inputs into k256 data structures + let Ok(signature) = Signature::try_from(signature.as_slice()) else { + // Signature `r` and `s` are forbidden from being zero. + return false; + }; + + let point = EncodedPoint::from_affine_coordinates( + public_key_x_bytes.into(), + public_key_y_bytes.into(), + true, + ); + + let pubkey = PublicKey::from_encoded_point(&point); + let pubkey = if pubkey.is_some().into() { + pubkey.unwrap() + } else { + // Public key must sit on the Secp256k1 curve. + return false; + }; + + // Note: This is incorrect as it will panic if `hashed_msg >= k256::Secp256k1::ORDER`. + // In this scenario we should just take the leftmost bits from `hashed_msg` up to the group order length. + let z = Scalar::from_repr(*GenericArray::from_slice(hashed_msg)).unwrap(); + + // Finished converting bytes into data structures + + let r = signature.r(); + let s = signature.s(); + + // Ensure signature is "low S" normalized ala BIP 0062 + if s.is_high().into() { + return false; + } + + let s_inv = s.invert().unwrap(); + let u1 = z * s_inv; + let u2 = *r * s_inv; + + #[allow(non_snake_case)] + let R: AffinePoint = ((ProjectivePoint::GENERATOR * u1) + + (ProjectivePoint::from(*pubkey.as_affine()) * u2)) + .to_affine(); + + match R.to_encoded_point(false).coordinates() { + Coordinates::Uncompressed { x, y: _ } => Scalar::from_repr(*x).unwrap().eq(&r), + _ => unreachable!("Point is uncompressed"), + } +} + +#[cfg(test)] +mod secp256k1_tests { + use super::verify_signature; + + // 0x3a73f4123a5cd2121f21cd7e8d358835476949d035d9c2da6806b4633ac8c1e2, + const HASHED_MESSAGE: [u8; 32] = [ + 0x3a, 0x73, 0xf4, 0x12, 0x3a, 0x5c, 0xd2, 0x12, 0x1f, 0x21, 0xcd, 0x7e, 0x8d, 0x35, 0x88, + 0x35, 0x47, 0x69, 0x49, 0xd0, 0x35, 0xd9, 0xc2, 0xda, 0x68, 0x06, 0xb4, 0x63, 0x3a, 0xc8, + 0xc1, 0xe2, + ]; + // 0xa0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7 + const PUB_KEY_X: [u8; 32] = [ + 0xa0, 0x43, 0x4d, 0x9e, 0x47, 0xf3, 0xc8, 0x62, 0x35, 0x47, 0x7c, 0x7b, 0x1a, 0xe6, 0xae, + 0x5d, 0x34, 0x42, 0xd4, 0x9b, 0x19, 0x43, 0xc2, 0xb7, 0x52, 0xa6, 0x8e, 0x2a, 0x47, 0xe2, + 0x47, 0xc7, + ]; + // 0x893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7 + const PUB_KEY_Y: [u8; 32] = [ + 0x89, 0x3a, 0xba, 0x42, 0x54, 0x19, 0xbc, 0x27, 0xa3, 0xb6, 0xc7, 0xe6, 0x93, 0xa2, 0x4c, + 0x69, 0x6f, 0x79, 0x4c, 0x2e, 0xd8, 0x77, 0xa1, 0x59, 0x3c, 0xbe, 0xe5, 0x3b, 0x03, 0x73, + 0x68, 0xd7, + ]; + // 0xe5081c80ab427dc370346f4a0e31aa2bad8d9798c38061db9ae55a4e8df454fd28119894344e71b78770cc931d61f480ecbb0b89d6eb69690161e49a715fcd55 + const SIGNATURE: [u8; 64] = [ + 0xe5, 0x08, 0x1c, 0x80, 0xab, 0x42, 0x7d, 0xc3, 0x70, 0x34, 0x6f, 0x4a, 0x0e, 0x31, 0xaa, + 0x2b, 0xad, 0x8d, 0x97, 0x98, 0xc3, 0x80, 0x61, 0xdb, 0x9a, 0xe5, 0x5a, 0x4e, 0x8d, 0xf4, + 0x54, 0xfd, 0x28, 0x11, 0x98, 0x94, 0x34, 0x4e, 0x71, 0xb7, 0x87, 0x70, 0xcc, 0x93, 0x1d, + 0x61, 0xf4, 0x80, 0xec, 0xbb, 0x0b, 0x89, 0xd6, 0xeb, 0x69, 0x69, 0x01, 0x61, 0xe4, 0x9a, + 0x71, 0x5f, 0xcd, 0x55, + ]; + + #[test] + fn verifies_valid_signature_with_low_s_value() { + let valid = verify_signature(&HASHED_MESSAGE, &PUB_KEY_X, &PUB_KEY_Y, &SIGNATURE); + + assert!(valid); + } + + #[test] + fn rejects_invalid_signature() { + // This signature is invalid as ECDSA specifies that `r` and `s` must be non-zero. + let invalid_signature: [u8; 64] = [0x00; 64]; + + let valid = verify_signature(&HASHED_MESSAGE, &PUB_KEY_X, &PUB_KEY_Y, &invalid_signature); + assert!(!valid); + } + + #[test] + fn rejects_invalid_public_key() { + let invalid_pub_key_x: [u8; 32] = [0xff; 32]; + let invalid_pub_key_y: [u8; 32] = [0xff; 32]; + + let valid = + verify_signature(&HASHED_MESSAGE, &invalid_pub_key_x, &invalid_pub_key_y, &SIGNATURE); + + assert!(!valid); + } + + #[test] + #[ignore = "ECDSA verification does not currently handle long hashes correctly"] + fn trims_overly_long_hashes_to_correct_length() { + let mut long_hashed_message = HASHED_MESSAGE.to_vec(); + long_hashed_message.push(0xff); + + let valid = verify_signature(&long_hashed_message, &PUB_KEY_X, &PUB_KEY_Y, &SIGNATURE); + + assert!(valid); + } +} diff --git a/noir/noir-repo/acvm-repo/blackbox_solver/src/ecdsa/secp256r1.rs b/noir/noir-repo/acvm-repo/blackbox_solver/src/ecdsa/secp256r1.rs new file mode 100644 index 00000000000..54559d7c774 --- /dev/null +++ b/noir/noir-repo/acvm-repo/blackbox_solver/src/ecdsa/secp256r1.rs @@ -0,0 +1,133 @@ +use p256::elliptic_curve::sec1::FromEncodedPoint; +use p256::elliptic_curve::PrimeField; + +use blake2::digest::generic_array::GenericArray; +use p256::{ecdsa::Signature, Scalar}; +use p256::{ + elliptic_curve::{ + sec1::{Coordinates, ToEncodedPoint}, + IsHigh, + }, + AffinePoint, EncodedPoint, ProjectivePoint, PublicKey, +}; + +pub(super) fn verify_signature( + hashed_msg: &[u8], + public_key_x_bytes: &[u8; 32], + public_key_y_bytes: &[u8; 32], + signature: &[u8; 64], +) -> bool { + // Convert the inputs into k256 data structures + let Ok(signature) = Signature::try_from(signature.as_slice()) else { + // Signature `r` and `s` are forbidden from being zero. + return false; + }; + + let point = EncodedPoint::from_affine_coordinates( + public_key_x_bytes.into(), + public_key_y_bytes.into(), + true, + ); + + let pubkey = PublicKey::from_encoded_point(&point); + let pubkey = if pubkey.is_some().into() { + pubkey.unwrap() + } else { + // Public key must sit on the Secp256r1 curve. + return false; + }; + + // Note: This is incorrect as it will panic if `hashed_msg >= p256::NistP256::ORDER`. + // In this scenario we should just take the leftmost bits from `hashed_msg` up to the group order length. + let z = Scalar::from_repr(*GenericArray::from_slice(hashed_msg)).unwrap(); + + // Finished converting bytes into data structures + + let r = signature.r(); + let s = signature.s(); + + // Ensure signature is "low S" normalized ala BIP 0062 + if s.is_high().into() { + return false; + } + + let s_inv = s.invert().unwrap(); + let u1 = z * s_inv; + let u2 = *r * s_inv; + + #[allow(non_snake_case)] + let R: AffinePoint = ((ProjectivePoint::GENERATOR * u1) + + (ProjectivePoint::from(*pubkey.as_affine()) * u2)) + .to_affine(); + + match R.to_encoded_point(false).coordinates() { + Coordinates::Uncompressed { x, y: _ } => Scalar::from_repr(*x).unwrap().eq(&r), + _ => unreachable!("Point is uncompressed"), + } +} + +#[cfg(test)] +mod secp256r1_tests { + use super::verify_signature; + + // 0x54705ba3baafdbdfba8c5f9a70f7a89bee98d906b53e31074da7baecdc0da9ad + const HASHED_MESSAGE: [u8; 32] = [ + 84, 112, 91, 163, 186, 175, 219, 223, 186, 140, 95, 154, 112, 247, 168, 155, 238, 152, 217, + 6, 181, 62, 49, 7, 77, 167, 186, 236, 220, 13, 169, 173, + ]; + // 0x550f471003f3df97c3df506ac797f6721fb1a1fb7b8f6f83d224498a65c88e24 + const PUB_KEY_X: [u8; 32] = [ + 85, 15, 71, 16, 3, 243, 223, 151, 195, 223, 80, 106, 199, 151, 246, 114, 31, 177, 161, 251, + 123, 143, 111, 131, 210, 36, 73, 138, 101, 200, 142, 36, + ]; + // 0x136093d7012e509a73715cbd0b00a3cc0ff4b5c01b3ffa196ab1fb327036b8e6 + const PUB_KEY_Y: [u8; 32] = [ + 19, 96, 147, 215, 1, 46, 80, 154, 115, 113, 92, 189, 11, 0, 163, 204, 15, 244, 181, 192, + 27, 63, 250, 25, 106, 177, 251, 50, 112, 54, 184, 230, + ]; + // 0x2c70a8d084b62bfc5ce03641caf9f72ad4da8c81bfe6ec9487bb5e1bef62a13218ad9ee29eaf351fdc50f1520c425e9b908a07278b43b0ec7b872778c14e0784 + const SIGNATURE: [u8; 64] = [ + 44, 112, 168, 208, 132, 182, 43, 252, 92, 224, 54, 65, 202, 249, 247, 42, 212, 218, 140, + 129, 191, 230, 236, 148, 135, 187, 94, 27, 239, 98, 161, 50, 24, 173, 158, 226, 158, 175, + 53, 31, 220, 80, 241, 82, 12, 66, 94, 155, 144, 138, 7, 39, 139, 67, 176, 236, 123, 135, + 39, 120, 193, 78, 7, 132, + ]; + + #[test] + fn verifies_valid_signature_with_low_s_value() { + let valid = verify_signature(&HASHED_MESSAGE, &PUB_KEY_X, &PUB_KEY_Y, &SIGNATURE); + + assert!(valid); + } + + #[test] + fn rejects_invalid_signature() { + // This signature is invalid as ECDSA specifies that `r` and `s` must be non-zero. + let invalid_signature: [u8; 64] = [0x00; 64]; + + let valid = verify_signature(&HASHED_MESSAGE, &PUB_KEY_X, &PUB_KEY_Y, &invalid_signature); + assert!(!valid); + } + + #[test] + fn rejects_invalid_public_key() { + let invalid_pub_key_x: [u8; 32] = [0xff; 32]; + let invalid_pub_key_y: [u8; 32] = [0xff; 32]; + + let valid = + verify_signature(&HASHED_MESSAGE, &invalid_pub_key_x, &invalid_pub_key_y, &SIGNATURE); + + assert!(!valid); + } + + #[test] + #[ignore = "ECDSA verification does not currently handle long hashes correctly"] + fn trims_overly_long_hashes_to_correct_length() { + let mut long_hashed_message = HASHED_MESSAGE.to_vec(); + long_hashed_message.push(0xff); + + let valid = verify_signature(&long_hashed_message, &PUB_KEY_X, &PUB_KEY_Y, &SIGNATURE); + + assert!(valid); + } +} diff --git a/noir/noir-repo/acvm-repo/blackbox_solver/src/hash.rs b/noir/noir-repo/acvm-repo/blackbox_solver/src/hash.rs new file mode 100644 index 00000000000..ac56029b436 --- /dev/null +++ b/noir/noir-repo/acvm-repo/blackbox_solver/src/hash.rs @@ -0,0 +1,126 @@ +use acir::BlackBoxFunc; +use blake2::digest::generic_array::GenericArray; +use blake2::{Blake2s256, Digest}; +use sha2::Sha256; +use sha3::Keccak256; + +use crate::BlackBoxResolutionError; + +/// Does a generic hash of the inputs returning the resulting 32 bytes separately. +fn generic_hash_256(message: &[u8]) -> Result<[u8; 32], String> { + let output_bytes: [u8; 32] = + D::digest(message).as_slice().try_into().map_err(|_| "digest should be 256 bits")?; + + Ok(output_bytes) +} + +pub fn sha256(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { + generic_hash_256::(inputs) + .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::SHA256, err)) +} + +pub fn blake2s(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { + generic_hash_256::(inputs) + .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::Blake2s, err)) +} + +pub fn blake3(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { + Ok(blake3::hash(inputs).into()) +} + +pub fn keccak256(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { + generic_hash_256::(inputs) + .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::Keccak256, err)) +} + +pub fn sha256compression(state: &mut [u32; 8], msg_blocks: &[u32; 16]) { + let mut blocks = [0_u8; 64]; + for (i, block) in msg_blocks.iter().enumerate() { + let bytes = block.to_be_bytes(); + blocks[i * 4..i * 4 + 4].copy_from_slice(&bytes); + } + let blocks: GenericArray = blocks.into(); + sha2::compress256(state, &[blocks]); +} + +const KECCAK_LANES: usize = 25; + +pub fn keccakf1600( + mut state: [u64; KECCAK_LANES], +) -> Result<[u64; KECCAK_LANES], BlackBoxResolutionError> { + keccak::f1600(&mut state); + Ok(state) +} + +#[cfg(test)] +mod keccakf1600_tests { + use super::keccakf1600; + + #[test] + fn sanity_check() { + // Test vectors are copied from XKCP (eXtended Keccak Code Package) + // https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KeccakF-1600-IntermediateValues.txt + let zero_state = [0u64; 25]; + + let expected_state_first = [ + 0xF1258F7940E1DDE7, + 0x84D5CCF933C0478A, + 0xD598261EA65AA9EE, + 0xBD1547306F80494D, + 0x8B284E056253D057, + 0xFF97A42D7F8E6FD4, + 0x90FEE5A0A44647C4, + 0x8C5BDA0CD6192E76, + 0xAD30A6F71B19059C, + 0x30935AB7D08FFC64, + 0xEB5AA93F2317D635, + 0xA9A6E6260D712103, + 0x81A57C16DBCF555F, + 0x43B831CD0347C826, + 0x01F22F1A11A5569F, + 0x05E5635A21D9AE61, + 0x64BEFEF28CC970F2, + 0x613670957BC46611, + 0xB87C5A554FD00ECB, + 0x8C3EE88A1CCF32C8, + 0x940C7922AE3A2614, + 0x1841F924A2C509E4, + 0x16F53526E70465C2, + 0x75F644E97F30A13B, + 0xEAF1FF7B5CECA249, + ]; + let expected_state_second = [ + 0x2D5C954DF96ECB3C, + 0x6A332CD07057B56D, + 0x093D8D1270D76B6C, + 0x8A20D9B25569D094, + 0x4F9C4F99E5E7F156, + 0xF957B9A2DA65FB38, + 0x85773DAE1275AF0D, + 0xFAF4F247C3D810F7, + 0x1F1B9EE6F79A8759, + 0xE4FECC0FEE98B425, + 0x68CE61B6B9CE68A1, + 0xDEEA66C4BA8F974F, + 0x33C43D836EAFB1F5, + 0xE00654042719DBD9, + 0x7CF8A9F009831265, + 0xFD5449A6BF174743, + 0x97DDAD33D8994B40, + 0x48EAD5FC5D0BE774, + 0xE3B8C8EE55B7B03C, + 0x91A0226E649E42E9, + 0x900E3129E7BADD7B, + 0x202A9EC5FAA3CCE8, + 0x5B3402464E1C3DB6, + 0x609F4E62A44C1059, + 0x20D06CD26A8FBF5C, + ]; + + let state_first = keccakf1600(zero_state).unwrap(); + let state_second = keccakf1600(state_first).unwrap(); + + assert_eq!(state_first, expected_state_first); + assert_eq!(state_second, expected_state_second); + } +} diff --git a/noir/noir-repo/acvm-repo/blackbox_solver/src/lib.rs b/noir/noir-repo/acvm-repo/blackbox_solver/src/lib.rs index e033344fefa..dc798bdab32 100644 --- a/noir/noir-repo/acvm-repo/blackbox_solver/src/lib.rs +++ b/noir/noir-repo/acvm-repo/blackbox_solver/src/lib.rs @@ -8,456 +8,18 @@ //! For functions that have a reference implementation, such as [keccak256], this crate exports the reference implementation directly. use acir::BlackBoxFunc; -use blake2::digest::generic_array::GenericArray; -use blake2::{Blake2s256, Digest}; -use sha2::Sha256; -use sha3::Keccak256; use thiserror::Error; mod curve_specific_solver; +mod ecdsa; +mod hash; pub use curve_specific_solver::{BlackBoxFunctionSolver, StubbedBlackBoxSolver}; +pub use ecdsa::{ecdsa_secp256k1_verify, ecdsa_secp256r1_verify}; +pub use hash::{blake2s, blake3, keccak256, keccakf1600, sha256, sha256compression}; #[derive(Clone, PartialEq, Eq, Debug, Error)] pub enum BlackBoxResolutionError { #[error("failed to solve blackbox function: {0}, reason: {1}")] Failed(BlackBoxFunc, String), } - -pub fn sha256(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { - generic_hash_256::(inputs) - .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::SHA256, err)) -} - -pub fn blake2s(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { - generic_hash_256::(inputs) - .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::Blake2s, err)) -} - -pub fn blake3(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { - Ok(blake3::hash(inputs).into()) -} - -pub fn keccak256(inputs: &[u8]) -> Result<[u8; 32], BlackBoxResolutionError> { - generic_hash_256::(inputs) - .map_err(|err| BlackBoxResolutionError::Failed(BlackBoxFunc::Keccak256, err)) -} - -pub fn sha256compression(state: &mut [u32; 8], msg_blocks: &[u32; 16]) { - let mut blocks = [0_u8; 64]; - for (i, block) in msg_blocks.iter().enumerate() { - let bytes = block.to_be_bytes(); - blocks[i * 4..i * 4 + 4].copy_from_slice(&bytes); - } - let blocks: GenericArray = blocks.into(); - sha2::compress256(state, &[blocks]); -} - -const KECCAK_LANES: usize = 25; - -pub fn keccakf1600( - mut state: [u64; KECCAK_LANES], -) -> Result<[u64; KECCAK_LANES], BlackBoxResolutionError> { - keccak::f1600(&mut state); - Ok(state) -} - -pub fn ecdsa_secp256k1_verify( - hashed_msg: &[u8], - public_key_x: &[u8; 32], - public_key_y: &[u8; 32], - signature: &[u8; 64], -) -> Result { - Ok(verify_secp256k1_ecdsa_signature(hashed_msg, public_key_x, public_key_y, signature)) -} - -pub fn ecdsa_secp256r1_verify( - hashed_msg: &[u8], - public_key_x: &[u8; 32], - public_key_y: &[u8; 32], - signature: &[u8; 64], -) -> Result { - Ok(verify_secp256r1_ecdsa_signature(hashed_msg, public_key_x, public_key_y, signature)) -} - -/// Does a generic hash of the inputs returning the resulting 32 bytes separately. -fn generic_hash_256(message: &[u8]) -> Result<[u8; 32], String> { - let output_bytes: [u8; 32] = - D::digest(message).as_slice().try_into().map_err(|_| "digest should be 256 bits")?; - - Ok(output_bytes) -} - -fn verify_secp256k1_ecdsa_signature( - hashed_msg: &[u8], - public_key_x_bytes: &[u8; 32], - public_key_y_bytes: &[u8; 32], - signature: &[u8; 64], -) -> bool { - use k256::elliptic_curve::sec1::FromEncodedPoint; - use k256::elliptic_curve::PrimeField; - - use k256::{ecdsa::Signature, Scalar}; - use k256::{ - elliptic_curve::{ - sec1::{Coordinates, ToEncodedPoint}, - IsHigh, - }, - AffinePoint, EncodedPoint, ProjectivePoint, PublicKey, - }; - // Convert the inputs into k256 data structures - - let Ok(signature) = Signature::try_from(signature.as_slice()) else { - // Signature `r` and `s` are forbidden from being zero. - return false; - }; - - let point = EncodedPoint::from_affine_coordinates( - public_key_x_bytes.into(), - public_key_y_bytes.into(), - true, - ); - - let pubkey = PublicKey::from_encoded_point(&point); - let pubkey = if pubkey.is_some().into() { - pubkey.unwrap() - } else { - // Public key must sit on the Secp256k1 curve. - return false; - }; - - // Note: This is incorrect as it will panic if `hashed_msg >= k256::Secp256k1::ORDER`. - // In this scenario we should just take the leftmost bits from `hashed_msg` up to the group order length. - let z = Scalar::from_repr(*GenericArray::from_slice(hashed_msg)).unwrap(); - - // Finished converting bytes into data structures - - let r = signature.r(); - let s = signature.s(); - - // Ensure signature is "low S" normalized ala BIP 0062 - if s.is_high().into() { - return false; - } - - let s_inv = s.invert().unwrap(); - let u1 = z * s_inv; - let u2 = *r * s_inv; - - #[allow(non_snake_case)] - let R: AffinePoint = ((ProjectivePoint::GENERATOR * u1) - + (ProjectivePoint::from(*pubkey.as_affine()) * u2)) - .to_affine(); - - match R.to_encoded_point(false).coordinates() { - Coordinates::Uncompressed { x, y: _ } => Scalar::from_repr(*x).unwrap().eq(&r), - _ => unreachable!("Point is uncompressed"), - } -} - -fn verify_secp256r1_ecdsa_signature( - hashed_msg: &[u8], - public_key_x_bytes: &[u8; 32], - public_key_y_bytes: &[u8; 32], - signature: &[u8; 64], -) -> bool { - use p256::elliptic_curve::sec1::FromEncodedPoint; - use p256::elliptic_curve::PrimeField; - - use p256::{ecdsa::Signature, Scalar}; - use p256::{ - elliptic_curve::{ - sec1::{Coordinates, ToEncodedPoint}, - IsHigh, - }, - AffinePoint, EncodedPoint, ProjectivePoint, PublicKey, - }; - - // Convert the inputs into k256 data structures - - let Ok(signature) = Signature::try_from(signature.as_slice()) else { - // Signature `r` and `s` are forbidden from being zero. - return false; - }; - - let point = EncodedPoint::from_affine_coordinates( - public_key_x_bytes.into(), - public_key_y_bytes.into(), - true, - ); - - let pubkey = PublicKey::from_encoded_point(&point); - let pubkey = if pubkey.is_some().into() { - pubkey.unwrap() - } else { - // Public key must sit on the Secp256r1 curve. - return false; - }; - - // Note: This is incorrect as it will panic if `hashed_msg >= p256::NistP256::ORDER`. - // In this scenario we should just take the leftmost bits from `hashed_msg` up to the group order length. - let z = Scalar::from_repr(*GenericArray::from_slice(hashed_msg)).unwrap(); - - // Finished converting bytes into data structures - - let r = signature.r(); - let s = signature.s(); - - // Ensure signature is "low S" normalized ala BIP 0062 - if s.is_high().into() { - return false; - } - - let s_inv = s.invert().unwrap(); - let u1 = z * s_inv; - let u2 = *r * s_inv; - - #[allow(non_snake_case)] - let R: AffinePoint = ((ProjectivePoint::GENERATOR * u1) - + (ProjectivePoint::from(*pubkey.as_affine()) * u2)) - .to_affine(); - - match R.to_encoded_point(false).coordinates() { - Coordinates::Uncompressed { x, y: _ } => Scalar::from_repr(*x).unwrap().eq(&r), - _ => unreachable!("Point is uncompressed"), - } -} - -#[cfg(test)] -mod keccakf1600_tests { - use crate::keccakf1600; - - #[test] - fn sanity_check() { - // Test vectors are copied from XKCP (eXtended Keccak Code Package) - // https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KeccakF-1600-IntermediateValues.txt - let zero_state = [0u64; 25]; - - let expected_state_first = [ - 0xF1258F7940E1DDE7, - 0x84D5CCF933C0478A, - 0xD598261EA65AA9EE, - 0xBD1547306F80494D, - 0x8B284E056253D057, - 0xFF97A42D7F8E6FD4, - 0x90FEE5A0A44647C4, - 0x8C5BDA0CD6192E76, - 0xAD30A6F71B19059C, - 0x30935AB7D08FFC64, - 0xEB5AA93F2317D635, - 0xA9A6E6260D712103, - 0x81A57C16DBCF555F, - 0x43B831CD0347C826, - 0x01F22F1A11A5569F, - 0x05E5635A21D9AE61, - 0x64BEFEF28CC970F2, - 0x613670957BC46611, - 0xB87C5A554FD00ECB, - 0x8C3EE88A1CCF32C8, - 0x940C7922AE3A2614, - 0x1841F924A2C509E4, - 0x16F53526E70465C2, - 0x75F644E97F30A13B, - 0xEAF1FF7B5CECA249, - ]; - let expected_state_second = [ - 0x2D5C954DF96ECB3C, - 0x6A332CD07057B56D, - 0x093D8D1270D76B6C, - 0x8A20D9B25569D094, - 0x4F9C4F99E5E7F156, - 0xF957B9A2DA65FB38, - 0x85773DAE1275AF0D, - 0xFAF4F247C3D810F7, - 0x1F1B9EE6F79A8759, - 0xE4FECC0FEE98B425, - 0x68CE61B6B9CE68A1, - 0xDEEA66C4BA8F974F, - 0x33C43D836EAFB1F5, - 0xE00654042719DBD9, - 0x7CF8A9F009831265, - 0xFD5449A6BF174743, - 0x97DDAD33D8994B40, - 0x48EAD5FC5D0BE774, - 0xE3B8C8EE55B7B03C, - 0x91A0226E649E42E9, - 0x900E3129E7BADD7B, - 0x202A9EC5FAA3CCE8, - 0x5B3402464E1C3DB6, - 0x609F4E62A44C1059, - 0x20D06CD26A8FBF5C, - ]; - - let state_first = keccakf1600(zero_state).unwrap(); - let state_second = keccakf1600(state_first).unwrap(); - - assert_eq!(state_first, expected_state_first); - assert_eq!(state_second, expected_state_second); - } -} - -#[cfg(test)] -mod secp256k1_tests { - use super::verify_secp256k1_ecdsa_signature; - - // 0x3a73f4123a5cd2121f21cd7e8d358835476949d035d9c2da6806b4633ac8c1e2, - const HASHED_MESSAGE: [u8; 32] = [ - 0x3a, 0x73, 0xf4, 0x12, 0x3a, 0x5c, 0xd2, 0x12, 0x1f, 0x21, 0xcd, 0x7e, 0x8d, 0x35, 0x88, - 0x35, 0x47, 0x69, 0x49, 0xd0, 0x35, 0xd9, 0xc2, 0xda, 0x68, 0x06, 0xb4, 0x63, 0x3a, 0xc8, - 0xc1, 0xe2, - ]; - // 0xa0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7 - const PUB_KEY_X: [u8; 32] = [ - 0xa0, 0x43, 0x4d, 0x9e, 0x47, 0xf3, 0xc8, 0x62, 0x35, 0x47, 0x7c, 0x7b, 0x1a, 0xe6, 0xae, - 0x5d, 0x34, 0x42, 0xd4, 0x9b, 0x19, 0x43, 0xc2, 0xb7, 0x52, 0xa6, 0x8e, 0x2a, 0x47, 0xe2, - 0x47, 0xc7, - ]; - // 0x893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7 - const PUB_KEY_Y: [u8; 32] = [ - 0x89, 0x3a, 0xba, 0x42, 0x54, 0x19, 0xbc, 0x27, 0xa3, 0xb6, 0xc7, 0xe6, 0x93, 0xa2, 0x4c, - 0x69, 0x6f, 0x79, 0x4c, 0x2e, 0xd8, 0x77, 0xa1, 0x59, 0x3c, 0xbe, 0xe5, 0x3b, 0x03, 0x73, - 0x68, 0xd7, - ]; - // 0xe5081c80ab427dc370346f4a0e31aa2bad8d9798c38061db9ae55a4e8df454fd28119894344e71b78770cc931d61f480ecbb0b89d6eb69690161e49a715fcd55 - const SIGNATURE: [u8; 64] = [ - 0xe5, 0x08, 0x1c, 0x80, 0xab, 0x42, 0x7d, 0xc3, 0x70, 0x34, 0x6f, 0x4a, 0x0e, 0x31, 0xaa, - 0x2b, 0xad, 0x8d, 0x97, 0x98, 0xc3, 0x80, 0x61, 0xdb, 0x9a, 0xe5, 0x5a, 0x4e, 0x8d, 0xf4, - 0x54, 0xfd, 0x28, 0x11, 0x98, 0x94, 0x34, 0x4e, 0x71, 0xb7, 0x87, 0x70, 0xcc, 0x93, 0x1d, - 0x61, 0xf4, 0x80, 0xec, 0xbb, 0x0b, 0x89, 0xd6, 0xeb, 0x69, 0x69, 0x01, 0x61, 0xe4, 0x9a, - 0x71, 0x5f, 0xcd, 0x55, - ]; - - #[test] - fn verifies_valid_signature_with_low_s_value() { - let valid = - verify_secp256k1_ecdsa_signature(&HASHED_MESSAGE, &PUB_KEY_X, &PUB_KEY_Y, &SIGNATURE); - - assert!(valid); - } - - #[test] - fn rejects_invalid_signature() { - // This signature is invalid as ECDSA specifies that `r` and `s` must be non-zero. - let invalid_signature: [u8; 64] = [0x00; 64]; - - let valid = verify_secp256k1_ecdsa_signature( - &HASHED_MESSAGE, - &PUB_KEY_X, - &PUB_KEY_Y, - &invalid_signature, - ); - assert!(!valid); - } - - #[test] - fn rejects_invalid_public_key() { - let invalid_pub_key_x: [u8; 32] = [0xff; 32]; - let invalid_pub_key_y: [u8; 32] = [0xff; 32]; - - let valid = verify_secp256k1_ecdsa_signature( - &HASHED_MESSAGE, - &invalid_pub_key_x, - &invalid_pub_key_y, - &SIGNATURE, - ); - - assert!(!valid); - } - - #[test] - #[ignore = "ECDSA verification does not currently handle long hashes correctly"] - fn trims_overly_long_hashes_to_correct_length() { - let mut long_hashed_message = HASHED_MESSAGE.to_vec(); - long_hashed_message.push(0xff); - - let valid = verify_secp256k1_ecdsa_signature( - &long_hashed_message, - &PUB_KEY_X, - &PUB_KEY_Y, - &SIGNATURE, - ); - - assert!(valid); - } -} - -#[cfg(test)] -mod secp256r1_tests { - use super::verify_secp256r1_ecdsa_signature; - - // 0x54705ba3baafdbdfba8c5f9a70f7a89bee98d906b53e31074da7baecdc0da9ad - const HASHED_MESSAGE: [u8; 32] = [ - 84, 112, 91, 163, 186, 175, 219, 223, 186, 140, 95, 154, 112, 247, 168, 155, 238, 152, 217, - 6, 181, 62, 49, 7, 77, 167, 186, 236, 220, 13, 169, 173, - ]; - // 0x550f471003f3df97c3df506ac797f6721fb1a1fb7b8f6f83d224498a65c88e24 - const PUB_KEY_X: [u8; 32] = [ - 85, 15, 71, 16, 3, 243, 223, 151, 195, 223, 80, 106, 199, 151, 246, 114, 31, 177, 161, 251, - 123, 143, 111, 131, 210, 36, 73, 138, 101, 200, 142, 36, - ]; - // 0x136093d7012e509a73715cbd0b00a3cc0ff4b5c01b3ffa196ab1fb327036b8e6 - const PUB_KEY_Y: [u8; 32] = [ - 19, 96, 147, 215, 1, 46, 80, 154, 115, 113, 92, 189, 11, 0, 163, 204, 15, 244, 181, 192, - 27, 63, 250, 25, 106, 177, 251, 50, 112, 54, 184, 230, - ]; - // 0x2c70a8d084b62bfc5ce03641caf9f72ad4da8c81bfe6ec9487bb5e1bef62a13218ad9ee29eaf351fdc50f1520c425e9b908a07278b43b0ec7b872778c14e0784 - const SIGNATURE: [u8; 64] = [ - 44, 112, 168, 208, 132, 182, 43, 252, 92, 224, 54, 65, 202, 249, 247, 42, 212, 218, 140, - 129, 191, 230, 236, 148, 135, 187, 94, 27, 239, 98, 161, 50, 24, 173, 158, 226, 158, 175, - 53, 31, 220, 80, 241, 82, 12, 66, 94, 155, 144, 138, 7, 39, 139, 67, 176, 236, 123, 135, - 39, 120, 193, 78, 7, 132, - ]; - - #[test] - fn verifies_valid_signature_with_low_s_value() { - let valid = - verify_secp256r1_ecdsa_signature(&HASHED_MESSAGE, &PUB_KEY_X, &PUB_KEY_Y, &SIGNATURE); - - assert!(valid); - } - - #[test] - fn rejects_invalid_signature() { - // This signature is invalid as ECDSA specifies that `r` and `s` must be non-zero. - let invalid_signature: [u8; 64] = [0x00; 64]; - - let valid = verify_secp256r1_ecdsa_signature( - &HASHED_MESSAGE, - &PUB_KEY_X, - &PUB_KEY_Y, - &invalid_signature, - ); - assert!(!valid); - } - - #[test] - fn rejects_invalid_public_key() { - let invalid_pub_key_x: [u8; 32] = [0xff; 32]; - let invalid_pub_key_y: [u8; 32] = [0xff; 32]; - - let valid = verify_secp256r1_ecdsa_signature( - &HASHED_MESSAGE, - &invalid_pub_key_x, - &invalid_pub_key_y, - &SIGNATURE, - ); - - assert!(!valid); - } - - #[test] - #[ignore = "ECDSA verification does not currently handle long hashes correctly"] - fn trims_overly_long_hashes_to_correct_length() { - let mut long_hashed_message = HASHED_MESSAGE.to_vec(); - long_hashed_message.push(0xff); - - let valid = verify_secp256r1_ecdsa_signature( - &long_hashed_message, - &PUB_KEY_X, - &PUB_KEY_Y, - &SIGNATURE, - ); - - assert!(valid); - } -} diff --git a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/Cargo.toml b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/Cargo.toml index ea601a6b80f..a0a15409604 100644 --- a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/Cargo.toml +++ b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/Cargo.toml @@ -32,7 +32,7 @@ ark-ff = { version = "^0.4.0", default-features = false } num-bigint.workspace = true [target.'cfg(target_arch = "wasm32")'.dependencies] -wasmer = { version = "4.2.3", default-features = false, features = [ +wasmer = { version = "4.2.6", default-features = false, features = [ "js-default", ] } @@ -42,7 +42,7 @@ js-sys.workspace = true [target.'cfg(not(target_arch = "wasm32"))'.dependencies] getrandom.workspace = true -wasmer = "4.2.3" +wasmer = "4.2.6" [build-dependencies] pkg-config = "0.3" diff --git a/noir/noir-repo/acvm-repo/brillig/Cargo.toml b/noir/noir-repo/acvm-repo/brillig/Cargo.toml index 8d91d19e117..57f89e091b4 100644 --- a/noir/noir-repo/acvm-repo/brillig/Cargo.toml +++ b/noir/noir-repo/acvm-repo/brillig/Cargo.toml @@ -2,7 +2,7 @@ name = "brillig" description = "Brillig is the bytecode ACIR uses for non-determinism." # x-release-please-start-version -version = "0.40.0" +version = "0.41.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/brillig_vm/Cargo.toml b/noir/noir-repo/acvm-repo/brillig_vm/Cargo.toml index 272e8389413..1c7add5cb40 100644 --- a/noir/noir-repo/acvm-repo/brillig_vm/Cargo.toml +++ b/noir/noir-repo/acvm-repo/brillig_vm/Cargo.toml @@ -2,7 +2,7 @@ name = "brillig_vm" description = "The virtual machine that processes Brillig bytecode, used to introduce non-determinism to the ACVM" # x-release-please-start-version -version = "0.40.0" +version = "0.41.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/aztec_macros/src/lib.rs b/noir/noir-repo/aztec_macros/src/lib.rs index 1285dab33ab..1f3546cbb6a 100644 --- a/noir/noir-repo/aztec_macros/src/lib.rs +++ b/noir/noir-repo/aztec_macros/src/lib.rs @@ -1,27 +1,26 @@ -use std::borrow::{Borrow, BorrowMut}; -use std::vec; +mod transforms; +mod utils; + +use transforms::{ + compute_note_hash_and_nullifier::inject_compute_note_hash_and_nullifier, + events::{generate_selector_impl, transform_events}, + functions::{transform_function, transform_unconstrained, transform_vm_function}, + storage::{ + assign_storage_slots, check_for_storage_definition, check_for_storage_implementation, + generate_storage_implementation, + }, +}; -use convert_case::{Case, Casing}; -use iter_extended::vecmap; -use noirc_errors::{Location, Spanned}; use noirc_frontend::hir::def_collector::dc_crate::{UnresolvedFunctions, UnresolvedTraitImpl}; -use noirc_frontend::hir::def_map::{LocalModuleId, ModuleId}; -use noirc_frontend::macros_api::parse_program; -use noirc_frontend::macros_api::FieldElement; -use noirc_frontend::macros_api::{ - BlockExpression, CallExpression, CastExpression, Distinctness, Expression, ExpressionKind, - ForLoopStatement, ForRange, FunctionDefinition, FunctionReturnType, FunctionVisibility, - HirContext, HirExpression, HirLiteral, HirStatement, Ident, IndexExpression, LetStatement, - Literal, MemberAccessExpression, MethodCallExpression, NoirFunction, NoirStruct, Param, Path, - PathKind, Pattern, PrefixExpression, SecondaryAttribute, Signedness, Span, Statement, - StatementKind, StructType, Type, TypeImpl, UnaryOp, UnresolvedType, UnresolvedTypeData, - Visibility, -}; -use noirc_frontend::macros_api::{CrateId, FileId}; -use noirc_frontend::macros_api::{MacroError, MacroProcessor}; -use noirc_frontend::macros_api::{ModuleDefId, NodeInterner, SortedModule, StructId}; -use noirc_frontend::node_interner::{FuncId, TraitId, TraitImplId, TraitImplKind}; -use noirc_frontend::{BinaryOpKind, ConstrainKind, ConstrainStatement, InfixExpression, Lambda}; + +use noirc_frontend::macros_api::SortedModule; +use noirc_frontend::macros_api::{CrateId, MacroError}; +use noirc_frontend::macros_api::{FileId, MacroProcessor}; +use noirc_frontend::macros_api::{HirContext, SecondaryAttribute, Span}; + +use utils::ast_utils::is_custom_attribute; +use utils::checks::{check_for_aztec_dependency, has_aztec_dependency}; +use utils::{constants::MAX_CONTRACT_PRIVATE_FUNCTIONS, errors::AztecMacroError}; pub struct AztecMacro; impl MacroProcessor for AztecMacro { @@ -34,23 +33,14 @@ impl MacroProcessor for AztecMacro { transform(ast, crate_id, context) } - fn process_unresolved_traits_impls( + fn process_collected_defs( &self, crate_id: &CrateId, context: &mut HirContext, - unresolved_traits_impls: &[UnresolvedTraitImpl], - collected_functions: &mut Vec, + collected_trait_impls: &[UnresolvedTraitImpl], + collected_functions: &mut [UnresolvedFunctions], ) -> Result<(), (MacroError, FileId)> { - if has_aztec_dependency(crate_id, context) { - inject_compute_note_hash_and_nullifier( - crate_id, - context, - unresolved_traits_impls, - collected_functions, - ) - } else { - Ok(()) - } + transform_collected_defs(crate_id, context, collected_trait_impls, collected_functions) } fn process_typed_ast( @@ -62,225 +52,6 @@ impl MacroProcessor for AztecMacro { } } -const FUNCTION_TREE_HEIGHT: u32 = 5; -const MAX_CONTRACT_PRIVATE_FUNCTIONS: usize = 2_usize.pow(FUNCTION_TREE_HEIGHT); - -#[derive(Debug, Clone)] -pub enum AztecMacroError { - AztecDepNotFound, - ContractHasTooManyPrivateFunctions { span: Span }, - ContractConstructorMissing { span: Span }, - UnsupportedFunctionArgumentType { span: Span, typ: UnresolvedTypeData }, - UnsupportedStorageType { span: Option, typ: UnresolvedTypeData }, - CouldNotAssignStorageSlots { secondary_message: Option }, - EventError { span: Span, message: String }, - UnsupportedAttributes { span: Span, secondary_message: Option }, -} - -impl From for MacroError { - fn from(err: AztecMacroError) -> Self { - match err { - AztecMacroError::AztecDepNotFound {} => MacroError { - primary_message: "Aztec dependency not found. Please add aztec as a dependency in your Cargo.toml. For more information go to https://docs.aztec.network/developers/debugging/aztecnr-errors#aztec-dependency-not-found-please-add-aztec-as-a-dependency-in-your-nargotoml".to_owned(), - secondary_message: None, - span: None, - }, - AztecMacroError::ContractHasTooManyPrivateFunctions { span } => MacroError { - primary_message: format!("Contract can only have a maximum of {} private functions", MAX_CONTRACT_PRIVATE_FUNCTIONS), - secondary_message: None, - span: Some(span), - }, - AztecMacroError::ContractConstructorMissing { span } => MacroError { - primary_message: "Contract must have a constructor function".to_owned(), - secondary_message: None, - span: Some(span), - }, - AztecMacroError::UnsupportedFunctionArgumentType { span, typ } => MacroError { - primary_message: format!("Provided parameter type `{typ:?}` is not supported in Aztec contract interface"), - secondary_message: None, - span: Some(span), - }, - AztecMacroError::UnsupportedStorageType { span, typ } => MacroError { - primary_message: format!("Provided storage type `{typ:?}` is not directly supported in Aztec. Please provide a custom storage implementation"), - secondary_message: None, - span, - }, - AztecMacroError::CouldNotAssignStorageSlots { secondary_message } => MacroError { - primary_message: "Could not assign storage slots, please provide a custom storage implementation".to_string(), - secondary_message, - span: None, - }, - AztecMacroError::EventError { span, message } => MacroError { - primary_message: message, - secondary_message: None, - span: Some(span), - }, - AztecMacroError::UnsupportedAttributes { span, secondary_message } => MacroError { - primary_message: "Unsupported attributes in contract function".to_string(), - secondary_message, - span: Some(span), - }, - } - } -} - -// -// Helper macros for creating noir ast nodes -// -fn ident(name: &str) -> Ident { - Ident::new(name.to_string(), Span::default()) -} - -fn ident_path(name: &str) -> Path { - Path::from_ident(ident(name)) -} - -fn path(ident: Ident) -> Path { - Path::from_ident(ident) -} - -fn expression(kind: ExpressionKind) -> Expression { - Expression::new(kind, Span::default()) -} - -fn variable(name: &str) -> Expression { - expression(ExpressionKind::Variable(ident_path(name))) -} - -fn variable_ident(identifier: Ident) -> Expression { - expression(ExpressionKind::Variable(path(identifier))) -} - -fn variable_path(path: Path) -> Expression { - expression(ExpressionKind::Variable(path)) -} - -fn method_call(object: Expression, method_name: &str, arguments: Vec) -> Expression { - expression(ExpressionKind::MethodCall(Box::new(MethodCallExpression { - object, - method_name: ident(method_name), - arguments, - }))) -} - -fn call(func: Expression, arguments: Vec) -> Expression { - expression(ExpressionKind::Call(Box::new(CallExpression { func: Box::new(func), arguments }))) -} - -fn pattern(name: &str) -> Pattern { - Pattern::Identifier(ident(name)) -} - -fn mutable(name: &str) -> Pattern { - Pattern::Mutable(Box::new(pattern(name)), Span::default(), true) -} - -fn mutable_assignment(name: &str, assigned_to: Expression) -> Statement { - make_statement(StatementKind::Let(LetStatement { - pattern: mutable(name), - r#type: make_type(UnresolvedTypeData::Unspecified), - expression: assigned_to, - })) -} - -fn mutable_reference(variable_name: &str) -> Expression { - expression(ExpressionKind::Prefix(Box::new(PrefixExpression { - operator: UnaryOp::MutableReference, - rhs: variable(variable_name), - }))) -} - -fn assignment(name: &str, assigned_to: Expression) -> Statement { - make_statement(StatementKind::Let(LetStatement { - pattern: pattern(name), - r#type: make_type(UnresolvedTypeData::Unspecified), - expression: assigned_to, - })) -} - -fn member_access(lhs: &str, rhs: &str) -> Expression { - expression(ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { - lhs: variable(lhs), - rhs: ident(rhs), - }))) -} - -fn return_type(path: Path) -> FunctionReturnType { - let ty = make_type(UnresolvedTypeData::Named(path, vec![], true)); - FunctionReturnType::Ty(ty) -} - -fn lambda(parameters: Vec<(Pattern, UnresolvedType)>, body: Expression) -> Expression { - expression(ExpressionKind::Lambda(Box::new(Lambda { - parameters, - return_type: UnresolvedType { - typ: UnresolvedTypeData::Unspecified, - span: Some(Span::default()), - }, - body, - }))) -} - -fn make_eq(lhs: Expression, rhs: Expression) -> Expression { - expression(ExpressionKind::Infix(Box::new(InfixExpression { - lhs, - rhs, - operator: Spanned::from(Span::default(), BinaryOpKind::Equal), - }))) -} - -macro_rules! chained_path { - ( $base:expr ) => { - { - ident_path($base) - } - }; - ( $base:expr $(, $tail:expr)* ) => { - { - let mut base_path = ident_path($base); - $( - base_path.segments.push(ident($tail)); - )* - base_path - } - } -} - -macro_rules! chained_dep { - ( $base:expr $(, $tail:expr)* ) => { - { - let mut base_path = ident_path($base); - base_path.kind = PathKind::Dep; - $( - base_path.segments.push(ident($tail)); - )* - base_path - } - } -} - -fn cast(lhs: Expression, ty: UnresolvedTypeData) -> Expression { - expression(ExpressionKind::Cast(Box::new(CastExpression { lhs, r#type: make_type(ty) }))) -} - -fn make_type(typ: UnresolvedTypeData) -> UnresolvedType { - UnresolvedType { typ, span: Some(Span::default()) } -} - -fn index_array(array: Ident, index: &str) -> Expression { - expression(ExpressionKind::Index(Box::new(IndexExpression { - collection: variable_path(path(array)), - index: variable(index), - }))) -} - -fn index_array_variable(array: Expression, index: &str) -> Expression { - expression(ExpressionKind::Index(Box::new(IndexExpression { - collection: array, - index: variable(index), - }))) -} - // // Create AST Nodes for Aztec // @@ -293,7 +64,6 @@ fn transform( context: &HirContext, ) -> Result { // Usage -> mut ast -> aztec_library::transform(&mut ast) - // Covers all functions in the ast for submodule in ast.submodules.iter_mut().filter(|submodule| submodule.is_contract) { if transform_module(&mut submodule.contents, crate_id, context) @@ -305,97 +75,6 @@ fn transform( Ok(ast) } -// -// Transform Hir Nodes for Aztec -// - -/// Completes the Hir with data gathered from type resolution -fn transform_hir( - crate_id: &CrateId, - context: &mut HirContext, -) -> Result<(), (AztecMacroError, FileId)> { - transform_events(crate_id, context)?; - assign_storage_slots(crate_id, context) -} - -/// Creates an error alerting the user that they have not downloaded the Aztec-noir library -fn check_for_aztec_dependency( - crate_id: &CrateId, - context: &HirContext, -) -> Result<(), (MacroError, FileId)> { - if has_aztec_dependency(crate_id, context) { - Ok(()) - } else { - Err((AztecMacroError::AztecDepNotFound.into(), context.crate_graph[crate_id].root_file_id)) - } -} - -fn has_aztec_dependency(crate_id: &CrateId, context: &HirContext) -> bool { - context.crate_graph[crate_id].dependencies.iter().any(|dep| dep.as_name() == "aztec") -} - -// Check to see if the user has defined a storage struct -fn check_for_storage_definition(module: &SortedModule) -> bool { - module.types.iter().any(|r#struct| r#struct.name.0.contents == "Storage") -} - -// Check to see if the user has defined a storage struct -fn check_for_storage_implementation(module: &SortedModule) -> bool { - module.impls.iter().any(|r#impl| match &r#impl.object_type.typ { - UnresolvedTypeData::Named(path, _, _) => { - path.segments.last().is_some_and(|segment| segment.0.contents == "Storage") - } - _ => false, - }) -} - -// Check if "compute_note_hash_and_nullifier(AztecAddress,Field,Field,Field,[Field; N]) -> [Field; 4]" is defined -fn check_for_compute_note_hash_and_nullifier_definition( - functions_data: &[(LocalModuleId, FuncId, NoirFunction)], - module_id: LocalModuleId, -) -> bool { - functions_data.iter().filter(|func_data| func_data.0 == module_id).any(|func_data| { - func_data.2.def.name.0.contents == "compute_note_hash_and_nullifier" - && func_data.2.def.parameters.len() == 5 - && match &func_data.2.def.parameters[0].typ.typ { - UnresolvedTypeData::Named(path, _, _) => path.segments.last().unwrap().0.contents == "AztecAddress", - _ => false, - } - && func_data.2.def.parameters[1].typ.typ == UnresolvedTypeData::FieldElement - && func_data.2.def.parameters[2].typ.typ == UnresolvedTypeData::FieldElement - && func_data.2.def.parameters[3].typ.typ == UnresolvedTypeData::FieldElement - // checks if the 5th parameter is an array and the Box in - // Array(Option, Box) contains only fields - && match &func_data.2.def.parameters[4].typ.typ { - UnresolvedTypeData::Array(_, inner_type) => { - matches!(inner_type.typ, UnresolvedTypeData::FieldElement) - }, - _ => false, - } - // We check the return type the same way as we did the 5th parameter - && match &func_data.2.def.return_type { - FunctionReturnType::Default(_) => false, - FunctionReturnType::Ty(unresolved_type) => { - match &unresolved_type.typ { - UnresolvedTypeData::Array(_, inner_type) => { - matches!(inner_type.typ, UnresolvedTypeData::FieldElement) - }, - _ => false, - } - } - } - }) -} - -/// Checks if an attribute is a custom attribute with a specific name -fn is_custom_attribute(attr: &SecondaryAttribute, attribute_name: &str) -> bool { - if let SecondaryAttribute::Custom(custom_attr) = attr { - custom_attr.as_str() == attribute_name - } else { - false - } -} - /// Determines if ast nodes are annotated with aztec attributes. /// For annotated functions it calls the `transform` function which will perform the required transformations. /// Returns true if an annotated node is found, false otherwise @@ -472,10 +151,7 @@ fn transform_module( transform_vm_function(func, storage_defined) .map_err(|err| (err, crate_graph.root_file_id))?; has_transformed_module = true; - } - - // Add the storage struct to the beginning of the function if it is unconstrained in an aztec contract - if storage_defined && func.def.is_unconstrained { + } else if storage_defined && func.def.is_unconstrained { transform_unconstrained(func); has_transformed_module = true; } @@ -517,1409 +193,33 @@ fn transform_module( Ok(has_transformed_module) } -/// Auxiliary function to generate the storage constructor for a given field, using -/// the Storage definition as a reference. Supports nesting. -fn generate_storage_field_constructor( - (type_ident, unresolved_type): &(Ident, UnresolvedType), - slot: Expression, -) -> Result { - let typ = &unresolved_type.typ; - match typ { - UnresolvedTypeData::Named(path, generics, _) => { - let mut new_path = path.clone().to_owned(); - new_path.segments.push(ident("new")); - match path.segments.last().unwrap().0.contents.as_str() { - "Map" => Ok(call( - variable_path(new_path), - vec![ - variable("context"), - slot, - lambda( - vec![ - ( - pattern("context"), - make_type(UnresolvedTypeData::Named( - chained_dep!("aztec", "context", "Context"), - vec![], - true, - )), - ), - ( - Pattern::Identifier(ident("slot")), - make_type(UnresolvedTypeData::FieldElement), - ), - ], - generate_storage_field_constructor( - &(type_ident.clone(), generics.iter().last().unwrap().clone()), - variable("slot"), - )?, - ), - ], - )), - _ => Ok(call(variable_path(new_path), vec![variable("context"), slot])), - } - } - _ => Err(AztecMacroError::UnsupportedStorageType { - typ: typ.clone(), - span: Some(type_ident.span()), - }), - } -} - -// Generates the Storage implementation block from the Storage struct definition if it does not exist -/// From: -/// -/// struct Storage { -/// a_map: Map>, -/// a_nested_map: Map>>, -/// a_field: SomeStoragePrimitive, -/// } -/// -/// To: -/// -/// impl Storage { -/// fn init(context: Context) -> Self { -/// Storage { -/// a_map: Map::new(context, 0, |context, slot| { -/// SomeStoragePrimitive::new(context, slot) -/// }), -/// a_nested_map: Map::new(context, 0, |context, slot| { -/// Map::new(context, slot, |context, slot| { -/// SomeStoragePrimitive::new(context, slot) -/// }) -/// }), -/// a_field: SomeStoragePrimitive::new(context, 0), -/// } -/// } -/// } -/// -/// Storage slots are generated as 0 and will be populated using the information from the HIR -/// at a later stage. -fn generate_storage_implementation(module: &mut SortedModule) -> Result<(), AztecMacroError> { - let definition = - module.types.iter().find(|r#struct| r#struct.name.0.contents == "Storage").unwrap(); - - let slot_zero = expression(ExpressionKind::Literal(Literal::Integer( - FieldElement::from(i128::from(0)), - false, - ))); - - let field_constructors = definition - .fields - .iter() - .flat_map(|field| { - generate_storage_field_constructor(field, slot_zero.clone()) - .map(|expression| (field.0.clone(), expression)) - }) - .collect(); - - let storage_constructor_statement = make_statement(StatementKind::Expression(expression( - ExpressionKind::constructor((chained_path!("Storage"), field_constructors)), - ))); - - let init = NoirFunction::normal(FunctionDefinition::normal( - &ident("init"), - &vec![], - &[( - ident("context"), - make_type(UnresolvedTypeData::Named( - chained_dep!("aztec", "context", "Context"), - vec![], - true, - )), - )], - &BlockExpression(vec![storage_constructor_statement]), - &[], - &return_type(chained_path!("Self")), - )); - - let storage_impl = TypeImpl { - object_type: UnresolvedType { - typ: UnresolvedTypeData::Named(chained_path!("Storage"), vec![], true), - span: Some(Span::default()), - }, - type_span: Span::default(), - generics: vec![], - methods: vec![(init, Span::default())], - }; - module.impls.push(storage_impl); - - Ok(()) -} - -/// If it does, it will insert the following things: -/// - A new Input that is provided for a kernel app circuit, named: {Public/Private}ContextInputs -/// - Hashes all of the function input variables -/// - This instantiates a helper function -fn transform_function( - ty: &str, - func: &mut NoirFunction, - storage_defined: bool, - is_initializer: bool, - insert_init_check: bool, - is_internal: bool, -) -> Result<(), AztecMacroError> { - let context_name = format!("{}Context", ty); - let inputs_name = format!("{}ContextInputs", ty); - let return_type_name = format!("{}CircuitPublicInputs", ty); - - // Add check that msg sender equals this address and flag function as internal - if is_internal { - let is_internal_check = create_internal_check(func.name()); - func.def.body.0.insert(0, is_internal_check); - func.def.is_internal = true; - } - - // Add initialization check - if insert_init_check { - let init_check = create_init_check(); - func.def.body.0.insert(0, init_check); - } - - // Add access to the storage struct - if storage_defined { - let storage_def = abstract_storage(&ty.to_lowercase(), false); - func.def.body.0.insert(0, storage_def); - } - - // Insert the context creation as the first action - let create_context = create_context(&context_name, &func.def.parameters)?; - func.def.body.0.splice(0..0, (create_context).iter().cloned()); - - // Add the inputs to the params - let input = create_inputs(&inputs_name); - func.def.parameters.insert(0, input); - - // Abstract return types such that they get added to the kernel's return_values - if let Some(return_values) = abstract_return_values(func) { - // In case we are pushing return values to the context, we remove the statement that originated it - // This avoids running duplicate code, since blocks like if/else can be value returning statements - func.def.body.0.pop(); - // Add the new return statement - func.def.body.0.push(return_values); - } - - // Before returning mark the contract as initialized - if is_initializer { - let mark_initialized = create_mark_as_initialized(ty); - func.def.body.0.push(mark_initialized); - } - - // Push the finish method call to the end of the function - let finish_def = create_context_finish(); - func.def.body.0.push(finish_def); - - let return_type = create_return_type(&return_type_name); - func.def.return_type = return_type; - func.def.return_visibility = Visibility::Public; - - // Distinct return types are only required for private functions - // Public functions should have open auto-inferred - match ty { - "Private" => func.def.return_distinctness = Distinctness::Distinct, - "Public" => func.def.is_open = true, - _ => (), - } - - Ok(()) -} - -/// Transform a function to work with AVM bytecode -fn transform_vm_function( - func: &mut NoirFunction, - storage_defined: bool, -) -> Result<(), AztecMacroError> { - // Create access to storage - if storage_defined { - let storage = abstract_storage("public_vm", true); - func.def.body.0.insert(0, storage); - } - - // Push Avm context creation to the beginning of the function - let create_context = create_avm_context()?; - func.def.body.0.insert(0, create_context); - - // We want the function to be seen as a public function - func.def.is_open = true; - - // NOTE: the line below is a temporary hack to trigger external transpilation tools - // It will be removed once the transpiler is integrated into the Noir compiler - func.def.name.0.contents = format!("avm_{}", func.def.name.0.contents); - Ok(()) -} - -/// Transform Unconstrained -/// -/// Inserts the following code at the beginning of an unconstrained function -/// ```noir -/// let storage = Storage::init(Context::none()); -/// ``` -/// -/// This will allow developers to access their contract' storage struct in unconstrained functions -fn transform_unconstrained(func: &mut NoirFunction) { - func.def.body.0.insert(0, abstract_storage("Unconstrained", true)); -} - -fn collect_crate_structs(crate_id: &CrateId, context: &HirContext) -> Vec { - context - .def_map(crate_id) - .expect("ICE: Missing crate in def_map") - .modules() - .iter() - .flat_map(|(_, module)| { - module.type_definitions().filter_map(|typ| { - if let ModuleDefId::TypeId(struct_id) = typ { - Some(struct_id) - } else { - None - } - }) - }) - .collect() -} - -fn collect_traits(context: &HirContext) -> Vec { - let crates = context.crates(); - crates - .flat_map(|crate_id| context.def_map(&crate_id).map(|def_map| def_map.modules())) - .flatten() - .flat_map(|module| { - module.type_definitions().filter_map(|typ| { - if let ModuleDefId::TraitId(struct_id) = typ { - Some(struct_id) - } else { - None - } - }) - }) - .collect() -} - -/// Substitutes the signature literal that was introduced in the selector method previously with the actual signature. -fn transform_event( - struct_id: StructId, - interner: &mut NodeInterner, -) -> Result<(), (AztecMacroError, FileId)> { - let struct_type = interner.get_struct(struct_id); - let selector_id = interner - .lookup_method(&Type::Struct(struct_type.clone(), vec![]), struct_id, "selector", false) - .ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Selector method not found".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?; - let selector_function = interner.function(&selector_id); - - let compute_selector_statement = interner.statement( - selector_function.block(interner).statements().first().ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Compute selector statement not found".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?, - ); - - let compute_selector_expression = match compute_selector_statement { - HirStatement::Expression(expression_id) => match interner.expression(&expression_id) { - HirExpression::Call(hir_call_expression) => Some(hir_call_expression), - _ => None, - }, - _ => None, - } - .ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Compute selector statement is not a call expression".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?; - - let first_arg_id = compute_selector_expression.arguments.first().ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Compute selector statement is not a call expression".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?; - - match interner.expression(first_arg_id) { - HirExpression::Literal(HirLiteral::Str(signature)) - if signature == SIGNATURE_PLACEHOLDER => - { - let selector_literal_id = *first_arg_id; - - let structure = interner.get_struct(struct_id); - let signature = event_signature(&structure.borrow()); - interner.update_expression(selector_literal_id, |expr| { - *expr = HirExpression::Literal(HirLiteral::Str(signature.clone())); - }); - - // Also update the type! It might have a different length now than the placeholder. - interner.push_expr_type( - selector_literal_id, - Type::String(Box::new(Type::Constant(signature.len() as u64))), - ); - Ok(()) - } - _ => Err(( - AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Signature placeholder literal does not match".to_owned(), - }, - struct_type.borrow().location.file, - )), - } -} - -fn transform_events( - crate_id: &CrateId, - context: &mut HirContext, -) -> Result<(), (AztecMacroError, FileId)> { - for struct_id in collect_crate_structs(crate_id, context) { - let attributes = context.def_interner.struct_attributes(&struct_id); - if attributes.iter().any(|attr| matches!(attr, SecondaryAttribute::Event)) { - transform_event(struct_id, &mut context.def_interner)?; - } - } - Ok(()) -} - -/// Obtains the serialized length of a type that implements the Serialize trait. -fn get_serialized_length( - traits: &[TraitId], - typ: &Type, - interner: &NodeInterner, -) -> Result { - let (struct_name, maybe_stored_in_state) = match typ { - Type::Struct(struct_type, generics) => { - Ok((struct_type.borrow().name.0.contents.clone(), generics.first())) - } - _ => Err(AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some("State storage variable must be a struct".to_string()), - }), - }?; - let stored_in_state = - maybe_stored_in_state.ok_or(AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some("State storage variable must be generic".to_string()), - })?; - - let is_note = traits.iter().any(|&trait_id| { - let r#trait = interner.get_trait(trait_id); - r#trait.name.0.contents == "NoteInterface" - && !interner.lookup_all_trait_implementations(stored_in_state, trait_id).is_empty() - }); - - // Maps and (private) Notes always occupy a single slot. Someone could store a Note in PublicMutable for whatever reason though. - if struct_name == "Map" || (is_note && struct_name != "PublicMutable") { - return Ok(1); - } - - let serialized_trait_impl_kind = traits - .iter() - .find_map(|&trait_id| { - let r#trait = interner.get_trait(trait_id); - if r#trait.borrow().name.0.contents == "Serialize" - && r#trait.borrow().generics.len() == 1 - { - interner - .lookup_all_trait_implementations(stored_in_state, trait_id) - .into_iter() - .next() - } else { - None - } - }) - .ok_or(AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some("Stored data must implement Serialize trait".to_string()), - })?; - - let serialized_trait_impl_id = match serialized_trait_impl_kind { - TraitImplKind::Normal(trait_impl_id) => Ok(trait_impl_id), - _ => Err(AztecMacroError::CouldNotAssignStorageSlots { secondary_message: None }), - }?; - - let serialized_trait_impl_shared = interner.get_trait_implementation(*serialized_trait_impl_id); - let serialized_trait_impl = serialized_trait_impl_shared.borrow(); - - match serialized_trait_impl.trait_generics.first().unwrap() { - Type::Constant(value) => Ok(*value), - _ => Err(AztecMacroError::CouldNotAssignStorageSlots { secondary_message: None }), - } -} - -/// Assigns storage slots to the storage struct fields based on the serialized length of the types. This automatic assignment -/// will only trigger if the assigned storage slot is invalid (0 as generated by generate_storage_implementation) -fn assign_storage_slots( +fn transform_collected_defs( crate_id: &CrateId, context: &mut HirContext, -) -> Result<(), (AztecMacroError, FileId)> { - let traits: Vec<_> = collect_traits(context); - for struct_id in collect_crate_structs(crate_id, context) { - let interner: &mut NodeInterner = context.def_interner.borrow_mut(); - let r#struct = interner.get_struct(struct_id); - let file_id = r#struct.borrow().location.file; - if r#struct.borrow().name.0.contents == "Storage" && r#struct.borrow().id.krate().is_root() - { - let init_id = interner - .lookup_method( - &Type::Struct(interner.get_struct(struct_id), vec![]), - struct_id, - "init", - false, - ) - .ok_or(( - AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some( - "Storage struct must have an init function".to_string(), - ), - }, - file_id, - ))?; - let init_function = interner.function(&init_id).block(interner); - let init_function_statement_id = init_function.statements().first().ok_or(( - AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some("Init storage statement not found".to_string()), - }, - file_id, - ))?; - let storage_constructor_statement = interner.statement(init_function_statement_id); - - let storage_constructor_expression = match storage_constructor_statement { - HirStatement::Expression(expression_id) => { - match interner.expression(&expression_id) { - HirExpression::Constructor(hir_constructor_expression) => { - Ok(hir_constructor_expression) - } - _ => Err((AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some( - "Storage constructor statement must be a constructor expression" - .to_string(), - ), - }, file_id)) - } - } - _ => Err(( - AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some( - "Storage constructor statement must be an expression".to_string(), - ), - }, - file_id, - )), - }?; - - let mut storage_slot: u64 = 1; - for (index, (_, expr_id)) in storage_constructor_expression.fields.iter().enumerate() { - let fields = r#struct.borrow().get_fields(&[]); - let (_, field_type) = fields.get(index).unwrap(); - let new_call_expression = match interner.expression(expr_id) { - HirExpression::Call(hir_call_expression) => Ok(hir_call_expression), - _ => Err(( - AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some( - "Storage field initialization expression is not a call expression" - .to_string(), - ), - }, - file_id, - )), - }?; - - let slot_arg_expression = interner.expression(&new_call_expression.arguments[1]); - - let current_storage_slot = match slot_arg_expression { - HirExpression::Literal(HirLiteral::Integer(slot, _)) => Ok(slot.to_u128()), - _ => Err(( - AztecMacroError::CouldNotAssignStorageSlots { - secondary_message: Some( - "Storage slot argument expression must be a literal integer" - .to_string(), - ), - }, - file_id, - )), - }?; - - if current_storage_slot != 0 { - continue; - } - - let type_serialized_len = get_serialized_length(&traits, field_type, interner) - .map_err(|err| (err, file_id))?; - interner.update_expression(new_call_expression.arguments[1], |expr| { - *expr = HirExpression::Literal(HirLiteral::Integer( - FieldElement::from(u128::from(storage_slot)), - false, - )); - }); - - storage_slot += type_serialized_len; - } - } - } - Ok(()) -} - -const SIGNATURE_PLACEHOLDER: &str = "SIGNATURE_PLACEHOLDER"; - -/// Generates the impl for an event selector -/// -/// Inserts the following code: -/// ```noir -/// impl SomeStruct { -/// fn selector() -> FunctionSelector { -/// aztec::protocol_types::abis::function_selector::FunctionSelector::from_signature("SIGNATURE_PLACEHOLDER") -/// } -/// } -/// ``` -/// -/// This allows developers to emit events without having to write the signature of the event every time they emit it. -/// The signature cannot be known at this point since types are not resolved yet, so we use a signature placeholder. -/// It'll get resolved after by transforming the HIR. -fn generate_selector_impl(structure: &NoirStruct) -> TypeImpl { - let struct_type = - make_type(UnresolvedTypeData::Named(path(structure.name.clone()), vec![], true)); - - let selector_path = - chained_dep!("aztec", "protocol_types", "abis", "function_selector", "FunctionSelector"); - let mut from_signature_path = selector_path.clone(); - from_signature_path.segments.push(ident("from_signature")); - - let selector_fun_body = BlockExpression(vec![make_statement(StatementKind::Expression(call( - variable_path(from_signature_path), - vec![expression(ExpressionKind::Literal(Literal::Str(SIGNATURE_PLACEHOLDER.to_string())))], - )))]); - - // Define `FunctionSelector` return type - let return_type = - FunctionReturnType::Ty(make_type(UnresolvedTypeData::Named(selector_path, vec![], true))); - - let mut selector_fn_def = FunctionDefinition::normal( - &ident("selector"), - &vec![], - &[], - &selector_fun_body, - &[], - &return_type, - ); - - selector_fn_def.visibility = FunctionVisibility::Public; - - // Seems to be necessary on contract modules - selector_fn_def.return_visibility = Visibility::Public; - - TypeImpl { - object_type: struct_type, - type_span: structure.span, - generics: vec![], - methods: vec![(NoirFunction::normal(selector_fn_def), Span::default())], - } -} - -/// Helper function that returns what the private context would look like in the ast -/// This should make it available to be consumed within aztec private annotated functions. -/// -/// The replaced code: -/// ```noir -/// /// Before -/// fn foo(inputs: PrivateContextInputs) { -/// // ... -/// } -/// -/// /// After -/// #[aztec(private)] -/// fn foo() { -/// // ... -/// } -fn create_inputs(ty: &str) -> Param { - let context_ident = ident("inputs"); - let context_pattern = Pattern::Identifier(context_ident); - - let path_snippet = ty.to_case(Case::Snake); // e.g. private_context_inputs - let type_path = chained_dep!("aztec", "context", "inputs", &path_snippet, ty); - - let context_type = make_type(UnresolvedTypeData::Named(type_path, vec![], true)); - let visibility = Visibility::Private; - - Param { pattern: context_pattern, typ: context_type, visibility, span: Span::default() } -} - -/// Creates an initialization check to ensure that the contract has been initialized, meant to -/// be injected as the first statement of any function after the context has been created. -/// -/// ```noir -/// assert_is_initialized(&mut context); -/// ``` -fn create_init_check() -> Statement { - make_statement(StatementKind::Expression(call( - variable_path(chained_dep!("aztec", "initializer", "assert_is_initialized")), - vec![mutable_reference("context")], - ))) -} - -/// Creates a call to mark_as_initialized which emits the initialization nullifier, meant to -/// be injected as the last statement before returning in a constructor. -/// -/// ```noir -/// mark_as_initialized(&mut context); -/// ``` -fn create_mark_as_initialized(ty: &str) -> Statement { - let name = if ty == "Public" { "mark_as_initialized_public" } else { "mark_as_initialized" }; - make_statement(StatementKind::Expression(call( - variable_path(chained_dep!("aztec", "initializer", name)), - vec![mutable_reference("context")], - ))) -} - -/// Creates a check for internal functions ensuring that the caller is self. -/// -/// ```noir -/// assert(context.msg_sender() == context.this_address(), "Function can only be called internally"); -/// ``` -fn create_internal_check(fname: &str) -> Statement { - make_statement(StatementKind::Constrain(ConstrainStatement( - make_eq( - method_call(variable("context"), "msg_sender", vec![]), - method_call(variable("context"), "this_address", vec![]), - ), - Some(expression(ExpressionKind::Literal(Literal::Str(format!( - "Function {} can only be called internally", - fname - ))))), - ConstrainKind::Assert, - ))) -} - -/// Creates the private context object to be accessed within the function, the parameters need to be extracted to be -/// appended into the args hash object. -/// -/// The replaced code: -/// ```noir -/// #[aztec(private)] -/// fn foo(structInput: SomeStruct, arrayInput: [u8; 10], fieldInput: Field) -> Field { -/// // Create the hasher object -/// let mut hasher = Hasher::new(); -/// -/// // struct inputs call serialize on them to add an array of fields -/// hasher.add_multiple(structInput.serialize()); -/// -/// // Array inputs are iterated over and each element is added to the hasher (as a field) -/// for i in 0..arrayInput.len() { -/// hasher.add(arrayInput[i] as Field); -/// } -/// // Field inputs are added to the hasher -/// hasher.add({ident}); -/// -/// // Create the context -/// // The inputs (injected by this `create_inputs`) and completed hash object are passed to the context -/// let mut context = PrivateContext::new(inputs, hasher.hash()); -/// } -/// ``` -fn create_context(ty: &str, params: &[Param]) -> Result, AztecMacroError> { - let mut injected_expressions: Vec = vec![]; - - // `let mut hasher = Hasher::new();` - let let_hasher = mutable_assignment( - "hasher", // Assigned to - call( - variable_path(chained_dep!("aztec", "hasher", "Hasher", "new")), // Path - vec![], // args - ), - ); - - // Completes: `let mut hasher = Hasher::new();` - injected_expressions.push(let_hasher); - - // Iterate over each of the function parameters, adding to them to the hasher - for Param { pattern, typ, span, .. } in params { - match pattern { - Pattern::Identifier(identifier) => { - // Match the type to determine the padding to do - let unresolved_type = &typ.typ; - let expression = match unresolved_type { - // `hasher.add_multiple({ident}.serialize())` - UnresolvedTypeData::Named(..) => add_struct_to_hasher(identifier), - UnresolvedTypeData::Array(_, arr_type) => { - add_array_to_hasher(identifier, arr_type) - } - // `hasher.add({ident})` - UnresolvedTypeData::FieldElement => add_field_to_hasher(identifier), - // Add the integer to the hasher, casted to a field - // `hasher.add({ident} as Field)` - UnresolvedTypeData::Integer(..) | UnresolvedTypeData::Bool => { - add_cast_to_hasher(identifier) - } - UnresolvedTypeData::String(..) => { - let (var_bytes, id) = str_to_bytes(identifier); - injected_expressions.push(var_bytes); - add_array_to_hasher( - &id, - &UnresolvedType { - typ: UnresolvedTypeData::Integer( - Signedness::Unsigned, - noirc_frontend::IntegerBitSize::ThirtyTwo, - ), - span: None, - }, - ) - } - _ => { - return Err(AztecMacroError::UnsupportedFunctionArgumentType { - typ: unresolved_type.clone(), - span: *span, - }) - } - }; - injected_expressions.push(expression); - } - _ => todo!(), // Maybe unreachable? - } - } - - // Create the inputs to the context - let inputs_expression = variable("inputs"); - // `hasher.hash()` - let hash_call = method_call( - variable("hasher"), // variable - "hash", // method name - vec![], // args - ); - - let path_snippet = ty.to_case(Case::Snake); // e.g. private_context - - // let mut context = {ty}::new(inputs, hash); - let let_context = mutable_assignment( - "context", // Assigned to - call( - variable_path(chained_dep!("aztec", "context", &path_snippet, ty, "new")), // Path - vec![inputs_expression, hash_call], // args - ), - ); - injected_expressions.push(let_context); - - // Return all expressions that will be injected by the hasher - Ok(injected_expressions) -} - -/// Creates an mutable avm context -/// -/// ```noir -/// /// Before -/// #[aztec(public-vm)] -/// fn foo() -> Field { -/// let mut context = aztec::context::AVMContext::new(); -/// let timestamp = context.timestamp(); -/// // ... -/// } -/// -/// /// After -/// #[aztec(private)] -/// fn foo() -> Field { -/// let mut timestamp = context.timestamp(); -/// // ... -/// } -fn create_avm_context() -> Result { - let let_context = mutable_assignment( - "context", // Assigned to - call( - variable_path(chained_dep!("aztec", "context", "AVMContext", "new")), // Path - vec![], // args - ), - ); - - Ok(let_context) -} - -/// Abstract Return Type -/// -/// This function intercepts the function's current return type and replaces it with pushes -/// To the kernel -/// -/// The replaced code: -/// ```noir -/// /// Before -/// #[aztec(private)] -/// fn foo() -> protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs { -/// // ... -/// let my_return_value: Field = 10; -/// context.return_values.push(my_return_value); -/// } -/// -/// /// After -/// #[aztec(private)] -/// fn foo() -> Field { -/// // ... -/// let my_return_value: Field = 10; -/// my_return_value -/// } -/// ``` -/// Similarly; Structs will be pushed to the context, after serialize() is called on them. -/// Arrays will be iterated over and each element will be pushed to the context. -/// Any primitive type that can be cast will be casted to a field and pushed to the context. -fn abstract_return_values(func: &NoirFunction) -> Option { - let current_return_type = func.return_type().typ; - let last_statement = func.def.body.0.last()?; - - // TODO: (length, type) => We can limit the size of the array returned to be limited by kernel size - // Doesn't need done until we have settled on a kernel size - // TODO: support tuples here and in inputs -> convert into an issue - // Check if the return type is an expression, if it is, we can handle it - match last_statement { - Statement { kind: StatementKind::Expression(expression), .. } => { - match current_return_type { - // Call serialize on structs, push the whole array, calling push_array - UnresolvedTypeData::Named(..) => Some(make_struct_return_type(expression.clone())), - UnresolvedTypeData::Array(..) => Some(make_array_return_type(expression.clone())), - // Cast these types to a field before pushing - UnresolvedTypeData::Bool | UnresolvedTypeData::Integer(..) => { - Some(make_castable_return_type(expression.clone())) - } - UnresolvedTypeData::FieldElement => Some(make_return_push(expression.clone())), - _ => None, - } - } - _ => None, - } -} - -/// Abstract storage -/// -/// For private functions: -/// ```noir -/// #[aztec(private)] -/// fn lol() { -/// let storage = Storage::init(Context::private(context)); -/// } -/// ``` -/// -/// For public functions: -/// ```noir -/// #[aztec(public)] -/// fn lol() { -/// let storage = Storage::init(Context::public(context)); -/// } -/// ``` -/// -/// For unconstrained functions: -/// ```noir -/// unconstrained fn lol() { -/// let storage = Storage::init(Context::none()); -/// } -fn abstract_storage(typ: &str, unconstrained: bool) -> Statement { - let init_context_call = if unconstrained { - call( - variable_path(chained_dep!("aztec", "context", "Context", "none")), // Path - vec![], // args + collected_trait_impls: &[UnresolvedTraitImpl], + collected_functions: &mut [UnresolvedFunctions], +) -> Result<(), (MacroError, FileId)> { + if has_aztec_dependency(crate_id, context) { + inject_compute_note_hash_and_nullifier( + crate_id, + context, + collected_trait_impls, + collected_functions, ) } else { - call( - variable_path(chained_dep!("aztec", "context", "Context", typ)), // Path - vec![mutable_reference("context")], // args - ) - }; - - assignment( - "storage", // Assigned to - call( - variable_path(chained_path!("Storage", "init")), // Path - vec![init_context_call], // args - ), - ) -} - -/// Context Return Values -/// -/// Creates an instance to the context return values -/// ```noir -/// `context.return_values` -/// ``` -fn context_return_values() -> Expression { - member_access("context", "return_values") -} - -fn make_statement(kind: StatementKind) -> Statement { - Statement { span: Span::default(), kind } -} - -/// Make return Push -/// -/// Translates to: -/// `context.return_values.push({push_value})` -fn make_return_push(push_value: Expression) -> Statement { - make_statement(StatementKind::Semi(method_call( - context_return_values(), - "push", - vec![push_value], - ))) -} - -/// Make Return push array -/// -/// Translates to: -/// `context.return_values.extend_from_array({push_value})` -fn make_return_extend_from_array(push_value: Expression) -> Statement { - make_statement(StatementKind::Semi(method_call( - context_return_values(), - "extend_from_array", - vec![push_value], - ))) -} - -/// Make struct return type -/// -/// Translates to: -/// ```noir -/// `context.return_values.extend_from_array({push_value}.serialize())` -fn make_struct_return_type(expression: Expression) -> Statement { - let serialized_call = method_call( - expression, // variable - "serialize", // method name - vec![], // args - ); - make_return_extend_from_array(serialized_call) -} - -/// Make array return type -/// -/// Translates to: -/// ```noir -/// for i in 0..{ident}.len() { -/// context.return_values.push({ident}[i] as Field) -/// } -/// ``` -fn make_array_return_type(expression: Expression) -> Statement { - let inner_cast_expression = - cast(index_array_variable(expression.clone(), "i"), UnresolvedTypeData::FieldElement); - let assignment = make_statement(StatementKind::Semi(method_call( - context_return_values(), // variable - "push", // method name - vec![inner_cast_expression], - ))); - - create_loop_over(expression, vec![assignment]) -} - -/// Castable return type -/// -/// Translates to: -/// ```noir -/// context.return_values.push({ident} as Field) -/// ``` -fn make_castable_return_type(expression: Expression) -> Statement { - // Cast these types to a field before pushing - let cast_expression = cast(expression, UnresolvedTypeData::FieldElement); - make_return_push(cast_expression) -} - -/// Create Return Type -/// -/// Public functions return protocol_types::abis::public_circuit_public_inputs::PublicCircuitPublicInputs while -/// private functions return protocol_types::abis::private_circuit_public_inputs::::PrivateCircuitPublicInputs -/// -/// This call constructs an ast token referencing the above types -/// The name is set in the function above `transform`, hence the -/// whole token name is passed in -/// -/// The replaced code: -/// ```noir -/// -/// /// Before -/// fn foo() -> protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs { -/// // ... -/// } -/// -/// /// After -/// #[aztec(private)] -/// fn foo() { -/// // ... -/// } -fn create_return_type(ty: &str) -> FunctionReturnType { - let path_snippet = ty.to_case(Case::Snake); // e.g. private_circuit_public_inputs or public_circuit_public_inputs - let return_path = chained_dep!("aztec", "protocol_types", "abis", &path_snippet, ty); - return_type(return_path) -} - -/// Create Context Finish -/// -/// Each aztec function calls `context.finish()` at the end of a function -/// to return values required by the kernel. -/// -/// The replaced code: -/// ```noir -/// /// Before -/// fn foo() -> protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs { -/// // ... -/// context.finish() -/// } -/// -/// /// After -/// #[aztec(private)] -/// fn foo() { -/// // ... -/// } -fn create_context_finish() -> Statement { - let method_call = method_call( - variable("context"), // variable - "finish", // method name - vec![], // args - ); - make_statement(StatementKind::Expression(method_call)) + Ok(()) + } } // -// Methods to create hasher inputs +// Transform Hir Nodes for Aztec // -fn add_struct_to_hasher(identifier: &Ident) -> Statement { - // If this is a struct, we call serialize and add the array to the hasher - let serialized_call = method_call( - variable_path(path(identifier.clone())), // variable - "serialize", // method name - vec![], // args - ); - - make_statement(StatementKind::Semi(method_call( - variable("hasher"), // variable - "add_multiple", // method name - vec![serialized_call], // args - ))) -} - -fn str_to_bytes(identifier: &Ident) -> (Statement, Ident) { - // let identifier_as_bytes = identifier.as_bytes(); - let var = variable_ident(identifier.clone()); - let contents = if let ExpressionKind::Variable(p) = &var.kind { - p.segments.first().cloned().unwrap_or_else(|| panic!("No segments")).0.contents - } else { - panic!("Unexpected identifier type") - }; - let bytes_name = format!("{}_bytes", contents); - let var_bytes = assignment(&bytes_name, method_call(var, "as_bytes", vec![])); - let id = Ident::new(bytes_name, Span::default()); - - (var_bytes, id) -} - -fn create_loop_over(var: Expression, loop_body: Vec) -> Statement { - // If this is an array of primitive types (integers / fields) we can add them each to the hasher - // casted to a field - let span = var.span; - - // `array.len()` - let end_range_expression = method_call( - var, // variable - "len", // method name - vec![], // args - ); - - // What will be looped over - // - `hasher.add({ident}[i] as Field)` - let for_loop_block = expression(ExpressionKind::Block(BlockExpression(loop_body))); - - // `for i in 0..{ident}.len()` - make_statement(StatementKind::For(ForLoopStatement { - range: ForRange::Range( - expression(ExpressionKind::Literal(Literal::Integer( - FieldElement::from(i128::from(0)), - false, - ))), - end_range_expression, - ), - identifier: ident("i"), - block: for_loop_block, - span, - })) -} - -fn add_array_to_hasher(identifier: &Ident, arr_type: &UnresolvedType) -> Statement { - // If this is an array of primitive types (integers / fields) we can add them each to the hasher - // casted to a field - - // Wrap in the semi thing - does that mean ended with semi colon? - // `hasher.add({ident}[i] as Field)` - - let arr_index = index_array(identifier.clone(), "i"); - let (add_expression, hasher_method_name) = match arr_type.typ { - UnresolvedTypeData::Named(..) => { - let hasher_method_name = "add_multiple".to_owned(); - let call = method_call( - // All serialize on each element - arr_index, // variable - "serialize", // method name - vec![], // args - ); - (call, hasher_method_name) - } - _ => { - let hasher_method_name = "add".to_owned(); - let call = cast( - arr_index, // lhs - `ident[i]` - UnresolvedTypeData::FieldElement, // cast to - `as Field` - ); - (call, hasher_method_name) - } - }; - - let block_statement = make_statement(StatementKind::Semi(method_call( - variable("hasher"), // variable - &hasher_method_name, // method name - vec![add_expression], - ))); - - create_loop_over(variable_ident(identifier.clone()), vec![block_statement]) -} - -fn add_field_to_hasher(identifier: &Ident) -> Statement { - // `hasher.add({ident})` - let ident = variable_path(path(identifier.clone())); - make_statement(StatementKind::Semi(method_call( - variable("hasher"), // variable - "add", // method name - vec![ident], // args - ))) -} - -fn add_cast_to_hasher(identifier: &Ident) -> Statement { - // `hasher.add({ident} as Field)` - // `{ident} as Field` - let cast_operation = cast( - variable_path(path(identifier.clone())), // lhs - UnresolvedTypeData::FieldElement, // rhs - ); - - // `hasher.add({ident} as Field)` - make_statement(StatementKind::Semi(method_call( - variable("hasher"), // variable - "add", // method name - vec![cast_operation], // args - ))) -} - -/// Computes the aztec signature for a resolved type. -fn signature_of_type(typ: &Type) -> String { - match typ { - Type::Integer(Signedness::Signed, bit_size) => format!("i{}", bit_size), - Type::Integer(Signedness::Unsigned, bit_size) => format!("u{}", bit_size), - Type::FieldElement => "Field".to_owned(), - Type::Bool => "bool".to_owned(), - Type::Array(len, typ) => { - if let Type::Constant(len) = **len { - format!("[{};{len}]", signature_of_type(typ)) - } else { - unimplemented!("Cannot generate signature for array with length type {:?}", typ) - } - } - Type::Struct(def, args) => { - let fields = def.borrow().get_fields(args); - let fields = vecmap(fields, |(_, typ)| signature_of_type(&typ)); - format!("({})", fields.join(",")) - } - Type::Tuple(types) => { - let fields = vecmap(types, signature_of_type); - format!("({})", fields.join(",")) - } - _ => unimplemented!("Cannot generate signature for type {:?}", typ), - } -} - -/// Computes the signature for a resolved event type. -/// It has the form 'EventName(Field,(Field),[u8;2])' -fn event_signature(event: &StructType) -> String { - let fields = vecmap(event.get_fields(&[]), |(_, typ)| signature_of_type(&typ)); - format!("{}({})", event.name.0.contents, fields.join(",")) -} - -fn inject_compute_note_hash_and_nullifier( +/// Completes the Hir with data gathered from type resolution +fn transform_hir( crate_id: &CrateId, context: &mut HirContext, - unresolved_traits_impls: &[UnresolvedTraitImpl], - collected_functions: &mut [UnresolvedFunctions], -) -> Result<(), (MacroError, FileId)> { - // We first fetch modules in this crate which correspond to contracts, along with their file id. - let contract_module_file_ids: Vec<(LocalModuleId, FileId)> = context - .def_map(crate_id) - .expect("ICE: Missing crate in def_map") - .modules() - .iter() - .filter(|(_, module)| module.is_contract) - .map(|(idx, module)| (LocalModuleId(idx), module.location.file)) - .collect(); - - // If the current crate does not contain a contract module we simply skip it. - if contract_module_file_ids.is_empty() { - return Ok(()); - } else if contract_module_file_ids.len() != 1 { - panic!("Found multiple contracts in the same crate"); - } - - let (module_id, file_id) = contract_module_file_ids[0]; - - // If compute_note_hash_and_nullifier is already defined by the user, we skip auto-generation in order to provide an - // escape hatch for this mechanism. - // TODO(#4647): improve this diagnosis and error messaging. - if collected_functions.iter().any(|coll_funcs_data| { - check_for_compute_note_hash_and_nullifier_definition(&coll_funcs_data.functions, module_id) - }) { - return Ok(()); - } - - // In order to implement compute_note_hash_and_nullifier, we need to know all of the different note types the - // contract might use. These are the types that implement the NoteInterface trait, which provides the - // get_note_type_id function. - let note_types = fetch_struct_trait_impls(context, unresolved_traits_impls, "NoteInterface"); - - // We can now generate a version of compute_note_hash_and_nullifier tailored for the contract in this crate. - let func = generate_compute_note_hash_and_nullifier(¬e_types); - - // And inject the newly created function into the contract. - - // TODO(#4373): We don't have a reasonable location for the source code of this autogenerated function, so we simply - // pass an empty span. This function should not produce errors anyway so this should not matter. - let location = Location::new(Span::empty(0), file_id); - - // These are the same things the ModCollector does when collecting functions: we push the function to the - // NodeInterner, declare it in the module (which checks for duplicate definitions), and finally add it to the list - // on collected but unresolved functions. - - let func_id = context.def_interner.push_empty_fn(); - context.def_interner.push_function( - func_id, - &func.def, - ModuleId { krate: *crate_id, local_id: module_id }, - location, - ); - - context.def_map_mut(crate_id).unwrap() - .modules_mut()[module_id.0] - .declare_function( - func.name_ident().clone(), func_id - ).expect( - "Failed to declare the autogenerated compute_note_hash_and_nullifier function, likely due to a duplicate definition. See https://github.com/AztecProtocol/aztec-packages/issues/4647." - ); - - collected_functions - .iter_mut() - .find(|fns| fns.file_id == file_id) - .expect("ICE: no functions found in contract file") - .push_fn(module_id, func_id, func.clone()); - - Ok(()) -} - -// Fetches the name of all structs that implement trait_name, both in the current crate and all of its dependencies. -fn fetch_struct_trait_impls( - context: &mut HirContext, - unresolved_traits_impls: &[UnresolvedTraitImpl], - trait_name: &str, -) -> Vec { - let mut struct_typenames: Vec = Vec::new(); - - // These structs can be declared in either external crates or the current one. External crates that contain - // dependencies have already been processed and resolved, but are available here via the NodeInterner. Note that - // crates on which the current crate does not depend on may not have been processed, and will be ignored. - for trait_impl_id in 0..context.def_interner.next_trait_impl_id().0 { - let trait_impl = &context.def_interner.get_trait_implementation(TraitImplId(trait_impl_id)); - - if trait_impl.borrow().ident.0.contents == *trait_name { - if let Type::Struct(s, _) = &trait_impl.borrow().typ { - struct_typenames.push(s.borrow().name.0.contents.clone()); - } else { - panic!("Found impl for {} on non-Struct", trait_name); - } - } - } - - // This crate's traits and impls have not yet been resolved, so we look for impls in unresolved_trait_impls. - struct_typenames.extend( - unresolved_traits_impls - .iter() - .filter(|trait_impl| { - trait_impl - .trait_path - .segments - .last() - .expect("ICE: empty trait_impl path") - .0 - .contents - == *trait_name - }) - .filter_map(|trait_impl| match &trait_impl.object_type.typ { - UnresolvedTypeData::Named(path, _, _) => { - Some(path.segments.last().unwrap().0.contents.clone()) - } - _ => None, - }), - ); - - struct_typenames -} - -fn generate_compute_note_hash_and_nullifier(note_types: &Vec) -> NoirFunction { - let function_source = generate_compute_note_hash_and_nullifier_source(note_types); - - let (function_ast, errors) = parse_program(&function_source); - if !errors.is_empty() { - dbg!(errors.clone()); - } - assert_eq!(errors.len(), 0, "Failed to parse Noir macro code. This is either a bug in the compiler or the Noir macro code"); - - let mut function_ast = function_ast.into_sorted(); - function_ast.functions.remove(0) -} - -fn generate_compute_note_hash_and_nullifier_source(note_types: &Vec) -> String { - // TODO(#4649): The serialized_note parameter is a fixed-size array, but we don't know what length it should have. - // For now we hardcode it to 20, which is the same as MAX_NOTE_FIELDS_LENGTH. - - if note_types.is_empty() { - // Even if the contract does not include any notes, other parts of the stack expect for this function to exist, - // so we include a dummy version. - " - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; 20] - ) -> pub [Field; 4] { - assert(false, \"This contract does not use private notes\"); - [0, 0, 0, 0] - }" - .to_string() - } else { - // For contracts that include notes we do a simple if-else chain comparing note_type_id with the different - // get_note_type_id of each of the note types. - - let if_statements: Vec = note_types.iter().map(|note_type| format!( - "if (note_type_id == {0}::get_note_type_id()) {{ - dep::aztec::note::utils::compute_note_hash_and_nullifier({0}::deserialize_content, note_header, serialized_note) - }}" - , note_type)).collect(); - - let full_if_statement = if_statements.join(" else ") - + " - else { - assert(false, \"Unknown note type ID\"); - [0, 0, 0, 0] - }"; - - format!( - " - unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, - nonce: Field, - storage_slot: Field, - note_type_id: Field, - serialized_note: [Field; 20] - ) -> pub [Field; 4] {{ - let note_header = dep::aztec::prelude::NoteHeader::new(contract_address, nonce, storage_slot); - - {} - }}", - full_if_statement - ) - } +) -> Result<(), (AztecMacroError, FileId)> { + transform_events(crate_id, context)?; + assign_storage_slots(crate_id, context) } diff --git a/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs b/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs new file mode 100644 index 00000000000..4f8f3f19ab8 --- /dev/null +++ b/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs @@ -0,0 +1,195 @@ +use noirc_errors::{Location, Span}; +use noirc_frontend::{ + graph::CrateId, + hir::{ + def_collector::dc_crate::{UnresolvedFunctions, UnresolvedTraitImpl}, + def_map::{LocalModuleId, ModuleId}, + }, + macros_api::{FileId, HirContext, MacroError}, + node_interner::FuncId, + parse_program, FunctionReturnType, NoirFunction, UnresolvedTypeData, +}; + +use crate::utils::hir_utils::fetch_struct_trait_impls; + +// Check if "compute_note_hash_and_nullifier(AztecAddress,Field,Field,Field,[Field; N]) -> [Field; 4]" is defined +fn check_for_compute_note_hash_and_nullifier_definition( + functions_data: &[(LocalModuleId, FuncId, NoirFunction)], + module_id: LocalModuleId, +) -> bool { + functions_data.iter().filter(|func_data| func_data.0 == module_id).any(|func_data| { + func_data.2.def.name.0.contents == "compute_note_hash_and_nullifier" + && func_data.2.def.parameters.len() == 5 + && match &func_data.2.def.parameters[0].typ.typ { + UnresolvedTypeData::Named(path, _, _) => path.segments.last().unwrap().0.contents == "AztecAddress", + _ => false, + } + && func_data.2.def.parameters[1].typ.typ == UnresolvedTypeData::FieldElement + && func_data.2.def.parameters[2].typ.typ == UnresolvedTypeData::FieldElement + && func_data.2.def.parameters[3].typ.typ == UnresolvedTypeData::FieldElement + // checks if the 5th parameter is an array and the Box in + // Array(Option, Box) contains only fields + && match &func_data.2.def.parameters[4].typ.typ { + UnresolvedTypeData::Array(_, inner_type) => { + matches!(inner_type.typ, UnresolvedTypeData::FieldElement) + }, + _ => false, + } + // We check the return type the same way as we did the 5th parameter + && match &func_data.2.def.return_type { + FunctionReturnType::Default(_) => false, + FunctionReturnType::Ty(unresolved_type) => { + match &unresolved_type.typ { + UnresolvedTypeData::Array(_, inner_type) => { + matches!(inner_type.typ, UnresolvedTypeData::FieldElement) + }, + _ => false, + } + } + } + }) +} + +pub fn inject_compute_note_hash_and_nullifier( + crate_id: &CrateId, + context: &mut HirContext, + unresolved_traits_impls: &[UnresolvedTraitImpl], + collected_functions: &mut [UnresolvedFunctions], +) -> Result<(), (MacroError, FileId)> { + // We first fetch modules in this crate which correspond to contracts, along with their file id. + let contract_module_file_ids: Vec<(LocalModuleId, FileId)> = context + .def_map(crate_id) + .expect("ICE: Missing crate in def_map") + .modules() + .iter() + .filter(|(_, module)| module.is_contract) + .map(|(idx, module)| (LocalModuleId(idx), module.location.file)) + .collect(); + + // If the current crate does not contain a contract module we simply skip it. + if contract_module_file_ids.is_empty() { + return Ok(()); + } else if contract_module_file_ids.len() != 1 { + panic!("Found multiple contracts in the same crate"); + } + + let (module_id, file_id) = contract_module_file_ids[0]; + + // If compute_note_hash_and_nullifier is already defined by the user, we skip auto-generation in order to provide an + // escape hatch for this mechanism. + // TODO(#4647): improve this diagnosis and error messaging. + if collected_functions.iter().any(|coll_funcs_data| { + check_for_compute_note_hash_and_nullifier_definition(&coll_funcs_data.functions, module_id) + }) { + return Ok(()); + } + + // In order to implement compute_note_hash_and_nullifier, we need to know all of the different note types the + // contract might use. These are the types that implement the NoteInterface trait, which provides the + // get_note_type_id function. + let note_types = fetch_struct_trait_impls(context, unresolved_traits_impls, "NoteInterface"); + + // We can now generate a version of compute_note_hash_and_nullifier tailored for the contract in this crate. + let func = generate_compute_note_hash_and_nullifier(¬e_types); + + // And inject the newly created function into the contract. + + // TODO(#4373): We don't have a reasonable location for the source code of this autogenerated function, so we simply + // pass an empty span. This function should not produce errors anyway so this should not matter. + let location = Location::new(Span::empty(0), file_id); + + // These are the same things the ModCollector does when collecting functions: we push the function to the + // NodeInterner, declare it in the module (which checks for duplicate definitions), and finally add it to the list + // on collected but unresolved functions. + + let func_id = context.def_interner.push_empty_fn(); + context.def_interner.push_function( + func_id, + &func.def, + ModuleId { krate: *crate_id, local_id: module_id }, + location, + ); + + context.def_map_mut(crate_id).unwrap() + .modules_mut()[module_id.0] + .declare_function( + func.name_ident().clone(), func_id + ).expect( + "Failed to declare the autogenerated compute_note_hash_and_nullifier function, likely due to a duplicate definition. See https://github.com/AztecProtocol/aztec-packages/issues/4647." + ); + + collected_functions + .iter_mut() + .find(|fns| fns.file_id == file_id) + .expect("ICE: no functions found in contract file") + .push_fn(module_id, func_id, func.clone()); + + Ok(()) +} + +fn generate_compute_note_hash_and_nullifier(note_types: &Vec) -> NoirFunction { + let function_source = generate_compute_note_hash_and_nullifier_source(note_types); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors.clone()); + } + assert_eq!(errors.len(), 0, "Failed to parse Noir macro code. This is either a bug in the compiler or the Noir macro code"); + + let mut function_ast = function_ast.into_sorted(); + function_ast.functions.remove(0) +} + +fn generate_compute_note_hash_and_nullifier_source(note_types: &Vec) -> String { + // TODO(#4649): The serialized_note parameter is a fixed-size array, but we don't know what length it should have. + // For now we hardcode it to 20, which is the same as MAX_NOTE_FIELDS_LENGTH. + + if note_types.is_empty() { + // Even if the contract does not include any notes, other parts of the stack expect for this function to exist, + // so we include a dummy version. + " + unconstrained fn compute_note_hash_and_nullifier( + contract_address: AztecAddress, + nonce: Field, + storage_slot: Field, + note_type_id: Field, + serialized_note: [Field; 20] + ) -> pub [Field; 4] { + assert(false, \"This contract does not use private notes\"); + [0, 0, 0, 0] + }" + .to_string() + } else { + // For contracts that include notes we do a simple if-else chain comparing note_type_id with the different + // get_note_type_id of each of the note types. + + let if_statements: Vec = note_types.iter().map(|note_type| format!( + "if (note_type_id == {0}::get_note_type_id()) {{ + dep::aztec::note::utils::compute_note_hash_and_nullifier({0}::deserialize_content, note_header, serialized_note) + }}" + , note_type)).collect(); + + let full_if_statement = if_statements.join(" else ") + + " + else { + assert(false, \"Unknown note type ID\"); + [0, 0, 0, 0] + }"; + + format!( + " + unconstrained fn compute_note_hash_and_nullifier( + contract_address: AztecAddress, + nonce: Field, + storage_slot: Field, + note_type_id: Field, + serialized_note: [Field; 20] + ) -> pub [Field; 4] {{ + let note_header = dep::aztec::prelude::NoteHeader::new(contract_address, nonce, storage_slot); + + {} + }}", + full_if_statement + ) + } +} diff --git a/noir/noir-repo/aztec_macros/src/transforms/events.rs b/noir/noir-repo/aztec_macros/src/transforms/events.rs new file mode 100644 index 00000000000..b02709efacb --- /dev/null +++ b/noir/noir-repo/aztec_macros/src/transforms/events.rs @@ -0,0 +1,178 @@ +use iter_extended::vecmap; +use noirc_errors::Span; +use noirc_frontend::{ + graph::CrateId, + macros_api::{ + BlockExpression, FileId, HirContext, HirExpression, HirLiteral, HirStatement, NodeInterner, + NoirStruct, PathKind, StatementKind, StructId, StructType, Type, TypeImpl, + UnresolvedTypeData, + }, + token::SecondaryAttribute, + ExpressionKind, FunctionDefinition, FunctionReturnType, ItemVisibility, Literal, NoirFunction, + Visibility, +}; + +use crate::{ + chained_dep, + utils::{ + ast_utils::{ + call, expression, ident, ident_path, make_statement, make_type, path, variable_path, + }, + constants::SIGNATURE_PLACEHOLDER, + errors::AztecMacroError, + hir_utils::{collect_crate_structs, signature_of_type}, + }, +}; + +/// Generates the impl for an event selector +/// +/// Inserts the following code: +/// ```noir +/// impl SomeStruct { +/// fn selector() -> FunctionSelector { +/// aztec::protocol_types::abis::function_selector::FunctionSelector::from_signature("SIGNATURE_PLACEHOLDER") +/// } +/// } +/// ``` +/// +/// This allows developers to emit events without having to write the signature of the event every time they emit it. +/// The signature cannot be known at this point since types are not resolved yet, so we use a signature placeholder. +/// It'll get resolved after by transforming the HIR. +pub fn generate_selector_impl(structure: &NoirStruct) -> TypeImpl { + let struct_type = + make_type(UnresolvedTypeData::Named(path(structure.name.clone()), vec![], true)); + + let selector_path = + chained_dep!("aztec", "protocol_types", "abis", "function_selector", "FunctionSelector"); + let mut from_signature_path = selector_path.clone(); + from_signature_path.segments.push(ident("from_signature")); + + let selector_fun_body = BlockExpression(vec![make_statement(StatementKind::Expression(call( + variable_path(from_signature_path), + vec![expression(ExpressionKind::Literal(Literal::Str(SIGNATURE_PLACEHOLDER.to_string())))], + )))]); + + // Define `FunctionSelector` return type + let return_type = + FunctionReturnType::Ty(make_type(UnresolvedTypeData::Named(selector_path, vec![], true))); + + let mut selector_fn_def = FunctionDefinition::normal( + &ident("selector"), + &vec![], + &[], + &selector_fun_body, + &[], + &return_type, + ); + + selector_fn_def.visibility = ItemVisibility::Public; + + // Seems to be necessary on contract modules + selector_fn_def.return_visibility = Visibility::Public; + + TypeImpl { + object_type: struct_type, + type_span: structure.span, + generics: vec![], + methods: vec![(NoirFunction::normal(selector_fn_def), Span::default())], + } +} + +/// Computes the signature for a resolved event type. +/// It has the form 'EventName(Field,(Field),[u8;2])' +fn event_signature(event: &StructType) -> String { + let fields = vecmap(event.get_fields(&[]), |(_, typ)| signature_of_type(&typ)); + format!("{}({})", event.name.0.contents, fields.join(",")) +} + +/// Substitutes the signature literal that was introduced in the selector method previously with the actual signature. +fn transform_event( + struct_id: StructId, + interner: &mut NodeInterner, +) -> Result<(), (AztecMacroError, FileId)> { + let struct_type = interner.get_struct(struct_id); + let selector_id = interner + .lookup_method(&Type::Struct(struct_type.clone(), vec![]), struct_id, "selector", false) + .ok_or_else(|| { + let error = AztecMacroError::EventError { + span: struct_type.borrow().location.span, + message: "Selector method not found".to_owned(), + }; + (error, struct_type.borrow().location.file) + })?; + let selector_function = interner.function(&selector_id); + + let compute_selector_statement = interner.statement( + selector_function.block(interner).statements().first().ok_or_else(|| { + let error = AztecMacroError::EventError { + span: struct_type.borrow().location.span, + message: "Compute selector statement not found".to_owned(), + }; + (error, struct_type.borrow().location.file) + })?, + ); + + let compute_selector_expression = match compute_selector_statement { + HirStatement::Expression(expression_id) => match interner.expression(&expression_id) { + HirExpression::Call(hir_call_expression) => Some(hir_call_expression), + _ => None, + }, + _ => None, + } + .ok_or_else(|| { + let error = AztecMacroError::EventError { + span: struct_type.borrow().location.span, + message: "Compute selector statement is not a call expression".to_owned(), + }; + (error, struct_type.borrow().location.file) + })?; + + let first_arg_id = compute_selector_expression.arguments.first().ok_or_else(|| { + let error = AztecMacroError::EventError { + span: struct_type.borrow().location.span, + message: "Compute selector statement is not a call expression".to_owned(), + }; + (error, struct_type.borrow().location.file) + })?; + + match interner.expression(first_arg_id) { + HirExpression::Literal(HirLiteral::Str(signature)) + if signature == SIGNATURE_PLACEHOLDER => + { + let selector_literal_id = *first_arg_id; + + let structure = interner.get_struct(struct_id); + let signature = event_signature(&structure.borrow()); + interner.update_expression(selector_literal_id, |expr| { + *expr = HirExpression::Literal(HirLiteral::Str(signature.clone())); + }); + + // Also update the type! It might have a different length now than the placeholder. + interner.push_expr_type( + selector_literal_id, + Type::String(Box::new(Type::Constant(signature.len() as u64))), + ); + Ok(()) + } + _ => Err(( + AztecMacroError::EventError { + span: struct_type.borrow().location.span, + message: "Signature placeholder literal does not match".to_owned(), + }, + struct_type.borrow().location.file, + )), + } +} + +pub fn transform_events( + crate_id: &CrateId, + context: &mut HirContext, +) -> Result<(), (AztecMacroError, FileId)> { + for struct_id in collect_crate_structs(crate_id, context) { + let attributes = context.def_interner.struct_attributes(&struct_id); + if attributes.iter().any(|attr| matches!(attr, SecondaryAttribute::Event)) { + transform_event(struct_id, &mut context.def_interner)?; + } + } + Ok(()) +} diff --git a/noir/noir-repo/aztec_macros/src/transforms/functions.rs b/noir/noir-repo/aztec_macros/src/transforms/functions.rs new file mode 100644 index 00000000000..8b3c7d2f53b --- /dev/null +++ b/noir/noir-repo/aztec_macros/src/transforms/functions.rs @@ -0,0 +1,707 @@ +use convert_case::{Case, Casing}; +use noirc_errors::Span; +use noirc_frontend::{ + macros_api::FieldElement, BlockExpression, ConstrainKind, ConstrainStatement, Distinctness, + Expression, ExpressionKind, ForLoopStatement, ForRange, FunctionReturnType, Ident, Literal, + NoirFunction, Param, PathKind, Pattern, Signedness, Statement, StatementKind, UnresolvedType, + UnresolvedTypeData, Visibility, +}; + +use crate::{ + chained_dep, chained_path, + utils::{ + ast_utils::{ + assignment, call, cast, expression, ident, ident_path, index_array, + index_array_variable, make_eq, make_statement, make_type, member_access, method_call, + mutable_assignment, mutable_reference, path, return_type, variable, variable_ident, + variable_path, + }, + errors::AztecMacroError, + }, +}; + +// If it does, it will insert the following things: +/// - A new Input that is provided for a kernel app circuit, named: {Public/Private}ContextInputs +/// - Hashes all of the function input variables +/// - This instantiates a helper function +pub fn transform_function( + ty: &str, + func: &mut NoirFunction, + storage_defined: bool, + is_initializer: bool, + insert_init_check: bool, + is_internal: bool, +) -> Result<(), AztecMacroError> { + let context_name = format!("{}Context", ty); + let inputs_name = format!("{}ContextInputs", ty); + let return_type_name = format!("{}CircuitPublicInputs", ty); + + // Add check that msg sender equals this address and flag function as internal + if is_internal { + let is_internal_check = create_internal_check(func.name()); + func.def.body.0.insert(0, is_internal_check); + } + + // Add initialization check + if insert_init_check { + let init_check = create_init_check(); + func.def.body.0.insert(0, init_check); + } + + // Add access to the storage struct + if storage_defined { + let storage_def = abstract_storage(&ty.to_lowercase(), false); + func.def.body.0.insert(0, storage_def); + } + + // Insert the context creation as the first action + let create_context = create_context(&context_name, &func.def.parameters)?; + func.def.body.0.splice(0..0, (create_context).iter().cloned()); + + // Add the inputs to the params + let input = create_inputs(&inputs_name); + func.def.parameters.insert(0, input); + + // Abstract return types such that they get added to the kernel's return_values + if let Some(return_values) = abstract_return_values(func) { + // In case we are pushing return values to the context, we remove the statement that originated it + // This avoids running duplicate code, since blocks like if/else can be value returning statements + func.def.body.0.pop(); + // Add the new return statement + func.def.body.0.push(return_values); + } + + // Before returning mark the contract as initialized + if is_initializer { + let mark_initialized = create_mark_as_initialized(); + func.def.body.0.push(mark_initialized); + } + + // Push the finish method call to the end of the function + let finish_def = create_context_finish(); + func.def.body.0.push(finish_def); + + let return_type = create_return_type(&return_type_name); + func.def.return_type = return_type; + func.def.return_visibility = Visibility::Public; + + // Distinct return types are only required for private functions + // Public functions should have unconstrained auto-inferred + match ty { + "Private" => func.def.return_distinctness = Distinctness::Distinct, + "Public" => func.def.is_unconstrained = true, + _ => (), + } + + Ok(()) +} + +/// Transform a function to work with AVM bytecode +pub fn transform_vm_function( + func: &mut NoirFunction, + storage_defined: bool, +) -> Result<(), AztecMacroError> { + // Create access to storage + if storage_defined { + let storage = abstract_storage("public_vm", true); + func.def.body.0.insert(0, storage); + } + + // Push Avm context creation to the beginning of the function + let create_context = create_avm_context()?; + func.def.body.0.insert(0, create_context); + + // We want the function to be seen as a public function + func.def.is_unconstrained = true; + + // NOTE: the line below is a temporary hack to trigger external transpilation tools + // It will be removed once the transpiler is integrated into the Noir compiler + func.def.name.0.contents = format!("avm_{}", func.def.name.0.contents); + Ok(()) +} + +/// Transform Unconstrained +/// +/// Inserts the following code at the beginning of an unconstrained function +/// ```noir +/// let storage = Storage::init(Context::none()); +/// ``` +/// +/// This will allow developers to access their contract' storage struct in unconstrained functions +pub fn transform_unconstrained(func: &mut NoirFunction) { + func.def.body.0.insert(0, abstract_storage("Unconstrained", true)); +} + +/// Helper function that returns what the private context would look like in the ast +/// This should make it available to be consumed within aztec private annotated functions. +/// +/// The replaced code: +/// ```noir +/// /// Before +/// fn foo(inputs: PrivateContextInputs) { +/// // ... +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() { +/// // ... +/// } +fn create_inputs(ty: &str) -> Param { + let context_ident = ident("inputs"); + let context_pattern = Pattern::Identifier(context_ident); + + let path_snippet = ty.to_case(Case::Snake); // e.g. private_context_inputs + let type_path = chained_dep!("aztec", "context", "inputs", &path_snippet, ty); + + let context_type = make_type(UnresolvedTypeData::Named(type_path, vec![], true)); + let visibility = Visibility::Private; + + Param { pattern: context_pattern, typ: context_type, visibility, span: Span::default() } +} + +/// Creates an initialization check to ensure that the contract has been initialized, meant to +/// be injected as the first statement of any function after the context has been created. +/// +/// ```noir +/// assert_is_initialized(&mut context); +/// ``` +fn create_init_check() -> Statement { + make_statement(StatementKind::Expression(call( + variable_path(chained_dep!("aztec", "initializer", "assert_is_initialized")), + vec![mutable_reference("context")], + ))) +} + +/// Creates a call to mark_as_initialized which emits the initialization nullifier, meant to +/// be injected as the last statement before returning in a constructor. +/// +/// ```noir +/// mark_as_initialized(&mut context); +/// ``` +fn create_mark_as_initialized() -> Statement { + make_statement(StatementKind::Expression(call( + variable_path(chained_dep!("aztec", "initializer", "mark_as_initialized")), + vec![mutable_reference("context")], + ))) +} + +/// Creates a check for internal functions ensuring that the caller is self. +/// +/// ```noir +/// assert(context.msg_sender() == context.this_address(), "Function can only be called internally"); +/// ``` +fn create_internal_check(fname: &str) -> Statement { + make_statement(StatementKind::Constrain(ConstrainStatement( + make_eq( + method_call(variable("context"), "msg_sender", vec![]), + method_call(variable("context"), "this_address", vec![]), + ), + Some(expression(ExpressionKind::Literal(Literal::Str(format!( + "Function {} can only be called internally", + fname + ))))), + ConstrainKind::Assert, + ))) +} + +/// Creates the private context object to be accessed within the function, the parameters need to be extracted to be +/// appended into the args hash object. +/// +/// The replaced code: +/// ```noir +/// #[aztec(private)] +/// fn foo(structInput: SomeStruct, arrayInput: [u8; 10], fieldInput: Field) -> Field { +/// // Create the hasher object +/// let mut hasher = Hasher::new(); +/// +/// // struct inputs call serialize on them to add an array of fields +/// hasher.add_multiple(structInput.serialize()); +/// +/// // Array inputs are iterated over and each element is added to the hasher (as a field) +/// for i in 0..arrayInput.len() { +/// hasher.add(arrayInput[i] as Field); +/// } +/// // Field inputs are added to the hasher +/// hasher.add({ident}); +/// +/// // Create the context +/// // The inputs (injected by this `create_inputs`) and completed hash object are passed to the context +/// let mut context = PrivateContext::new(inputs, hasher.hash()); +/// } +/// ``` +fn create_context(ty: &str, params: &[Param]) -> Result, AztecMacroError> { + let mut injected_expressions: Vec = vec![]; + + // `let mut hasher = Hasher::new();` + let let_hasher = mutable_assignment( + "hasher", // Assigned to + call( + variable_path(chained_dep!("aztec", "hasher", "Hasher", "new")), // Path + vec![], // args + ), + ); + + // Completes: `let mut hasher = Hasher::new();` + injected_expressions.push(let_hasher); + + // Iterate over each of the function parameters, adding to them to the hasher + for Param { pattern, typ, span, .. } in params { + match pattern { + Pattern::Identifier(identifier) => { + // Match the type to determine the padding to do + let unresolved_type = &typ.typ; + let expression = match unresolved_type { + // `hasher.add_multiple({ident}.serialize())` + UnresolvedTypeData::Named(..) => add_struct_to_hasher(identifier), + UnresolvedTypeData::Array(_, arr_type) => { + add_array_to_hasher(identifier, arr_type) + } + // `hasher.add({ident})` + UnresolvedTypeData::FieldElement => add_field_to_hasher(identifier), + // Add the integer to the hasher, casted to a field + // `hasher.add({ident} as Field)` + UnresolvedTypeData::Integer(..) | UnresolvedTypeData::Bool => { + add_cast_to_hasher(identifier) + } + UnresolvedTypeData::String(..) => { + let (var_bytes, id) = str_to_bytes(identifier); + injected_expressions.push(var_bytes); + add_array_to_hasher( + &id, + &UnresolvedType { + typ: UnresolvedTypeData::Integer( + Signedness::Unsigned, + noirc_frontend::IntegerBitSize::ThirtyTwo, + ), + span: None, + }, + ) + } + _ => { + return Err(AztecMacroError::UnsupportedFunctionArgumentType { + typ: unresolved_type.clone(), + span: *span, + }) + } + }; + injected_expressions.push(expression); + } + _ => todo!(), // Maybe unreachable? + } + } + + // Create the inputs to the context + let inputs_expression = variable("inputs"); + // `hasher.hash()` + let hash_call = method_call( + variable("hasher"), // variable + "hash", // method name + vec![], // args + ); + + let path_snippet = ty.to_case(Case::Snake); // e.g. private_context + + // let mut context = {ty}::new(inputs, hash); + let let_context = mutable_assignment( + "context", // Assigned to + call( + variable_path(chained_dep!("aztec", "context", &path_snippet, ty, "new")), // Path + vec![inputs_expression, hash_call], // args + ), + ); + injected_expressions.push(let_context); + + // Return all expressions that will be injected by the hasher + Ok(injected_expressions) +} + +/// Creates an mutable avm context +/// +/// ```noir +/// /// Before +/// #[aztec(public-vm)] +/// fn foo() -> Field { +/// let mut context = aztec::context::AVMContext::new(); +/// let timestamp = context.timestamp(); +/// // ... +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() -> Field { +/// let mut timestamp = context.timestamp(); +/// // ... +/// } +fn create_avm_context() -> Result { + let let_context = mutable_assignment( + "context", // Assigned to + call( + variable_path(chained_dep!("aztec", "context", "AVMContext", "new")), // Path + vec![], // args + ), + ); + + Ok(let_context) +} + +/// Abstract Return Type +/// +/// This function intercepts the function's current return type and replaces it with pushes +/// To the kernel +/// +/// The replaced code: +/// ```noir +/// /// Before +/// #[aztec(private)] +/// fn foo() -> protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs { +/// // ... +/// let my_return_value: Field = 10; +/// context.return_values.push(my_return_value); +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() -> Field { +/// // ... +/// let my_return_value: Field = 10; +/// my_return_value +/// } +/// ``` +/// Similarly; Structs will be pushed to the context, after serialize() is called on them. +/// Arrays will be iterated over and each element will be pushed to the context. +/// Any primitive type that can be cast will be casted to a field and pushed to the context. +fn abstract_return_values(func: &NoirFunction) -> Option { + let current_return_type = func.return_type().typ; + let last_statement = func.def.body.0.last()?; + + // TODO: (length, type) => We can limit the size of the array returned to be limited by kernel size + // Doesn't need done until we have settled on a kernel size + // TODO: support tuples here and in inputs -> convert into an issue + // Check if the return type is an expression, if it is, we can handle it + match last_statement { + Statement { kind: StatementKind::Expression(expression), .. } => { + match current_return_type { + // Call serialize on structs, push the whole array, calling push_array + UnresolvedTypeData::Named(..) => Some(make_struct_return_type(expression.clone())), + UnresolvedTypeData::Array(..) => Some(make_array_return_type(expression.clone())), + // Cast these types to a field before pushing + UnresolvedTypeData::Bool | UnresolvedTypeData::Integer(..) => { + Some(make_castable_return_type(expression.clone())) + } + UnresolvedTypeData::FieldElement => Some(make_return_push(expression.clone())), + _ => None, + } + } + _ => None, + } +} + +/// Abstract storage +/// +/// For private functions: +/// ```noir +/// #[aztec(private)] +/// fn lol() { +/// let storage = Storage::init(Context::private(context)); +/// } +/// ``` +/// +/// For public functions: +/// ```noir +/// #[aztec(public)] +/// fn lol() { +/// let storage = Storage::init(Context::public(context)); +/// } +/// ``` +/// +/// For unconstrained functions: +/// ```noir +/// unconstrained fn lol() { +/// let storage = Storage::init(Context::none()); +/// } +fn abstract_storage(typ: &str, unconstrained: bool) -> Statement { + let init_context_call = if unconstrained { + call( + variable_path(chained_dep!("aztec", "context", "Context", "none")), // Path + vec![], // args + ) + } else { + call( + variable_path(chained_dep!("aztec", "context", "Context", typ)), // Path + vec![mutable_reference("context")], // args + ) + }; + + assignment( + "storage", // Assigned to + call( + variable_path(chained_path!("Storage", "init")), // Path + vec![init_context_call], // args + ), + ) +} + +/// Context Return Values +/// +/// Creates an instance to the context return values +/// ```noir +/// `context.return_values` +/// ``` +fn context_return_values() -> Expression { + member_access("context", "return_values") +} + +/// Make return Push +/// +/// Translates to: +/// `context.return_values.push({push_value})` +fn make_return_push(push_value: Expression) -> Statement { + make_statement(StatementKind::Semi(method_call( + context_return_values(), + "push", + vec![push_value], + ))) +} + +/// Make Return push array +/// +/// Translates to: +/// `context.return_values.extend_from_array({push_value})` +fn make_return_extend_from_array(push_value: Expression) -> Statement { + make_statement(StatementKind::Semi(method_call( + context_return_values(), + "extend_from_array", + vec![push_value], + ))) +} + +/// Make struct return type +/// +/// Translates to: +/// ```noir +/// `context.return_values.extend_from_array({push_value}.serialize())` +fn make_struct_return_type(expression: Expression) -> Statement { + let serialized_call = method_call( + expression, // variable + "serialize", // method name + vec![], // args + ); + make_return_extend_from_array(serialized_call) +} + +/// Make array return type +/// +/// Translates to: +/// ```noir +/// for i in 0..{ident}.len() { +/// context.return_values.push({ident}[i] as Field) +/// } +/// ``` +fn make_array_return_type(expression: Expression) -> Statement { + let inner_cast_expression = + cast(index_array_variable(expression.clone(), "i"), UnresolvedTypeData::FieldElement); + let assignment = make_statement(StatementKind::Semi(method_call( + context_return_values(), // variable + "push", // method name + vec![inner_cast_expression], + ))); + + create_loop_over(expression, vec![assignment]) +} + +/// Castable return type +/// +/// Translates to: +/// ```noir +/// context.return_values.push({ident} as Field) +/// ``` +fn make_castable_return_type(expression: Expression) -> Statement { + // Cast these types to a field before pushing + let cast_expression = cast(expression, UnresolvedTypeData::FieldElement); + make_return_push(cast_expression) +} + +/// Create Return Type +/// +/// Public functions return protocol_types::abis::public_circuit_public_inputs::PublicCircuitPublicInputs while +/// private functions return protocol_types::abis::private_circuit_public_inputs::::PrivateCircuitPublicInputs +/// +/// This call constructs an ast token referencing the above types +/// The name is set in the function above `transform`, hence the +/// whole token name is passed in +/// +/// The replaced code: +/// ```noir +/// +/// /// Before +/// fn foo() -> protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs { +/// // ... +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() { +/// // ... +/// } +fn create_return_type(ty: &str) -> FunctionReturnType { + let path_snippet = ty.to_case(Case::Snake); // e.g. private_circuit_public_inputs or public_circuit_public_inputs + let return_path = chained_dep!("aztec", "protocol_types", "abis", &path_snippet, ty); + return_type(return_path) +} + +/// Create Context Finish +/// +/// Each aztec function calls `context.finish()` at the end of a function +/// to return values required by the kernel. +/// +/// The replaced code: +/// ```noir +/// /// Before +/// fn foo() -> protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs { +/// // ... +/// context.finish() +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() { +/// // ... +/// } +fn create_context_finish() -> Statement { + let method_call = method_call( + variable("context"), // variable + "finish", // method name + vec![], // args + ); + make_statement(StatementKind::Expression(method_call)) +} + +// +// Methods to create hasher inputs +// + +fn add_struct_to_hasher(identifier: &Ident) -> Statement { + // If this is a struct, we call serialize and add the array to the hasher + let serialized_call = method_call( + variable_path(path(identifier.clone())), // variable + "serialize", // method name + vec![], // args + ); + + make_statement(StatementKind::Semi(method_call( + variable("hasher"), // variable + "add_multiple", // method name + vec![serialized_call], // args + ))) +} + +fn str_to_bytes(identifier: &Ident) -> (Statement, Ident) { + // let identifier_as_bytes = identifier.as_bytes(); + let var = variable_ident(identifier.clone()); + let contents = if let ExpressionKind::Variable(p) = &var.kind { + p.segments.first().cloned().unwrap_or_else(|| panic!("No segments")).0.contents + } else { + panic!("Unexpected identifier type") + }; + let bytes_name = format!("{}_bytes", contents); + let var_bytes = assignment(&bytes_name, method_call(var, "as_bytes", vec![])); + let id = Ident::new(bytes_name, Span::default()); + + (var_bytes, id) +} + +fn create_loop_over(var: Expression, loop_body: Vec) -> Statement { + // If this is an array of primitive types (integers / fields) we can add them each to the hasher + // casted to a field + let span = var.span; + + // `array.len()` + let end_range_expression = method_call( + var, // variable + "len", // method name + vec![], // args + ); + + // What will be looped over + // - `hasher.add({ident}[i] as Field)` + let for_loop_block = expression(ExpressionKind::Block(BlockExpression(loop_body))); + + // `for i in 0..{ident}.len()` + make_statement(StatementKind::For(ForLoopStatement { + range: ForRange::Range( + expression(ExpressionKind::Literal(Literal::Integer( + FieldElement::from(i128::from(0)), + false, + ))), + end_range_expression, + ), + identifier: ident("i"), + block: for_loop_block, + span, + })) +} + +fn add_array_to_hasher(identifier: &Ident, arr_type: &UnresolvedType) -> Statement { + // If this is an array of primitive types (integers / fields) we can add them each to the hasher + // casted to a field + + // Wrap in the semi thing - does that mean ended with semi colon? + // `hasher.add({ident}[i] as Field)` + + let arr_index = index_array(identifier.clone(), "i"); + let (add_expression, hasher_method_name) = match arr_type.typ { + UnresolvedTypeData::Named(..) => { + let hasher_method_name = "add_multiple".to_owned(); + let call = method_call( + // All serialize on each element + arr_index, // variable + "serialize", // method name + vec![], // args + ); + (call, hasher_method_name) + } + _ => { + let hasher_method_name = "add".to_owned(); + let call = cast( + arr_index, // lhs - `ident[i]` + UnresolvedTypeData::FieldElement, // cast to - `as Field` + ); + (call, hasher_method_name) + } + }; + + let block_statement = make_statement(StatementKind::Semi(method_call( + variable("hasher"), // variable + &hasher_method_name, // method name + vec![add_expression], + ))); + + create_loop_over(variable_ident(identifier.clone()), vec![block_statement]) +} + +fn add_field_to_hasher(identifier: &Ident) -> Statement { + // `hasher.add({ident})` + let ident = variable_path(path(identifier.clone())); + make_statement(StatementKind::Semi(method_call( + variable("hasher"), // variable + "add", // method name + vec![ident], // args + ))) +} + +fn add_cast_to_hasher(identifier: &Ident) -> Statement { + // `hasher.add({ident} as Field)` + // `{ident} as Field` + let cast_operation = cast( + variable_path(path(identifier.clone())), // lhs + UnresolvedTypeData::FieldElement, // rhs + ); + + // `hasher.add({ident} as Field)` + make_statement(StatementKind::Semi(method_call( + variable("hasher"), // variable + "add", // method name + vec![cast_operation], // args + ))) +} diff --git a/noir/noir-repo/aztec_macros/src/transforms/mod.rs b/noir/noir-repo/aztec_macros/src/transforms/mod.rs new file mode 100644 index 00000000000..144ffc3efc3 --- /dev/null +++ b/noir/noir-repo/aztec_macros/src/transforms/mod.rs @@ -0,0 +1,4 @@ +pub mod compute_note_hash_and_nullifier; +pub mod events; +pub mod functions; +pub mod storage; diff --git a/noir/noir-repo/aztec_macros/src/transforms/storage.rs b/noir/noir-repo/aztec_macros/src/transforms/storage.rs new file mode 100644 index 00000000000..40a094f78e3 --- /dev/null +++ b/noir/noir-repo/aztec_macros/src/transforms/storage.rs @@ -0,0 +1,346 @@ +use std::borrow::{Borrow, BorrowMut}; + +use noirc_errors::Span; +use noirc_frontend::{ + graph::CrateId, + macros_api::{ + FieldElement, FileId, HirContext, HirExpression, HirLiteral, HirStatement, NodeInterner, + }, + node_interner::{TraitId, TraitImplKind}, + parser::SortedModule, + BlockExpression, Expression, ExpressionKind, FunctionDefinition, Ident, Literal, NoirFunction, + PathKind, Pattern, StatementKind, Type, TypeImpl, UnresolvedType, UnresolvedTypeData, +}; + +use crate::{ + chained_dep, chained_path, + utils::{ + ast_utils::{ + call, expression, ident, ident_path, lambda, make_statement, make_type, pattern, + return_type, variable, variable_path, + }, + errors::AztecMacroError, + hir_utils::{collect_crate_structs, collect_traits}, + }, +}; + +// Check to see if the user has defined a storage struct +pub fn check_for_storage_definition(module: &SortedModule) -> bool { + module.types.iter().any(|r#struct| r#struct.name.0.contents == "Storage") +} + +// Check to see if the user has defined a storage struct +pub fn check_for_storage_implementation(module: &SortedModule) -> bool { + module.impls.iter().any(|r#impl| match &r#impl.object_type.typ { + UnresolvedTypeData::Named(path, _, _) => { + path.segments.last().is_some_and(|segment| segment.0.contents == "Storage") + } + _ => false, + }) +} + +/// Auxiliary function to generate the storage constructor for a given field, using +/// the Storage definition as a reference. Supports nesting. +pub fn generate_storage_field_constructor( + (type_ident, unresolved_type): &(Ident, UnresolvedType), + slot: Expression, +) -> Result { + let typ = &unresolved_type.typ; + match typ { + UnresolvedTypeData::Named(path, generics, _) => { + let mut new_path = path.clone().to_owned(); + new_path.segments.push(ident("new")); + match path.segments.last().unwrap().0.contents.as_str() { + "Map" => Ok(call( + variable_path(new_path), + vec![ + variable("context"), + slot, + lambda( + vec![ + ( + pattern("context"), + make_type(UnresolvedTypeData::Named( + chained_dep!("aztec", "context", "Context"), + vec![], + true, + )), + ), + ( + Pattern::Identifier(ident("slot")), + make_type(UnresolvedTypeData::FieldElement), + ), + ], + generate_storage_field_constructor( + &(type_ident.clone(), generics.iter().last().unwrap().clone()), + variable("slot"), + )?, + ), + ], + )), + _ => Ok(call(variable_path(new_path), vec![variable("context"), slot])), + } + } + _ => Err(AztecMacroError::UnsupportedStorageType { + typ: typ.clone(), + span: Some(type_ident.span()), + }), + } +} + +// Generates the Storage implementation block from the Storage struct definition if it does not exist +/// From: +/// +/// struct Storage { +/// a_map: Map>, +/// a_nested_map: Map>>, +/// a_field: SomeStoragePrimitive, +/// } +/// +/// To: +/// +/// impl Storage { +/// fn init(context: Context) -> Self { +/// Storage { +/// a_map: Map::new(context, 0, |context, slot| { +/// SomeStoragePrimitive::new(context, slot) +/// }), +/// a_nested_map: Map::new(context, 0, |context, slot| { +/// Map::new(context, slot, |context, slot| { +/// SomeStoragePrimitive::new(context, slot) +/// }) +/// }), +/// a_field: SomeStoragePrimitive::new(context, 0), +/// } +/// } +/// } +/// +/// Storage slots are generated as 0 and will be populated using the information from the HIR +/// at a later stage. +pub fn generate_storage_implementation(module: &mut SortedModule) -> Result<(), AztecMacroError> { + let definition = + module.types.iter().find(|r#struct| r#struct.name.0.contents == "Storage").unwrap(); + + let slot_zero = expression(ExpressionKind::Literal(Literal::Integer( + FieldElement::from(i128::from(0)), + false, + ))); + + let field_constructors = definition + .fields + .iter() + .flat_map(|field| { + generate_storage_field_constructor(field, slot_zero.clone()) + .map(|expression| (field.0.clone(), expression)) + }) + .collect(); + + let storage_constructor_statement = make_statement(StatementKind::Expression(expression( + ExpressionKind::constructor((chained_path!("Storage"), field_constructors)), + ))); + + let init = NoirFunction::normal(FunctionDefinition::normal( + &ident("init"), + &vec![], + &[( + ident("context"), + make_type(UnresolvedTypeData::Named( + chained_dep!("aztec", "context", "Context"), + vec![], + true, + )), + )], + &BlockExpression(vec![storage_constructor_statement]), + &[], + &return_type(chained_path!("Self")), + )); + + let storage_impl = TypeImpl { + object_type: UnresolvedType { + typ: UnresolvedTypeData::Named(chained_path!("Storage"), vec![], true), + span: Some(Span::default()), + }, + type_span: Span::default(), + generics: vec![], + methods: vec![(init, Span::default())], + }; + module.impls.push(storage_impl); + + Ok(()) +} + +/// Obtains the serialized length of a type that implements the Serialize trait. +fn get_serialized_length( + traits: &[TraitId], + typ: &Type, + interner: &NodeInterner, +) -> Result { + let (struct_name, maybe_stored_in_state) = match typ { + Type::Struct(struct_type, generics) => { + Ok((struct_type.borrow().name.0.contents.clone(), generics.first())) + } + _ => Err(AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some("State storage variable must be a struct".to_string()), + }), + }?; + let stored_in_state = + maybe_stored_in_state.ok_or(AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some("State storage variable must be generic".to_string()), + })?; + + let is_note = traits.iter().any(|&trait_id| { + let r#trait = interner.get_trait(trait_id); + r#trait.name.0.contents == "NoteInterface" + && !interner.lookup_all_trait_implementations(stored_in_state, trait_id).is_empty() + }); + + // Maps and (private) Notes always occupy a single slot. Someone could store a Note in PublicMutable for whatever reason though. + if struct_name == "Map" || (is_note && struct_name != "PublicMutable") { + return Ok(1); + } + + let serialized_trait_impl_kind = traits + .iter() + .find_map(|&trait_id| { + let r#trait = interner.get_trait(trait_id); + if r#trait.borrow().name.0.contents == "Serialize" + && r#trait.borrow().generics.len() == 1 + { + interner + .lookup_all_trait_implementations(stored_in_state, trait_id) + .into_iter() + .next() + } else { + None + } + }) + .ok_or(AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some("Stored data must implement Serialize trait".to_string()), + })?; + + let serialized_trait_impl_id = match serialized_trait_impl_kind { + TraitImplKind::Normal(trait_impl_id) => Ok(trait_impl_id), + _ => Err(AztecMacroError::CouldNotAssignStorageSlots { secondary_message: None }), + }?; + + let serialized_trait_impl_shared = interner.get_trait_implementation(*serialized_trait_impl_id); + let serialized_trait_impl = serialized_trait_impl_shared.borrow(); + + match serialized_trait_impl.trait_generics.first().unwrap() { + Type::Constant(value) => Ok(*value), + _ => Err(AztecMacroError::CouldNotAssignStorageSlots { secondary_message: None }), + } +} + +/// Assigns storage slots to the storage struct fields based on the serialized length of the types. This automatic assignment +/// will only trigger if the assigned storage slot is invalid (0 as generated by generate_storage_implementation) +pub fn assign_storage_slots( + crate_id: &CrateId, + context: &mut HirContext, +) -> Result<(), (AztecMacroError, FileId)> { + let traits: Vec<_> = collect_traits(context); + for struct_id in collect_crate_structs(crate_id, context) { + let interner: &mut NodeInterner = context.def_interner.borrow_mut(); + let r#struct = interner.get_struct(struct_id); + let file_id = r#struct.borrow().location.file; + if r#struct.borrow().name.0.contents == "Storage" && r#struct.borrow().id.krate().is_root() + { + let init_id = interner + .lookup_method( + &Type::Struct(interner.get_struct(struct_id), vec![]), + struct_id, + "init", + false, + ) + .ok_or(( + AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some( + "Storage struct must have an init function".to_string(), + ), + }, + file_id, + ))?; + let init_function = interner.function(&init_id).block(interner); + let init_function_statement_id = init_function.statements().first().ok_or(( + AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some("Init storage statement not found".to_string()), + }, + file_id, + ))?; + let storage_constructor_statement = interner.statement(init_function_statement_id); + + let storage_constructor_expression = match storage_constructor_statement { + HirStatement::Expression(expression_id) => { + match interner.expression(&expression_id) { + HirExpression::Constructor(hir_constructor_expression) => { + Ok(hir_constructor_expression) + } + _ => Err((AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some( + "Storage constructor statement must be a constructor expression" + .to_string(), + ), + }, file_id)) + } + } + _ => Err(( + AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some( + "Storage constructor statement must be an expression".to_string(), + ), + }, + file_id, + )), + }?; + + let mut storage_slot: u64 = 1; + for (index, (_, expr_id)) in storage_constructor_expression.fields.iter().enumerate() { + let fields = r#struct.borrow().get_fields(&[]); + let (_, field_type) = fields.get(index).unwrap(); + let new_call_expression = match interner.expression(expr_id) { + HirExpression::Call(hir_call_expression) => Ok(hir_call_expression), + _ => Err(( + AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some( + "Storage field initialization expression is not a call expression" + .to_string(), + ), + }, + file_id, + )), + }?; + + let slot_arg_expression = interner.expression(&new_call_expression.arguments[1]); + + let current_storage_slot = match slot_arg_expression { + HirExpression::Literal(HirLiteral::Integer(slot, _)) => Ok(slot.to_u128()), + _ => Err(( + AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some( + "Storage slot argument expression must be a literal integer" + .to_string(), + ), + }, + file_id, + )), + }?; + + if current_storage_slot != 0 { + continue; + } + + let type_serialized_len = get_serialized_length(&traits, field_type, interner) + .map_err(|err| (err, file_id))?; + interner.update_expression(new_call_expression.arguments[1], |expr| { + *expr = HirExpression::Literal(HirLiteral::Integer( + FieldElement::from(u128::from(storage_slot)), + false, + )); + }); + + storage_slot += type_serialized_len; + } + } + } + Ok(()) +} diff --git a/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs b/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs new file mode 100644 index 00000000000..71c6a93f388 --- /dev/null +++ b/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs @@ -0,0 +1,183 @@ +use noirc_errors::{Span, Spanned}; +use noirc_frontend::{ + token::SecondaryAttribute, BinaryOpKind, CallExpression, CastExpression, Expression, + ExpressionKind, FunctionReturnType, Ident, IndexExpression, InfixExpression, Lambda, + LetStatement, MemberAccessExpression, MethodCallExpression, Path, Pattern, PrefixExpression, + Statement, StatementKind, UnaryOp, UnresolvedType, UnresolvedTypeData, +}; + +// +// Helper macros for creating noir ast nodes +// +pub fn ident(name: &str) -> Ident { + Ident::new(name.to_string(), Span::default()) +} + +pub fn ident_path(name: &str) -> Path { + Path::from_ident(ident(name)) +} + +pub fn path(ident: Ident) -> Path { + Path::from_ident(ident) +} + +pub fn expression(kind: ExpressionKind) -> Expression { + Expression::new(kind, Span::default()) +} + +pub fn variable(name: &str) -> Expression { + expression(ExpressionKind::Variable(ident_path(name))) +} + +pub fn variable_ident(identifier: Ident) -> Expression { + expression(ExpressionKind::Variable(path(identifier))) +} + +pub fn variable_path(path: Path) -> Expression { + expression(ExpressionKind::Variable(path)) +} + +pub fn method_call( + object: Expression, + method_name: &str, + arguments: Vec, +) -> Expression { + expression(ExpressionKind::MethodCall(Box::new(MethodCallExpression { + object, + method_name: ident(method_name), + arguments, + }))) +} + +pub fn call(func: Expression, arguments: Vec) -> Expression { + expression(ExpressionKind::Call(Box::new(CallExpression { func: Box::new(func), arguments }))) +} + +pub fn pattern(name: &str) -> Pattern { + Pattern::Identifier(ident(name)) +} + +pub fn mutable(name: &str) -> Pattern { + Pattern::Mutable(Box::new(pattern(name)), Span::default(), true) +} + +pub fn mutable_assignment(name: &str, assigned_to: Expression) -> Statement { + make_statement(StatementKind::Let(LetStatement { + pattern: mutable(name), + r#type: make_type(UnresolvedTypeData::Unspecified), + expression: assigned_to, + })) +} + +pub fn mutable_reference(variable_name: &str) -> Expression { + expression(ExpressionKind::Prefix(Box::new(PrefixExpression { + operator: UnaryOp::MutableReference, + rhs: variable(variable_name), + }))) +} + +pub fn assignment(name: &str, assigned_to: Expression) -> Statement { + make_statement(StatementKind::Let(LetStatement { + pattern: pattern(name), + r#type: make_type(UnresolvedTypeData::Unspecified), + expression: assigned_to, + })) +} + +pub fn member_access(lhs: &str, rhs: &str) -> Expression { + expression(ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { + lhs: variable(lhs), + rhs: ident(rhs), + }))) +} + +pub fn return_type(path: Path) -> FunctionReturnType { + let ty = make_type(UnresolvedTypeData::Named(path, vec![], true)); + FunctionReturnType::Ty(ty) +} + +pub fn lambda(parameters: Vec<(Pattern, UnresolvedType)>, body: Expression) -> Expression { + expression(ExpressionKind::Lambda(Box::new(Lambda { + parameters, + return_type: UnresolvedType { + typ: UnresolvedTypeData::Unspecified, + span: Some(Span::default()), + }, + body, + }))) +} + +pub fn make_eq(lhs: Expression, rhs: Expression) -> Expression { + expression(ExpressionKind::Infix(Box::new(InfixExpression { + lhs, + rhs, + operator: Spanned::from(Span::default(), BinaryOpKind::Equal), + }))) +} + +pub fn make_statement(kind: StatementKind) -> Statement { + Statement { span: Span::default(), kind } +} + +#[macro_export] +macro_rules! chained_path { + ( $base:expr ) => { + { + ident_path($base) + } + }; + ( $base:expr $(, $tail:expr)* ) => { + { + let mut base_path = ident_path($base); + $( + base_path.segments.push(ident($tail)); + )* + base_path + } + } +} + +#[macro_export] +macro_rules! chained_dep { + ( $base:expr $(, $tail:expr)* ) => { + { + let mut base_path = ident_path($base); + base_path.kind = PathKind::Dep; + $( + base_path.segments.push(ident($tail)); + )* + base_path + } + } +} + +pub fn cast(lhs: Expression, ty: UnresolvedTypeData) -> Expression { + expression(ExpressionKind::Cast(Box::new(CastExpression { lhs, r#type: make_type(ty) }))) +} + +pub fn make_type(typ: UnresolvedTypeData) -> UnresolvedType { + UnresolvedType { typ, span: Some(Span::default()) } +} + +pub fn index_array(array: Ident, index: &str) -> Expression { + expression(ExpressionKind::Index(Box::new(IndexExpression { + collection: variable_path(path(array)), + index: variable(index), + }))) +} + +pub fn index_array_variable(array: Expression, index: &str) -> Expression { + expression(ExpressionKind::Index(Box::new(IndexExpression { + collection: array, + index: variable(index), + }))) +} + +/// Checks if an attribute is a custom attribute with a specific name +pub fn is_custom_attribute(attr: &SecondaryAttribute, attribute_name: &str) -> bool { + if let SecondaryAttribute::Custom(custom_attr) = attr { + custom_attr.as_str() == attribute_name + } else { + false + } +} diff --git a/noir/noir-repo/aztec_macros/src/utils/checks.rs b/noir/noir-repo/aztec_macros/src/utils/checks.rs new file mode 100644 index 00000000000..5232f67ae87 --- /dev/null +++ b/noir/noir-repo/aztec_macros/src/utils/checks.rs @@ -0,0 +1,22 @@ +use noirc_frontend::{ + graph::CrateId, + macros_api::{FileId, HirContext, MacroError}, +}; + +use super::errors::AztecMacroError; + +/// Creates an error alerting the user that they have not downloaded the Aztec-noir library +pub fn check_for_aztec_dependency( + crate_id: &CrateId, + context: &HirContext, +) -> Result<(), (MacroError, FileId)> { + if has_aztec_dependency(crate_id, context) { + Ok(()) + } else { + Err((AztecMacroError::AztecDepNotFound.into(), context.crate_graph[crate_id].root_file_id)) + } +} + +pub fn has_aztec_dependency(crate_id: &CrateId, context: &HirContext) -> bool { + context.crate_graph[crate_id].dependencies.iter().any(|dep| dep.as_name() == "aztec") +} diff --git a/noir/noir-repo/aztec_macros/src/utils/constants.rs b/noir/noir-repo/aztec_macros/src/utils/constants.rs new file mode 100644 index 00000000000..464cd10e2c7 --- /dev/null +++ b/noir/noir-repo/aztec_macros/src/utils/constants.rs @@ -0,0 +1,3 @@ +pub const FUNCTION_TREE_HEIGHT: u32 = 5; +pub const MAX_CONTRACT_PRIVATE_FUNCTIONS: usize = 2_usize.pow(FUNCTION_TREE_HEIGHT); +pub const SIGNATURE_PLACEHOLDER: &str = "SIGNATURE_PLACEHOLDER"; diff --git a/noir/noir-repo/aztec_macros/src/utils/errors.rs b/noir/noir-repo/aztec_macros/src/utils/errors.rs new file mode 100644 index 00000000000..63892b58af9 --- /dev/null +++ b/noir/noir-repo/aztec_macros/src/utils/errors.rs @@ -0,0 +1,69 @@ +use noirc_errors::Span; +use noirc_frontend::{macros_api::MacroError, UnresolvedTypeData}; + +use super::constants::MAX_CONTRACT_PRIVATE_FUNCTIONS; + +#[derive(Debug, Clone)] +pub enum AztecMacroError { + AztecDepNotFound, + ContractHasTooManyPrivateFunctions { span: Span }, + ContractConstructorMissing { span: Span }, + UnsupportedFunctionArgumentType { span: Span, typ: UnresolvedTypeData }, + UnsupportedStorageType { span: Option, typ: UnresolvedTypeData }, + CouldNotAssignStorageSlots { secondary_message: Option }, + CouldNotImplementNoteSerialization { span: Option, typ: UnresolvedTypeData }, + EventError { span: Span, message: String }, + UnsupportedAttributes { span: Span, secondary_message: Option }, +} + +impl From for MacroError { + fn from(err: AztecMacroError) -> Self { + match err { + AztecMacroError::AztecDepNotFound {} => MacroError { + primary_message: "Aztec dependency not found. Please add aztec as a dependency in your Cargo.toml. For more information go to https://docs.aztec.network/developers/debugging/aztecnr-errors#aztec-dependency-not-found-please-add-aztec-as-a-dependency-in-your-nargotoml".to_owned(), + secondary_message: None, + span: None, + }, + AztecMacroError::ContractHasTooManyPrivateFunctions { span } => MacroError { + primary_message: format!("Contract can only have a maximum of {} private functions", MAX_CONTRACT_PRIVATE_FUNCTIONS), + secondary_message: None, + span: Some(span), + }, + AztecMacroError::ContractConstructorMissing { span } => MacroError { + primary_message: "Contract must have a constructor function".to_owned(), + secondary_message: None, + span: Some(span), + }, + AztecMacroError::UnsupportedFunctionArgumentType { span, typ } => MacroError { + primary_message: format!("Provided parameter type `{typ:?}` is not supported in Aztec contract interface"), + secondary_message: None, + span: Some(span), + }, + AztecMacroError::UnsupportedStorageType { span, typ } => MacroError { + primary_message: format!("Provided storage type `{typ:?}` is not directly supported in Aztec. Please provide a custom storage implementation"), + secondary_message: None, + span, + }, + AztecMacroError::CouldNotAssignStorageSlots { secondary_message } => MacroError { + primary_message: "Could not assign storage slots, please provide a custom storage implementation".to_string(), + secondary_message, + span: None, + }, + AztecMacroError::CouldNotImplementNoteSerialization { span, typ } => MacroError { + primary_message: format!("Could not implement serialization methods for note `{typ:?}`, please provide a serialize_content and deserialize_content methods"), + secondary_message: None, + span, + }, + AztecMacroError::EventError { span, message } => MacroError { + primary_message: message, + secondary_message: None, + span: Some(span), + }, +AztecMacroError::UnsupportedAttributes { span, secondary_message } => MacroError { + primary_message: "Unsupported attributes in contract function".to_string(), + secondary_message, + span: Some(span), + }, + } + } +} diff --git a/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs b/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs new file mode 100644 index 00000000000..f31a0584261 --- /dev/null +++ b/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs @@ -0,0 +1,118 @@ +use iter_extended::vecmap; +use noirc_frontend::{ + graph::CrateId, + hir::def_collector::dc_crate::UnresolvedTraitImpl, + macros_api::{HirContext, ModuleDefId, StructId}, + node_interner::{TraitId, TraitImplId}, + Signedness, Type, UnresolvedTypeData, +}; + +pub fn collect_crate_structs(crate_id: &CrateId, context: &HirContext) -> Vec { + context + .def_map(crate_id) + .expect("ICE: Missing crate in def_map") + .modules() + .iter() + .flat_map(|(_, module)| { + module.type_definitions().filter_map(|typ| { + if let ModuleDefId::TypeId(struct_id) = typ { + Some(struct_id) + } else { + None + } + }) + }) + .collect() +} + +pub fn collect_traits(context: &HirContext) -> Vec { + let crates = context.crates(); + crates + .flat_map(|crate_id| context.def_map(&crate_id).map(|def_map| def_map.modules())) + .flatten() + .flat_map(|module| { + module.type_definitions().filter_map(|typ| { + if let ModuleDefId::TraitId(struct_id) = typ { + Some(struct_id) + } else { + None + } + }) + }) + .collect() +} + +/// Computes the aztec signature for a resolved type. +pub fn signature_of_type(typ: &Type) -> String { + match typ { + Type::Integer(Signedness::Signed, bit_size) => format!("i{}", bit_size), + Type::Integer(Signedness::Unsigned, bit_size) => format!("u{}", bit_size), + Type::FieldElement => "Field".to_owned(), + Type::Bool => "bool".to_owned(), + Type::Array(len, typ) => { + if let Type::Constant(len) = **len { + format!("[{};{len}]", signature_of_type(typ)) + } else { + unimplemented!("Cannot generate signature for array with length type {:?}", typ) + } + } + Type::Struct(def, args) => { + let fields = def.borrow().get_fields(args); + let fields = vecmap(fields, |(_, typ)| signature_of_type(&typ)); + format!("({})", fields.join(",")) + } + Type::Tuple(types) => { + let fields = vecmap(types, signature_of_type); + format!("({})", fields.join(",")) + } + _ => unimplemented!("Cannot generate signature for type {:?}", typ), + } +} + +// Fetches the name of all structs that implement trait_name, both in the current crate and all of its dependencies. +pub fn fetch_struct_trait_impls( + context: &mut HirContext, + unresolved_traits_impls: &[UnresolvedTraitImpl], + trait_name: &str, +) -> Vec { + let mut struct_typenames: Vec = Vec::new(); + + // These structs can be declared in either external crates or the current one. External crates that contain + // dependencies have already been processed and resolved, but are available here via the NodeInterner. Note that + // crates on which the current crate does not depend on may not have been processed, and will be ignored. + for trait_impl_id in 0..context.def_interner.next_trait_impl_id().0 { + let trait_impl = &context.def_interner.get_trait_implementation(TraitImplId(trait_impl_id)); + + if trait_impl.borrow().ident.0.contents == *trait_name { + if let Type::Struct(s, _) = &trait_impl.borrow().typ { + struct_typenames.push(s.borrow().name.0.contents.clone()); + } else { + panic!("Found impl for {} on non-Struct", trait_name); + } + } + } + + // This crate's traits and impls have not yet been resolved, so we look for impls in unresolved_trait_impls. + struct_typenames.extend( + unresolved_traits_impls + .iter() + .filter(|trait_impl| { + trait_impl + .trait_path + .segments + .last() + .expect("ICE: empty trait_impl path") + .0 + .contents + == *trait_name + }) + .filter_map(|trait_impl| match &trait_impl.object_type.typ { + UnresolvedTypeData::Named(path, _, _) => { + Some(path.segments.last().unwrap().0.contents.clone()) + } + _ => None, + }), + ); + + struct_typenames +} diff --git a/noir/noir-repo/aztec_macros/src/utils/mod.rs b/noir/noir-repo/aztec_macros/src/utils/mod.rs new file mode 100644 index 00000000000..c8914f83025 --- /dev/null +++ b/noir/noir-repo/aztec_macros/src/utils/mod.rs @@ -0,0 +1,5 @@ +pub mod ast_utils; +pub mod checks; +pub mod constants; +pub mod errors; +pub mod hir_utils; diff --git a/noir/noir-repo/compiler/noirc_driver/Cargo.toml b/noir/noir-repo/compiler/noirc_driver/Cargo.toml index 681976735f3..a7fe0b4b610 100644 --- a/noir/noir-repo/compiler/noirc_driver/Cargo.toml +++ b/noir/noir-repo/compiler/noirc_driver/Cargo.toml @@ -26,4 +26,3 @@ tracing.workspace = true thiserror.workspace = true aztec_macros = { path = "../../aztec_macros" } -noirc_macros = { path = "../../noirc_macros" } diff --git a/noir/noir-repo/compiler/noirc_driver/src/contract.rs b/noir/noir-repo/compiler/noirc_driver/src/contract.rs index 5f4b66e7dd2..66e8dc0e730 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/contract.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/contract.rs @@ -9,23 +9,6 @@ use noirc_evaluator::errors::SsaReport; use super::debug::DebugFile; -/// Describes the types of smart contract functions that are allowed. -/// Unlike the similar enum in noirc_frontend, 'open' and 'unconstrained' -/// are mutually exclusive here. In the case a function is both, 'unconstrained' -/// takes precedence. -#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)] -pub enum ContractFunctionType { - /// This function will be executed in a private - /// context. - Secret, - /// This function will be executed in a public - /// context. - Open, - /// This function cannot constrain any values and can use nondeterministic features - /// like arrays of a dynamic size. - Unconstrained, -} - #[derive(Clone, Debug, Serialize, Deserialize)] pub struct CompiledContract { pub noir_version: String, @@ -55,9 +38,9 @@ pub struct CompiledContract { pub struct ContractFunction { pub name: String, - pub function_type: ContractFunctionType, + pub is_unconstrained: bool, - pub is_internal: bool, + pub custom_attributes: Vec, pub abi: Abi, @@ -69,13 +52,3 @@ pub struct ContractFunction { pub debug: DebugInfo, } - -impl ContractFunctionType { - pub(super) fn new(kind: noirc_frontend::ContractFunctionType, is_unconstrained: bool) -> Self { - match (kind, is_unconstrained) { - (_, true) => Self::Unconstrained, - (noirc_frontend::ContractFunctionType::Secret, false) => Self::Secret, - (noirc_frontend::ContractFunctionType::Open, false) => Self::Open, - } - } -} diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index 11f53cdb749..c9494a64b41 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -18,6 +18,7 @@ use noirc_frontend::hir::Context; use noirc_frontend::macros_api::MacroProcessor; use noirc_frontend::monomorphization::{monomorphize, monomorphize_debug, MonomorphizationError}; use noirc_frontend::node_interner::FuncId; +use noirc_frontend::token::SecondaryAttribute; use std::path::Path; use thiserror::Error; use tracing::info; @@ -30,7 +31,7 @@ mod stdlib; use debug::filter_relevant_files; -pub use contract::{CompiledContract, ContractFunction, ContractFunctionType}; +pub use contract::{CompiledContract, ContractFunction}; pub use debug::DebugFile; pub use program::CompiledProgram; @@ -237,14 +238,8 @@ pub fn check_crate( deny_warnings: bool, disable_macros: bool, ) -> CompilationResult<()> { - let macros: Vec<&dyn MacroProcessor> = if disable_macros { - vec![&noirc_macros::AssertMessageMacro as &dyn MacroProcessor] - } else { - vec![ - &aztec_macros::AztecMacro as &dyn MacroProcessor, - &noirc_macros::AssertMessageMacro as &dyn MacroProcessor, - ] - }; + let macros: &[&dyn MacroProcessor] = + if disable_macros { &[] } else { &[&aztec_macros::AztecMacro as &dyn MacroProcessor] }; let mut errors = vec![]; let diagnostics = CrateDefMap::collect_defs(crate_id, context, macros); @@ -404,19 +399,24 @@ fn compile_contract_inner( }; warnings.extend(function.warnings); let modifiers = context.def_interner.function_modifiers(&function_id); - let func_type = modifiers - .contract_function_type - .expect("Expected contract function to have a contract visibility"); - let function_type = ContractFunctionType::new(func_type, modifiers.is_unconstrained); + let custom_attributes = modifiers + .attributes + .secondary + .iter() + .filter_map( + |attr| if let SecondaryAttribute::Custom(tag) = attr { Some(tag) } else { None }, + ) + .cloned() + .collect(); functions.push(ContractFunction { name, - function_type, - is_internal: modifiers.is_internal.unwrap_or(false), + custom_attributes, abi: function.abi, bytecode: function.circuit, debug: function.debug, + is_unconstrained: modifiers.is_unconstrained, }); } diff --git a/noir/noir-repo/compiler/noirc_errors/src/debug_info.rs b/noir/noir-repo/compiler/noirc_errors/src/debug_info.rs index 67ec851d46d..09117bdc3b7 100644 --- a/noir/noir-repo/compiler/noirc_errors/src/debug_info.rs +++ b/noir/noir-repo/compiler/noirc_errors/src/debug_info.rs @@ -24,6 +24,9 @@ use serde::{ #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, Deserialize, Serialize)] pub struct DebugVarId(pub u32); +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, Deserialize, Serialize)] +pub struct DebugFnId(pub u32); + #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, Deserialize, Serialize)] pub struct DebugTypeId(pub u32); @@ -33,7 +36,14 @@ pub struct DebugVariable { pub debug_type_id: DebugTypeId, } +#[derive(Debug, Clone, Hash, Deserialize, Serialize)] +pub struct DebugFunction { + pub name: String, + pub arg_names: Vec, +} + pub type DebugVariables = BTreeMap; +pub type DebugFunctions = BTreeMap; pub type DebugTypes = BTreeMap; #[serde_as] @@ -45,6 +55,7 @@ pub struct DebugInfo { #[serde_as(as = "BTreeMap")] pub locations: BTreeMap>, pub variables: DebugVariables, + pub functions: DebugFunctions, pub types: DebugTypes, } @@ -60,9 +71,10 @@ impl DebugInfo { pub fn new( locations: BTreeMap>, variables: DebugVariables, + functions: DebugFunctions, types: DebugTypes, ) -> Self { - Self { locations, variables, types } + Self { locations, variables, functions, types } } /// Updates the locations map when the [`Circuit`][acvm::acir::circuit::Circuit] is modified. diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index 0189a499d49..5b227372396 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -248,17 +248,6 @@ impl<'block> BrilligBlock<'block> { self.convert_ssa_binary(binary, dfg, result_var); } Instruction::Constrain(lhs, rhs, assert_message) => { - let condition = SingleAddrVariable { - address: self.brillig_context.allocate_register(), - bit_size: 1, - }; - - self.convert_ssa_binary( - &Binary { lhs: *lhs, rhs: *rhs, operator: BinaryOp::Eq }, - dfg, - condition, - ); - let assert_message = if let Some(error) = assert_message { match error.as_ref() { ConstrainError::Static(string) => Some(string.clone()), @@ -282,6 +271,17 @@ impl<'block> BrilligBlock<'block> { None }; + let condition = SingleAddrVariable { + address: self.brillig_context.allocate_register(), + bit_size: 1, + }; + + self.convert_ssa_binary( + &Binary { lhs: *lhs, rhs: *rhs, operator: BinaryOp::Eq }, + dfg, + condition, + ); + self.brillig_context.constrain_instruction(condition.address, assert_message); self.brillig_context.deallocate_register(condition.address); } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index 0bb81efe977..56cb76adbe4 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -88,6 +88,7 @@ pub fn create_circuit( ) -> Result<(Circuit, DebugInfo, Vec, Vec, Vec), RuntimeError> { let debug_variables = program.debug_variables.clone(); let debug_types = program.debug_types.clone(); + let debug_functions = program.debug_functions.clone(); let func_sig = program.main_function_signature.clone(); let recursive = program.recursive; let mut generated_acir = optimize_into_acir( @@ -130,7 +131,7 @@ pub fn create_circuit( .map(|(index, locations)| (index, locations.into_iter().collect())) .collect(); - let mut debug_info = DebugInfo::new(locations, debug_variables, debug_types); + let mut debug_info = DebugInfo::new(locations, debug_variables, debug_functions, debug_types); // Perform any ACIR-level optimizations let (optimized_circuit, transformation_map) = acvm::compiler::optimize(circuit); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 8d4d0668534..140ed0b53ff 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -2268,11 +2268,9 @@ impl Context { // We can omit the element size array for arrays which don't contain arrays or slices. fn can_omit_element_sizes_array(array_typ: &Type) -> bool { - if array_typ.contains_slice_element() { - return false; - } - let Type::Array(types, _) = array_typ else { - panic!("ICE: expected array type"); + let types = match array_typ { + Type::Array(types, _) | Type::Slice(types) => types, + _ => panic!("ICE: expected array or slice type"), }; !types.iter().any(|typ| typ.contains_an_array()) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index 9d27554dcaa..bf34a47485b 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -393,10 +393,25 @@ impl FunctionBuilder { self.increment_array_reference_count(value); } } - Type::Array(..) | Type::Slice(..) => { - self.insert_instruction(Instruction::IncrementRc { value }, None); + typ @ Type::Array(..) | typ @ Type::Slice(..) => { // If there are nested arrays or slices, we wait until ArrayGet // is issued to increment the count of that array. + self.insert_instruction(Instruction::IncrementRc { value }, None); + + // This is a bit odd, but in brillig the inc_rc instruction operates on + // a copy of the array's metadata, so we need to re-store a loaded array + // even if there have been no other changes to it. + if let Value::Instruction { instruction, .. } = &self.current_function.dfg[value] { + let instruction = &self.current_function.dfg[*instruction]; + if let Instruction::Load { address } = instruction { + // We can't re-use `value` in case the original address was stored + // to again in the meantime. So introduce another load. + let address = *address; + let value = self.insert_load(address, typ); + self.insert_instruction(Instruction::IncrementRc { value }, None); + self.insert_store(address, value); + } + } } } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index 943a57c1bc0..46f1e7a2765 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -199,22 +199,47 @@ struct Context<'f> { /// found, the top of this conditions stack is popped since we are no longer under that /// condition. If we are under multiple conditions (a nested if), the topmost condition is /// the most recent condition combined with all previous conditions via `And` instructions. - conditions: Vec<(BasicBlockId, ValueId)>, + condition_stack: Vec, /// Maps SSA array values with a slice type to their size. /// This is maintained by appropriate calls to the `SliceCapacityTracker` and is used by the `ValueMerger`. slice_sizes: HashMap, + + /// Stack of block arguments + /// When processing a block, we pop this stack to get its arguments + /// and at the end we push the arguments for his successor + arguments_stack: Vec>, } +#[derive(Clone)] pub(crate) struct Store { old_value: ValueId, new_value: ValueId, } -struct Branch { - condition: ValueId, +#[derive(Clone)] +struct ConditionalBranch { + // Contains the last processed block during the processing of the branch. last_block: BasicBlockId, + // The unresolved condition of the branch + old_condition: ValueId, + // The condition of the branch + condition: ValueId, + // The store values accumulated when processing the branch store_values: HashMap, + // The allocations accumulated when processing the branch + local_allocations: HashSet, +} + +struct ConditionalContext { + // Condition from the conditional statement + condition: ValueId, + // Block containing the conditional statement + entry_block: BasicBlockId, + // First block of the then branch + then_branch: ConditionalBranch, + // First block of the else branch + else_branch: Option, } fn flatten_function_cfg(function: &mut Function) { @@ -233,90 +258,117 @@ fn flatten_function_cfg(function: &mut Function) { store_values: HashMap::default(), local_allocations: HashSet::new(), branch_ends, - conditions: Vec::new(), slice_sizes: HashMap::default(), + condition_stack: Vec::new(), + arguments_stack: Vec::new(), }; context.flatten(); } impl<'f> Context<'f> { fn flatten(&mut self) { - // Start with following the terminator of the entry block since we don't - // need to flatten the entry block into itself. - self.handle_terminator(self.inserter.function.entry_block()); + // Flatten the CFG by inlining all instructions from the queued blocks + // until all blocks have been flattened. + // We follow the terminator of each block to determine which blocks to + // process next + let mut queue = vec![self.inserter.function.entry_block()]; + while let Some(block) = queue.pop() { + self.inline_block(block); + let to_process = self.handle_terminator(block, &queue); + for incoming_block in to_process { + if !queue.contains(&incoming_block) { + queue.push(incoming_block); + } + } + } } - /// Check the terminator of the given block and recursively inline any blocks reachable from - /// it. Since each block from a jmpif terminator is inlined successively, we must handle - /// instructions with side effects like constrain and store specially to preserve correctness. - /// For these instructions we must keep track of what the current condition is and modify - /// the instructions according to the module-level comment at the top of this file. Note that - /// the current condition is all the jmpif conditions required to reach the current block, - /// combined via `And` instructions. - /// - /// Returns the last block to be inlined. This is either the return block of the function or, - /// if self.conditions is not empty, the end block of the most recent condition. - fn handle_terminator(&mut self, block: BasicBlockId) -> BasicBlockId { - // As we recursively flatten inner blocks, we need to track the slice information - // for the outer block before we start recursively inlining - let outer_block_instructions = self.inserter.function.dfg[block].instructions(); - let mut capacity_tracker = SliceCapacityTracker::new(&self.inserter.function.dfg); - for instruction in outer_block_instructions { - let results = self.inserter.function.dfg.instruction_results(*instruction); - let instruction = &self.inserter.function.dfg[*instruction]; + /// Returns the updated condition so that + /// it is 'AND-ed' with the previous condition (if any) + fn link_condition(&mut self, condition: ValueId) -> ValueId { + // Retrieve the previous condition + if let Some(context) = self.condition_stack.last() { + let previous_branch = context.else_branch.as_ref().unwrap_or(&context.then_branch); + let and = Instruction::binary(BinaryOp::And, previous_branch.condition, condition); + self.insert_instruction(and, CallStack::new()) + } else { + condition + } + } + + /// Returns the current condition + fn get_last_condition(&self) -> Option { + self.condition_stack.last().map(|context| match &context.else_branch { + Some(else_branch) => else_branch.condition, + None => context.then_branch.condition, + }) + } + + // Inline all instructions from the given block into the entry block, and track slice capacities + fn inline_block(&mut self, block: BasicBlockId) { + if self.inserter.function.entry_block() == block { + // we do not inline the entry block into itself + // for the outer block before we start inlining + let outer_block_instructions = self.inserter.function.dfg[block].instructions(); + let mut capacity_tracker = SliceCapacityTracker::new(&self.inserter.function.dfg); + for instruction in outer_block_instructions { + let results = self.inserter.function.dfg.instruction_results(*instruction); + let instruction = &self.inserter.function.dfg[*instruction]; + capacity_tracker.collect_slice_information( + instruction, + &mut self.slice_sizes, + results.to_vec(), + ); + } + + return; + } + + let arguments = self.arguments_stack.pop().unwrap(); + self.inserter.remember_block_params(block, &arguments); + + // If this is not a separate variable, clippy gets confused and says the to_vec is + // unnecessary, when removing it actually causes an aliasing/mutability error. + let instructions = self.inserter.function.dfg[block].instructions().to_vec(); + for instruction in instructions.iter() { + let results = self.push_instruction(*instruction); + let (instruction, _) = self.inserter.map_instruction(*instruction); + let mut capacity_tracker = SliceCapacityTracker::new(&self.inserter.function.dfg); capacity_tracker.collect_slice_information( - instruction, + &instruction, &mut self.slice_sizes, - results.to_vec(), + results, ); } + } - match self.inserter.function.dfg[block].unwrap_terminator() { + /// Returns the list of blocks that need to be processed after the given block + /// For a normal block, it would be its successor + /// For blocks related to a conditional statement, we ensure to process + /// the 'then-branch', then the 'else-branch' (if it exists), and finally the end block + fn handle_terminator( + &mut self, + block: BasicBlockId, + work_list: &[BasicBlockId], + ) -> Vec { + let terminator = self.inserter.function.dfg[block].unwrap_terminator().clone(); + match &terminator { TerminatorInstruction::JmpIf { condition, then_destination, else_destination } => { - let old_condition = *condition; - let then_block = *then_destination; - let else_block = *else_destination; - let then_condition = self.inserter.resolve(old_condition); - - let one = FieldElement::one(); - let then_branch = - self.inline_branch(block, then_block, old_condition, then_condition, one); - - let else_condition = - self.insert_instruction(Instruction::Not(then_condition), CallStack::new()); - let zero = FieldElement::zero(); - - // Make sure the else branch sees the previous values of each store - // rather than any values created in the 'then' branch. - self.undo_stores_in_then_branch(&then_branch); - - let else_branch = - self.inline_branch(block, else_block, old_condition, else_condition, zero); - - // We must remember to reset whether side effects are enabled when both branches - // end, in addition to resetting the value of old_condition since it is set to - // known to be true/false within the then/else branch respectively. - self.insert_current_side_effects_enabled(); - - // We must map back to `then_condition` here. Mapping `old_condition` to itself would - // lose any previous mappings. - self.inserter.map_value(old_condition, then_condition); - - // While there is a condition on the stack we don't compile outside the condition - // until it is popped. This ensures we inline the full then and else branches - // before continuing from the end of the conditional here where they can be merged properly. - let end = self.branch_ends[&block]; - self.inline_branch_end(end, then_branch, else_branch) + self.arguments_stack.push(vec![]); + self.if_start(condition, then_destination, else_destination, &block) } TerminatorInstruction::Jmp { destination, arguments, call_stack: _ } => { - if let Some((end_block, _)) = self.conditions.last() { - if destination == end_block { - return block; + let arguments = vecmap(arguments.clone(), |value| self.inserter.resolve(value)); + self.arguments_stack.push(arguments); + if work_list.contains(destination) { + if work_list.last() == Some(destination) { + self.else_stop(&block) + } else { + self.then_stop(&block) } + } else { + vec![*destination] } - let destination = *destination; - let arguments = vecmap(arguments.clone(), |value| self.inserter.resolve(value)); - self.inline_block(destination, &arguments) } TerminatorInstruction::Return { return_values, call_stack } => { let call_stack = call_stack.clone(); @@ -326,133 +378,133 @@ impl<'f> Context<'f> { let entry = self.inserter.function.entry_block(); self.inserter.function.dfg.set_block_terminator(entry, new_return); - block + vec![] } } } - /// Push a condition to the stack of conditions. - /// - /// This condition should be present while we're inlining each block reachable from the 'then' - /// branch of a jmpif instruction, until the branches eventually join back together. Likewise, - /// !condition should be present while we're inlining each block reachable from the 'else' - /// branch of a jmpif instruction until the join block. - fn push_condition(&mut self, start_block: BasicBlockId, condition: ValueId) { - let end_block = self.branch_ends[&start_block]; - - if let Some((_, previous_condition)) = self.conditions.last() { - let and = Instruction::binary(BinaryOp::And, *previous_condition, condition); - let new_condition = self.insert_instruction(and, CallStack::new()); - self.conditions.push((end_block, new_condition)); - } else { - self.conditions.push((end_block, condition)); + /// Process a conditional statement + fn if_start( + &mut self, + condition: &ValueId, + then_destination: &BasicBlockId, + else_destination: &BasicBlockId, + if_entry: &BasicBlockId, + ) -> Vec { + // manage conditions + let old_condition = *condition; + let then_condition = self.inserter.resolve(old_condition); + + let one = FieldElement::one(); + let old_stores = std::mem::take(&mut self.store_values); + let old_allocations = std::mem::take(&mut self.local_allocations); + let branch = ConditionalBranch { + old_condition, + condition: self.link_condition(then_condition), + store_values: old_stores, + local_allocations: old_allocations, + last_block: *then_destination, + }; + let cond_context = ConditionalContext { + condition: then_condition, + entry_block: *if_entry, + then_branch: branch, + else_branch: None, + }; + self.condition_stack.push(cond_context); + self.insert_current_side_effects_enabled(); + // Optimization: within the then branch we know the condition to be true, so replace + // any references of it within this branch with true. Likewise, do the same with false + // with the else branch. We must be careful not to replace the condition if it is a + // known constant, otherwise we can end up setting 1 = 0 or vice-versa. + if self.inserter.function.dfg.get_numeric_constant(old_condition).is_none() { + let known_value = self.inserter.function.dfg.make_constant(one, Type::bool()); + + self.inserter.map_value(old_condition, known_value); } + vec![self.branch_ends[if_entry], *else_destination, *then_destination] } - /// Insert a new instruction into the function's entry block. - /// Unlike push_instruction, this function will not map any ValueIds. - /// within the given instruction, nor will it modify self.values in any way. - fn insert_instruction(&mut self, instruction: Instruction, call_stack: CallStack) -> ValueId { - let block = self.inserter.function.entry_block(); - self.inserter - .function - .dfg - .insert_instruction_and_results(instruction, block, None, call_stack) - .first() + /// Switch context to the 'else-branch' + fn then_stop(&mut self, block: &BasicBlockId) -> Vec { + let mut cond_context = self.condition_stack.pop().unwrap(); + cond_context.then_branch.last_block = *block; + + let else_condition = + self.insert_instruction(Instruction::Not(cond_context.condition), CallStack::new()); + let else_condition = self.link_condition(else_condition); + + let zero = FieldElement::zero(); + // Make sure the else branch sees the previous values of each store + // rather than any values created in the 'then' branch. + let old_stores = std::mem::take(&mut cond_context.then_branch.store_values); + cond_context.then_branch.store_values = std::mem::take(&mut self.store_values); + self.undo_stores_in_then_branch(&cond_context.then_branch.store_values); + + let old_allocations = std::mem::take(&mut self.local_allocations); + let else_branch = ConditionalBranch { + old_condition: cond_context.then_branch.old_condition, + condition: else_condition, + store_values: old_stores, + local_allocations: old_allocations, + last_block: *block, + }; + let old_condition = else_branch.old_condition; + cond_context.then_branch.local_allocations.clear(); + cond_context.else_branch = Some(else_branch); + self.condition_stack.push(cond_context); + + self.insert_current_side_effects_enabled(); + // Optimization: within the then branch we know the condition to be true, so replace + // any references of it within this branch with true. Likewise, do the same with false + // with the else branch. We must be careful not to replace the condition if it is a + // known constant, otherwise we can end up setting 1 = 0 or vice-versa. + if self.inserter.function.dfg.get_numeric_constant(old_condition).is_none() { + let known_value = self.inserter.function.dfg.make_constant(zero, Type::bool()); + + self.inserter.map_value(old_condition, known_value); + } + assert_eq!(self.cfg.successors(*block).len(), 1); + vec![self.cfg.successors(*block).next().unwrap()] } - /// Inserts a new instruction into the function's entry block, using the given - /// control type variables to specify result types if needed. - /// Unlike push_instruction, this function will not map any ValueIds. - /// within the given instruction, nor will it modify self.values in any way. - fn insert_instruction_with_typevars( - &mut self, - instruction: Instruction, - ctrl_typevars: Option>, - ) -> InsertInstructionResult { - let block = self.inserter.function.entry_block(); - self.inserter.function.dfg.insert_instruction_and_results( - instruction, - block, - ctrl_typevars, - CallStack::new(), - ) - } + /// Process the 'exit' block of a conditional statement + fn else_stop(&mut self, block: &BasicBlockId) -> Vec { + let mut cond_context = self.condition_stack.pop().unwrap(); + if cond_context.else_branch.is_none() { + // then_stop() has not been called, this means that the conditional statement has no else branch + // so we simply do the then_stop() now + self.condition_stack.push(cond_context); + self.then_stop(block); + cond_context = self.condition_stack.pop().unwrap(); + } - /// Checks the branch condition on the top of the stack and uses it to build and insert an - /// `EnableSideEffects` instruction into the entry block. - /// - /// If the stack is empty, a "true" u1 constant is taken to be the active condition. This is - /// necessary for re-enabling side-effects when re-emerging to a branch depth of 0. - fn insert_current_side_effects_enabled(&mut self) { - let condition = match self.conditions.last() { - Some((_, cond)) => *cond, - None => { - self.inserter.function.dfg.make_constant(FieldElement::one(), Type::unsigned(1)) - } - }; - let enable_side_effects = Instruction::EnableSideEffects { condition }; - self.insert_instruction_with_typevars(enable_side_effects, None); - } + let mut else_branch = cond_context.else_branch.unwrap(); + let stores_in_branch = std::mem::replace(&mut self.store_values, else_branch.store_values); + self.local_allocations = std::mem::take(&mut else_branch.local_allocations); + else_branch.last_block = *block; + else_branch.store_values = stores_in_branch; + cond_context.else_branch = Some(else_branch); - /// Inline one branch of a jmpif instruction. - /// - /// This will continue inlining recursively until the next end block is reached where each branch - /// of the jmpif instruction is joined back into a single block. - /// - /// Within a branch of a jmpif instruction, we can assume the condition of the jmpif to be - /// always true or false, depending on which branch we're in. - /// - /// Returns the ending block / join block of this branch. - fn inline_branch( - &mut self, - jmpif_block: BasicBlockId, - destination: BasicBlockId, - old_condition: ValueId, - new_condition: ValueId, - condition_value: FieldElement, - ) -> Branch { - if destination == self.branch_ends[&jmpif_block] { - // If the branch destination is the same as the end of the branch, this must be the - // 'else' case of an if with no else - so there is no else branch. - Branch { - condition: new_condition, - // The last block here is somewhat arbitrary. It only matters that it has no Jmp - // args that will be merged by inline_branch_end. Since jmpifs don't have - // block arguments, it is safe to use the jmpif block here. - last_block: jmpif_block, - store_values: HashMap::default(), - } - } else { - self.push_condition(jmpif_block, new_condition); - self.insert_current_side_effects_enabled(); - let old_stores = std::mem::take(&mut self.store_values); - let old_allocations = std::mem::take(&mut self.local_allocations); - - // Optimization: within the then branch we know the condition to be true, so replace - // any references of it within this branch with true. Likewise, do the same with false - // with the else branch. We must be careful not to replace the condition if it is a - // known constant, otherwise we can end up setting 1 = 0 or vice-versa. - if self.inserter.function.dfg.get_numeric_constant(old_condition).is_none() { - let known_value = - self.inserter.function.dfg.make_constant(condition_value, Type::bool()); - - self.inserter.map_value(old_condition, known_value); - } + // We must remember to reset whether side effects are enabled when both branches + // end, in addition to resetting the value of old_condition since it is set to + // known to be true/false within the then/else branch respectively. + self.insert_current_side_effects_enabled(); - let final_block = self.inline_block(destination, &[]); + // We must map back to `then_condition` here. Mapping `old_condition` to itself would + // lose any previous mappings. + self.inserter + .map_value(cond_context.then_branch.old_condition, cond_context.then_branch.condition); - self.conditions.pop(); + // While there is a condition on the stack we don't compile outside the condition + // until it is popped. This ensures we inline the full then and else branches + // before continuing from the end of the conditional here where they can be merged properly. + let end = self.branch_ends[&cond_context.entry_block]; - let stores_in_branch = std::mem::replace(&mut self.store_values, old_stores); - self.local_allocations = old_allocations; + // Merge arguments and stores from the else/end branches + self.inline_branch_end(end, cond_context); - Branch { - condition: new_condition, - last_block: final_block, - store_values: stores_in_branch, - } - } + vec![self.cfg.successors(*block).next().unwrap()] } /// Inline the ending block of a branch, the point where all blocks from a jmpif instruction @@ -467,15 +519,17 @@ impl<'f> Context<'f> { fn inline_branch_end( &mut self, destination: BasicBlockId, - then_branch: Branch, - else_branch: Branch, + cond_context: ConditionalContext, ) -> BasicBlockId { assert_eq!(self.cfg.predecessors(destination).len(), 2); + let last_then = cond_context.then_branch.last_block; + let mut else_args = Vec::new(); + if cond_context.else_branch.is_some() { + let last_else = cond_context.else_branch.clone().unwrap().last_block; + else_args = self.inserter.function.dfg[last_else].terminator_arguments().to_vec(); + } - let then_args = - self.inserter.function.dfg[then_branch.last_block].terminator_arguments().to_vec(); - let else_args = - self.inserter.function.dfg[else_branch.last_block].terminator_arguments().to_vec(); + let then_args = self.inserter.function.dfg[last_then].terminator_arguments().to_vec(); let params = self.inserter.function.dfg.block_parameters(destination); assert_eq!(params.len(), then_args.len()); @@ -500,17 +554,64 @@ impl<'f> Context<'f> { // Cannot include this in the previous vecmap since it requires exclusive access to self let args = vecmap(args, |(then_arg, else_arg)| { value_merger.merge_values( - then_branch.condition, - else_branch.condition, + cond_context.then_branch.condition, + cond_context.else_branch.clone().unwrap().condition, then_arg, else_arg, ) }); - self.merge_stores(then_branch, else_branch); + self.merge_stores(cond_context.then_branch, cond_context.else_branch); + self.arguments_stack.pop(); + self.arguments_stack.pop(); + self.arguments_stack.push(args); + destination + } - // insert merge instruction - self.inline_block(destination, &args) + /// Insert a new instruction into the function's entry block. + /// Unlike push_instruction, this function will not map any ValueIds. + /// within the given instruction, nor will it modify self.values in any way. + fn insert_instruction(&mut self, instruction: Instruction, call_stack: CallStack) -> ValueId { + let block = self.inserter.function.entry_block(); + self.inserter + .function + .dfg + .insert_instruction_and_results(instruction, block, None, call_stack) + .first() + } + + /// Inserts a new instruction into the function's entry block, using the given + /// control type variables to specify result types if needed. + /// Unlike push_instruction, this function will not map any ValueIds. + /// within the given instruction, nor will it modify self.values in any way. + fn insert_instruction_with_typevars( + &mut self, + instruction: Instruction, + ctrl_typevars: Option>, + ) -> InsertInstructionResult { + let block = self.inserter.function.entry_block(); + self.inserter.function.dfg.insert_instruction_and_results( + instruction, + block, + ctrl_typevars, + CallStack::new(), + ) + } + + /// Checks the branch condition on the top of the stack and uses it to build and insert an + /// `EnableSideEffects` instruction into the entry block. + /// + /// If the stack is empty, a "true" u1 constant is taken to be the active condition. This is + /// necessary for re-enabling side-effects when re-emerging to a branch depth of 0. + fn insert_current_side_effects_enabled(&mut self) { + let condition = match self.get_last_condition() { + Some(cond) => cond, + None => { + self.inserter.function.dfg.make_constant(FieldElement::one(), Type::unsigned(1)) + } + }; + let enable_side_effects = Instruction::EnableSideEffects { condition }; + self.insert_instruction_with_typevars(enable_side_effects, None); } /// Merge any store instructions found in each branch. @@ -518,7 +619,11 @@ impl<'f> Context<'f> { /// This function relies on the 'then' branch being merged before the 'else' branch of a jmpif /// instruction. If this ordering is changed, the ordering that store values are merged within /// this function also needs to be changed to reflect that. - fn merge_stores(&mut self, then_branch: Branch, else_branch: Branch) { + fn merge_stores( + &mut self, + then_branch: ConditionalBranch, + else_branch: Option, + ) { // Address -> (then_value, else_value, value_before_the_if) let mut new_map = BTreeMap::new(); @@ -526,11 +631,13 @@ impl<'f> Context<'f> { new_map.insert(address, (store.new_value, store.old_value, store.old_value)); } - for (address, store) in else_branch.store_values { - if let Some(entry) = new_map.get_mut(&address) { - entry.1 = store.new_value; - } else { - new_map.insert(address, (store.old_value, store.new_value, store.old_value)); + if else_branch.is_some() { + for (address, store) in else_branch.clone().unwrap().store_values { + if let Some(entry) = new_map.get_mut(&address) { + entry.1 = store.new_value; + } else { + new_map.insert(address, (store.old_value, store.new_value, store.old_value)); + } } } @@ -544,8 +651,11 @@ impl<'f> Context<'f> { } let then_condition = then_branch.condition; - let else_condition = else_branch.condition; - + let else_condition = if let Some(branch) = else_branch { + branch.condition + } else { + self.inserter.function.dfg.make_constant(FieldElement::zero(), Type::bool()) + }; let block = self.inserter.function.entry_block(); let mut value_merger = @@ -607,35 +717,6 @@ impl<'f> Context<'f> { } } - /// Inline all instructions from the given destination block into the entry block. - /// Afterwards, check the block's terminator and continue inlining recursively. - /// - /// Returns the final block that was inlined. - /// - /// Expects that the `arguments` given are already translated via self.inserter.resolve. - /// If they are not, it is possible some values which no longer exist, such as block - /// parameters, will be kept in the program. - fn inline_block(&mut self, destination: BasicBlockId, arguments: &[ValueId]) -> BasicBlockId { - self.inserter.remember_block_params(destination, arguments); - - // If this is not a separate variable, clippy gets confused and says the to_vec is - // unnecessary, when removing it actually causes an aliasing/mutability error. - let instructions = self.inserter.function.dfg[destination].instructions().to_vec(); - - for instruction in instructions.iter() { - let results = self.push_instruction(*instruction); - let (instruction, _) = self.inserter.map_instruction(*instruction); - let mut capacity_tracker = SliceCapacityTracker::new(&self.inserter.function.dfg); - capacity_tracker.collect_slice_information( - &instruction, - &mut self.slice_sizes, - results, - ); - } - - self.handle_terminator(destination) - } - /// Push the given instruction to the end of the entry block of the current function. /// /// Note that each ValueId of the instruction will be mapped via self.inserter.resolve. @@ -666,7 +747,7 @@ impl<'f> Context<'f> { instruction: Instruction, call_stack: CallStack, ) -> Instruction { - if let Some((_, condition)) = self.conditions.last().copied() { + if let Some(condition) = self.get_last_condition() { match instruction { Instruction::Constrain(lhs, rhs, message) => { // Replace constraint `lhs == rhs` with `condition * lhs == condition * rhs`. @@ -741,8 +822,8 @@ impl<'f> Context<'f> { } } - fn undo_stores_in_then_branch(&mut self, then_branch: &Branch) { - for (address, store) in &then_branch.store_values { + fn undo_stores_in_then_branch(&mut self, store_values: &HashMap) { + for (address, store) in store_values { let address = *address; let value = store.old_value; self.insert_instruction_with_typevars(Instruction::Store { address, value }, None); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/capacity_tracker.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/capacity_tracker.rs index 7cd0fe3084e..bdfc04f0bbe 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/capacity_tracker.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/capacity_tracker.rs @@ -5,6 +5,7 @@ use crate::ssa::ir::{ value::{Value, ValueId}, }; +use acvm::FieldElement; use fxhash::FxHashMap as HashMap; pub(crate) struct SliceCapacityTracker<'a> { @@ -62,21 +63,27 @@ impl<'a> SliceCapacityTracker<'a> { | Intrinsic::SlicePushFront | Intrinsic::SlicePopBack | Intrinsic::SliceInsert - | Intrinsic::SliceRemove => (1, 1), + | Intrinsic::SliceRemove => (Some(1), 1), // `pop_front` returns the popped element, and then the respective slice. // This means in the case of a slice with structs, the result index of the popped slice // will change depending on the number of elements in the struct. // For example, a slice with four elements will look as such in SSA: // v3, v4, v5, v6, v7, v8 = call slice_pop_front(v1, v2) // where v7 is the slice length and v8 is the popped slice itself. - Intrinsic::SlicePopFront => (1, results.len() - 1), + Intrinsic::SlicePopFront => (Some(1), results.len() - 1), + // The slice capacity of these intrinsics is not determined by the arguments of the function. + Intrinsic::ToBits(_) | Intrinsic::ToRadix(_) => (None, 1), _ => return, }; - let slice_contents = arguments[argument_index]; + let result_slice = results[result_index]; match intrinsic { Intrinsic::SlicePushBack | Intrinsic::SlicePushFront | Intrinsic::SliceInsert => { + let argument_index = argument_index + .expect("ICE: Should have an argument index for slice intrinsics"); + let slice_contents = arguments[argument_index]; + for arg in &arguments[(argument_index + 1)..] { let element_typ = self.dfg.type_of_value(*arg); if element_typ.contains_slice_element() { @@ -85,20 +92,35 @@ impl<'a> SliceCapacityTracker<'a> { } if let Some(contents_capacity) = slice_sizes.get(&slice_contents) { let new_capacity = *contents_capacity + 1; - slice_sizes.insert(results[result_index], new_capacity); + slice_sizes.insert(result_slice, new_capacity); } } Intrinsic::SlicePopBack | Intrinsic::SliceRemove | Intrinsic::SlicePopFront => { + let argument_index = argument_index + .expect("ICE: Should have an argument index for slice intrinsics"); + let slice_contents = arguments[argument_index]; + // We do not decrement the size on intrinsics that could remove values from a slice. // This is because we could potentially go back to the smaller slice and not fill in dummies. // This pass should be tracking the potential max that a slice ***could be*** if let Some(contents_capacity) = slice_sizes.get(&slice_contents) { let new_capacity = *contents_capacity - 1; - slice_sizes.insert(results[result_index], new_capacity); + slice_sizes.insert(result_slice, new_capacity); } } + Intrinsic::ToBits(_) => { + // Compiler sanity check + assert!(matches!(self.dfg.type_of_value(result_slice), Type::Slice(_))); + slice_sizes.insert(result_slice, FieldElement::max_num_bits() as usize); + } + Intrinsic::ToRadix(_) => { + // Compiler sanity check + assert!(matches!(self.dfg.type_of_value(result_slice), Type::Slice(_))); + slice_sizes + .insert(result_slice, FieldElement::max_num_bytes() as usize); + } _ => {} } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index d95295ae3c9..f3fa5d1d2f8 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -722,6 +722,11 @@ impl<'a> FunctionContext<'a> { let lhs = self.extract_current_value(&assign.lvalue)?; let rhs = self.codegen_expression(&assign.expression)?; + rhs.clone().for_each(|value| { + let value = value.eval(self); + self.builder.increment_array_reference_count(value); + }); + self.assign_new_value(lhs, rhs); Ok(Self::unit_value()) } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs index 2a252633a29..a9ecc1a53e5 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs @@ -3,7 +3,7 @@ use std::fmt::Display; use crate::token::{Attributes, Token}; use crate::{ - Distinctness, FunctionVisibility, Ident, Path, Pattern, Recoverable, Statement, StatementKind, + Distinctness, Ident, ItemVisibility, Path, Pattern, Recoverable, Statement, StatementKind, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, Visibility, }; use acvm::FieldElement; @@ -369,16 +369,11 @@ pub struct FunctionDefinition { // and `secondary` attributes (ones that do not change the function kind) pub attributes: Attributes, - /// True if this function was defined with the 'open' keyword - pub is_open: bool, - - pub is_internal: bool, - /// True if this function was defined with the 'unconstrained' keyword pub is_unconstrained: bool, /// Indicate if this function was defined with the 'pub' keyword - pub visibility: FunctionVisibility, + pub visibility: ItemVisibility, pub generics: UnresolvedGenerics, pub parameters: Vec, @@ -406,18 +401,6 @@ pub enum FunctionReturnType { Ty(UnresolvedType), } -/// Describes the types of smart contract functions that are allowed. -/// - All Noir programs in the non-contract context can be seen as `Secret`. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum ContractFunctionType { - /// This function will be executed in a private - /// context. - Secret, - /// This function will be executed in a public - /// context. - Open, -} - #[derive(Debug, PartialEq, Eq, Clone)] pub enum ArrayLiteral { Standard(Vec), @@ -674,10 +657,8 @@ impl FunctionDefinition { FunctionDefinition { name: name.clone(), attributes: Attributes::empty(), - is_open: false, - is_internal: false, is_unconstrained: false, - visibility: FunctionVisibility::Private, + visibility: ItemVisibility::Private, generics: generics.clone(), parameters: p, body: body.clone(), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs index 29edbaca594..8a420c32fb8 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs @@ -354,8 +354,8 @@ impl UnresolvedTypeExpression { } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -/// Represents whether the function can be called outside its module/crate -pub enum FunctionVisibility { +/// Represents whether the definition can be referenced outside its module/crate +pub enum ItemVisibility { Public, Private, PublicCrate, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs index f39b71405d3..387840b57c4 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs @@ -240,6 +240,17 @@ pub trait Recoverable { fn error(span: Span) -> Self; } +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct ModuleDeclaration { + pub ident: Ident, +} + +impl std::fmt::Display for ModuleDeclaration { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "mod {}", self.ident) + } +} + #[derive(Debug, PartialEq, Eq, Clone)] pub struct ImportStatement { pub path: Path, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs index a88567fcaf9..05916502d73 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs @@ -4,9 +4,11 @@ use crate::{ ast::{Path, PathKind}, parser::{Item, ItemKind}, }; +use noirc_errors::debug_info::{DebugFnId, DebugFunction}; use noirc_errors::{Span, Spanned}; use std::collections::HashMap; use std::collections::VecDeque; +use std::mem::take; const MAX_MEMBER_ASSIGN_DEPTH: usize = 8; @@ -26,8 +28,12 @@ pub struct DebugInstrumenter { // all field names referenced when assigning to a member of a variable pub field_names: HashMap, + // all collected function metadata (name + argument names) + pub functions: HashMap, + next_var_id: u32, next_field_name_id: u32, + next_fn_id: u32, // last seen variable names and their IDs grouped by scope scope: Vec>, @@ -38,9 +44,11 @@ impl Default for DebugInstrumenter { Self { variables: HashMap::default(), field_names: HashMap::default(), + functions: HashMap::default(), scope: vec![], next_var_id: 0, next_field_name_id: 1, + next_fn_id: 0, } } } @@ -76,10 +84,22 @@ impl DebugInstrumenter { field_name_id } + fn insert_function(&mut self, fn_name: String, arguments: Vec) -> DebugFnId { + let fn_id = DebugFnId(self.next_fn_id); + self.next_fn_id += 1; + self.functions.insert(fn_id, DebugFunction { name: fn_name, arg_names: arguments }); + fn_id + } + fn walk_fn(&mut self, func: &mut ast::FunctionDefinition) { + let func_name = func.name.0.contents.clone(); + let func_args = + func.parameters.iter().map(|param| pattern_to_string(¶m.pattern)).collect(); + let fn_id = self.insert_function(func_name, func_args); + let enter_stmt = build_debug_call_stmt("enter", fn_id, func.span); self.scope.push(HashMap::default()); - let set_fn_params = func + let set_fn_params: Vec<_> = func .parameters .iter() .flat_map(|param| { @@ -93,10 +113,21 @@ impl DebugInstrumenter { }) .collect(); - self.walk_scope(&mut func.body.0, func.span); + let func_body = &mut func.body.0; + let mut statements = take(func_body); + + self.walk_scope(&mut statements, func.span); - // prepend fn params: - func.body.0 = [set_fn_params, func.body.0.clone()].concat(); + // walk_scope ensures that the last statement is the return value of the function + let last_stmt = statements.pop().expect("at least one statement after walk_scope"); + let exit_stmt = build_debug_call_stmt("exit", fn_id, last_stmt.span); + + // rebuild function body + func_body.push(enter_stmt); + func_body.extend(set_fn_params); + func_body.extend(statements); + func_body.push(exit_stmt); + func_body.push(last_stmt); } // Modify a vector of statements in-place, adding instrumentation for sets and drops. @@ -427,6 +458,8 @@ impl DebugInstrumenter { use dep::__debug::{{ __debug_var_assign, __debug_var_drop, + __debug_fn_enter, + __debug_fn_exit, __debug_dereference_assign, {member_assigns}, }};"# @@ -451,14 +484,32 @@ pub fn build_debug_crate_file() -> String { } #[oracle(__debug_var_drop)] - unconstrained fn __debug_var_drop_oracle(_var_id: u32) {} - unconstrained fn __debug_var_drop_inner(var_id: u32) { + unconstrained fn __debug_var_drop_oracle(_var_id: u32) {} + unconstrained fn __debug_var_drop_inner(var_id: u32) { __debug_var_drop_oracle(var_id); } - pub fn __debug_var_drop(var_id: u32) { + pub fn __debug_var_drop(var_id: u32) { __debug_var_drop_inner(var_id); } + #[oracle(__debug_fn_enter)] + unconstrained fn __debug_fn_enter_oracle(_fn_id: u32) {} + unconstrained fn __debug_fn_enter_inner(fn_id: u32) { + __debug_fn_enter_oracle(fn_id); + } + pub fn __debug_fn_enter(fn_id: u32) { + __debug_fn_enter_inner(fn_id); + } + + #[oracle(__debug_fn_exit)] + unconstrained fn __debug_fn_exit_oracle(_fn_id: u32) {} + unconstrained fn __debug_fn_exit_inner(fn_id: u32) { + __debug_fn_exit_oracle(fn_id); + } + pub fn __debug_fn_exit(fn_id: u32) { + __debug_fn_exit_inner(fn_id); + } + #[oracle(__debug_dereference_assign)] unconstrained fn __debug_dereference_assign_oracle(_var_id: u32, _value: T) {} unconstrained fn __debug_dereference_assign_inner(var_id: u32, value: T) { @@ -561,6 +612,21 @@ fn build_assign_member_stmt( ast::Statement { kind: ast::StatementKind::Semi(ast::Expression { kind, span }), span } } +fn build_debug_call_stmt(fname: &str, fn_id: DebugFnId, span: Span) -> ast::Statement { + let kind = ast::ExpressionKind::Call(Box::new(ast::CallExpression { + func: Box::new(ast::Expression { + kind: ast::ExpressionKind::Variable(ast::Path { + segments: vec![ident(&format!["__debug_fn_{fname}"], span)], + kind: PathKind::Plain, + span, + }), + span, + }), + arguments: vec![uint_expr(fn_id.0 as u128, span)], + })); + ast::Statement { kind: ast::StatementKind::Semi(ast::Expression { kind, span }), span } +} + fn pattern_vars(pattern: &ast::Pattern) -> Vec<(ast::Ident, bool)> { let mut vars = vec![]; let mut stack = VecDeque::from([(pattern, false)]); @@ -585,6 +651,30 @@ fn pattern_vars(pattern: &ast::Pattern) -> Vec<(ast::Ident, bool)> { vars } +fn pattern_to_string(pattern: &ast::Pattern) -> String { + match pattern { + ast::Pattern::Identifier(id) => id.0.contents.clone(), + ast::Pattern::Mutable(mpat, _, _) => format!("mut {}", pattern_to_string(mpat.as_ref())), + ast::Pattern::Tuple(elements, _) => format!( + "({})", + elements.iter().map(pattern_to_string).collect::>().join(", ") + ), + ast::Pattern::Struct(name, fields, _) => { + format!( + "{} {{ {} }}", + name, + fields + .iter() + .map(|(field_ident, field_pattern)| { + format!("{}: {}", &field_ident.0.contents, pattern_to_string(field_pattern)) + }) + .collect::>() + .join(", "), + ) + } + } +} + fn ident(s: &str, span: Span) -> ast::Ident { ast::Ident(Spanned::from(span, s.to_string())) } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 7f36af5b30e..8ea9d475539 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -5,13 +5,14 @@ use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleId}; use crate::hir::resolution::errors::ResolverError; use crate::hir::resolution::import::{resolve_import, ImportDirective}; -use crate::hir::resolution::resolver::Resolver; use crate::hir::resolution::{ collect_impls, collect_trait_impls, path_resolver, resolve_free_functions, resolve_globals, resolve_impls, resolve_structs, resolve_trait_by_path, resolve_trait_impls, resolve_traits, resolve_type_aliases, }; -use crate::hir::type_check::{type_check_func, TypeCheckError, TypeChecker}; +use crate::hir::type_check::{ + check_trait_impl_method_matches_declaration, type_check_func, TypeCheckError, TypeChecker, +}; use crate::hir::Context; use crate::macros_api::{MacroError, MacroProcessor}; @@ -20,8 +21,7 @@ use crate::node_interner::{FuncId, GlobalId, NodeInterner, StructId, TraitId, Ty use crate::parser::{ParserError, SortedModule}; use crate::{ ExpressionKind, Ident, LetStatement, Literal, NoirFunction, NoirStruct, NoirTrait, - NoirTypeAlias, Path, PathKind, Type, TypeBindings, UnresolvedGenerics, - UnresolvedTraitConstraint, UnresolvedType, + NoirTypeAlias, Path, PathKind, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, }; use fm::FileId; use iter_extended::vecmap; @@ -207,7 +207,7 @@ impl DefCollector { context: &mut Context, ast: SortedModule, root_file_id: FileId, - macro_processors: Vec<&dyn MacroProcessor>, + macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; let crate_id = def_map.krate; @@ -220,11 +220,7 @@ impl DefCollector { let crate_graph = &context.crate_graph[crate_id]; for dep in crate_graph.dependencies.clone() { - errors.extend(CrateDefMap::collect_defs( - dep.crate_id, - context, - macro_processors.clone(), - )); + errors.extend(CrateDefMap::collect_defs(dep.crate_id, context, macro_processors)); let dep_def_root = context.def_map(&dep.crate_id).expect("ice: def map was just created").root; @@ -250,6 +246,7 @@ impl DefCollector { crate_root, crate_id, context, + macro_processors, )); let submodules = vecmap(def_collector.def_map.modules().iter(), |(index, _)| index); @@ -257,9 +254,9 @@ impl DefCollector { context.def_maps.insert(crate_id, def_collector.def_map); // TODO(#4653): generalize this function - for macro_processor in ¯o_processors { + for macro_processor in macro_processors { macro_processor - .process_unresolved_traits_impls( + .process_collected_defs( &crate_id, context, &def_collector.collected_traits_impls, @@ -282,7 +279,7 @@ impl DefCollector { // Resolve unresolved imports collected from the crate, one by one. for collected_import in def_collector.collected_imports { - match resolve_import(crate_id, collected_import, &context.def_maps) { + match resolve_import(crate_id, &collected_import, &context.def_maps) { Ok(resolved_import) => { // Populate module namespaces according to the imports used let current_def_map = context.def_maps.get_mut(&crate_id).unwrap(); @@ -372,12 +369,12 @@ impl DefCollector { &mut errors, )); - functions.extend(resolve_trait_impls( + let impl_functions = resolve_trait_impls( context, def_collector.collected_traits_impls, crate_id, &mut errors, - )); + ); for macro_processor in macro_processors { macro_processor.process_typed_ast(&crate_id, context).unwrap_or_else( @@ -391,6 +388,8 @@ impl DefCollector { errors.extend(type_check_globals(&mut context.def_interner, resolved_globals.globals)); errors.extend(type_check_functions(&mut context.def_interner, functions)); + errors.extend(type_check_trait_impl_signatures(&mut context.def_interner, &impl_functions)); + errors.extend(type_check_functions(&mut context.def_interner, impl_functions)); errors } } @@ -472,158 +471,24 @@ fn type_check_functions( .into_iter() .flat_map(|(file, func)| { type_check_func(interner, func) - .iter() - .cloned() + .into_iter() .map(|e| (e.into(), file)) .collect::>() }) .collect() } -// TODO(vitkov): Move this out of here and into type_check -#[allow(clippy::too_many_arguments)] -pub(crate) fn check_methods_signatures( - resolver: &mut Resolver, - impl_methods: &[(FileId, FuncId)], - trait_id: TraitId, - trait_name_span: Span, - // These are the generics on the trait itself from the impl. - // E.g. in `impl Foo for Bar`, this is `vec![A, B]`. - trait_generics: Vec, - trait_impl_generic_count: usize, - file_id: FileId, - errors: &mut Vec<(CompilationError, FileId)>, -) { - let self_type = resolver.get_self_type().expect("trait impl must have a Self type").clone(); - let trait_generics = vecmap(trait_generics, |typ| resolver.resolve_type(typ)); - - // Temporarily bind the trait's Self type to self_type so we can type check - let the_trait = resolver.interner.get_trait_mut(trait_id); - the_trait.self_type_typevar.bind(self_type); - - if trait_generics.len() != the_trait.generics.len() { - let error = DefCollectorErrorKind::MismatchGenericCount { - actual_generic_count: trait_generics.len(), - expected_generic_count: the_trait.generics.len(), - // Preferring to use 'here' over a more precise term like 'this reference' - // to try to make the error easier to understand for newer users. - location: "here it", - origin: the_trait.name.to_string(), - span: trait_name_span, - }; - errors.push((error.into(), file_id)); - } - - // We also need to bind the traits generics to the trait's generics on the impl - for (generic, binding) in the_trait.generics.iter().zip(trait_generics) { - generic.bind(binding); - } - - // Temporarily take the trait's methods so we can use both them and a mutable reference - // to the interner within the loop. - let trait_methods = std::mem::take(&mut the_trait.methods); - - for (file_id, func_id) in impl_methods { - let func_name = resolver.interner.function_name(func_id).to_owned(); - - // This is None in the case where the impl block has a method that's not part of the trait. - // If that's the case, a `MethodNotInTrait` error has already been thrown, and we can ignore - // the impl method, since there's nothing in the trait to match its signature against. - if let Some(trait_method) = - trait_methods.iter().find(|method| method.name.0.contents == func_name) - { - let impl_method = resolver.interner.function_meta(func_id); - - let impl_method_generic_count = - impl_method.typ.generic_count() - trait_impl_generic_count; - - // We subtract 1 here to account for the implicit generic `Self` type that is on all - // traits (and thus trait methods) but is not required (or allowed) for users to specify. - let the_trait = resolver.interner.get_trait(trait_id); - let trait_method_generic_count = - trait_method.generics().len() - 1 - the_trait.generics.len(); - - if impl_method_generic_count != trait_method_generic_count { - let trait_name = resolver.interner.get_trait(trait_id).name.clone(); - - let error = DefCollectorErrorKind::MismatchGenericCount { - actual_generic_count: impl_method_generic_count, - expected_generic_count: trait_method_generic_count, - origin: format!("{}::{}", trait_name, func_name), - location: "this method", - span: impl_method.location.span, - }; - errors.push((error.into(), *file_id)); - } - - // This instantiation is technically not needed. We could bind each generic in the - // trait function to the impl's corresponding generic but to do so we'd have to rely - // on the trait function's generics being first in the generic list, since the same - // list also contains the generic `Self` variable, and any generics on the trait itself. - // - // Instantiating the impl method's generics here instead is a bit less precise but - // doesn't rely on any orderings that may be changed. - let impl_function_type = impl_method.typ.instantiate(resolver.interner).0; - - let mut bindings = TypeBindings::new(); - let mut typecheck_errors = Vec::new(); - - if let Type::Function(impl_params, impl_return, _) = impl_function_type.as_monotype() { - if trait_method.arguments().len() != impl_params.len() { - let error = DefCollectorErrorKind::MismatchTraitImplementationNumParameters { - actual_num_parameters: impl_method.parameters.0.len(), - expected_num_parameters: trait_method.arguments().len(), - trait_name: resolver.interner.get_trait(trait_id).name.to_string(), - method_name: func_name.to_string(), - span: impl_method.location.span, - }; - errors.push((error.into(), *file_id)); - } - - // Check the parameters of the impl method against the parameters of the trait method - let args = trait_method.arguments().iter(); - let args_and_params = args.zip(impl_params).zip(&impl_method.parameters.0); - - for (parameter_index, ((expected, actual), (hir_pattern, _, _))) in - args_and_params.enumerate() - { - if expected.try_unify(actual, &mut bindings).is_err() { - typecheck_errors.push(TypeCheckError::TraitMethodParameterTypeMismatch { - method_name: func_name.to_string(), - expected_typ: expected.to_string(), - actual_typ: actual.to_string(), - parameter_span: hir_pattern.span(), - parameter_index: parameter_index + 1, - }); - } - } - - if trait_method.return_type().try_unify(impl_return, &mut bindings).is_err() { - let impl_method = resolver.interner.function_meta(func_id); - let ret_type_span = impl_method.return_type.get_type().span; - let expr_span = ret_type_span.expect("return type must always have a span"); - - let expected_typ = trait_method.return_type().to_string(); - let expr_typ = impl_method.return_type().to_string(); - let error = TypeCheckError::TypeMismatch { expr_typ, expected_typ, expr_span }; - typecheck_errors.push(error); - } - } else { - unreachable!( - "impl_function_type is not a function type, it is: {impl_function_type}" - ); - } - - errors.extend(typecheck_errors.iter().cloned().map(|e| (e.into(), *file_id))); - } - } - - // Now unbind `Self` and the trait's generics - let the_trait = resolver.interner.get_trait_mut(trait_id); - the_trait.set_methods(trait_methods); - the_trait.self_type_typevar.unbind(the_trait.self_type_typevar_id); - - for generic in &the_trait.generics { - generic.unbind(generic.id()); - } +fn type_check_trait_impl_signatures( + interner: &mut NodeInterner, + file_func_ids: &[(FileId, FuncId)], +) -> Vec<(CompilationError, fm::FileId)> { + file_func_ids + .iter() + .flat_map(|(file, func)| { + check_trait_impl_method_matches_declaration(interner, *func) + .into_iter() + .map(|e| (e.into(), *file)) + .collect::>() + }) + .collect() } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 77224cc311c..ae99e61e534 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -7,10 +7,11 @@ use noirc_errors::Location; use crate::{ graph::CrateId, hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait}, + macros_api::MacroProcessor, node_interner::{FunctionModifiers, TraitId, TypeAliasId}, parser::{SortedModule, SortedSubModule}, - FunctionDefinition, Ident, LetStatement, NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, - NoirTypeAlias, TraitImplItem, TraitItem, TypeImpl, + FunctionDefinition, Ident, LetStatement, ModuleDeclaration, NoirFunction, NoirStruct, + NoirTrait, NoirTraitImpl, NoirTypeAlias, TraitImplItem, TraitItem, TypeImpl, }; use super::{ @@ -41,16 +42,28 @@ pub fn collect_defs( module_id: LocalModuleId, crate_id: CrateId, context: &mut Context, + macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { let mut collector = ModCollector { def_collector, file_id, module_id }; let mut errors: Vec<(CompilationError, FileId)> = vec![]; // First resolve the module declarations for decl in ast.module_decls { - errors.extend(collector.parse_module_declaration(context, &decl, crate_id)); + errors.extend(collector.parse_module_declaration( + context, + &decl, + crate_id, + macro_processors, + )); } - errors.extend(collector.collect_submodules(context, crate_id, ast.submodules, file_id)); + errors.extend(collector.collect_submodules( + context, + crate_id, + ast.submodules, + file_id, + macro_processors, + )); // Then add the imports to defCollector to resolve once all modules in the hierarchy have been resolved for import in ast.imports { @@ -394,12 +407,10 @@ impl<'a> ModCollector<'a> { let modifiers = FunctionModifiers { name: name.to_string(), - visibility: crate::FunctionVisibility::Public, + visibility: crate::ItemVisibility::Public, // TODO(Maddiaa): Investigate trait implementations with attributes see: https://github.com/noir-lang/noir/issues/2629 attributes: crate::token::Attributes::empty(), is_unconstrained: false, - contract_function_type: None, - is_internal: None, }; let location = Location::new(name.span(), self.file_id); @@ -494,6 +505,7 @@ impl<'a> ModCollector<'a> { crate_id: CrateId, submodules: Vec, file_id: FileId, + macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; for submodule in submodules { @@ -506,6 +518,7 @@ impl<'a> ModCollector<'a> { child, crate_id, context, + macro_processors, )); } Err(error) => { @@ -522,15 +535,16 @@ impl<'a> ModCollector<'a> { fn parse_module_declaration( &mut self, context: &mut Context, - mod_name: &Ident, + mod_decl: &ModuleDeclaration, crate_id: CrateId, + macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; let child_file_id = - match find_module(&context.file_manager, self.file_id, &mod_name.0.contents) { + match find_module(&context.file_manager, self.file_id, &mod_decl.ident.0.contents) { Ok(child_file_id) => child_file_id, Err(expected_path) => { - let mod_name = mod_name.clone(); + let mod_name = mod_decl.ident.clone(); let err = DefCollectorErrorKind::UnresolvedModuleDecl { mod_name, expected_path }; errors.push((err.into(), self.file_id)); @@ -538,17 +552,17 @@ impl<'a> ModCollector<'a> { } }; - let location = Location { file: self.file_id, span: mod_name.span() }; + let location = Location { file: self.file_id, span: mod_decl.ident.span() }; if let Some(old_location) = context.visited_files.get(&child_file_id) { let error = DefCollectorErrorKind::ModuleAlreadyPartOfCrate { - mod_name: mod_name.clone(), + mod_name: mod_decl.ident.clone(), span: location.span, }; errors.push((error.into(), location.file)); let error = DefCollectorErrorKind::ModuleOriginallyDefined { - mod_name: mod_name.clone(), + mod_name: mod_decl.ident.clone(), span: old_location.span, }; errors.push((error.into(), old_location.file)); @@ -559,14 +573,26 @@ impl<'a> ModCollector<'a> { // Parse the AST for the module we just found and then recursively look for it's defs let (ast, parsing_errors) = context.parsed_file_results(child_file_id); - let ast = ast.into_sorted(); + let mut ast = ast.into_sorted(); + + for macro_processor in macro_processors { + match macro_processor.process_untyped_ast(ast.clone(), &crate_id, context) { + Ok(processed_ast) => { + ast = processed_ast; + } + Err((error, file_id)) => { + let def_error = DefCollectorErrorKind::MacroError(error); + errors.push((def_error.into(), file_id)); + } + } + } errors.extend( parsing_errors.iter().map(|e| (e.clone().into(), child_file_id)).collect::>(), ); // Add module into def collector and get a ModuleId - match self.push_child_module(mod_name, child_file_id, true, false) { + match self.push_child_module(&mod_decl.ident, child_file_id, true, false) { Ok(child_mod_id) => { errors.extend(collect_defs( self.def_collector, @@ -575,6 +601,7 @@ impl<'a> ModCollector<'a> { child_mod_id, crate_id, context, + macro_processors, )); } Err(error) => { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/errors.rs index de45be48c4e..29daf5d6369 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/errors.rs @@ -41,14 +41,6 @@ pub enum DefCollectorErrorKind { OverlappingImplNote { span: Span }, #[error("Cannot `impl` a type defined outside the current crate")] ForeignImpl { span: Span, type_name: String }, - #[error("Mismatched number of parameters in trait implementation")] - MismatchTraitImplementationNumParameters { - actual_num_parameters: usize, - expected_num_parameters: usize, - trait_name: String, - method_name: String, - span: Span, - }, #[error("Mismatched number of generics in {location}")] MismatchGenericCount { actual_generic_count: usize, @@ -176,18 +168,6 @@ impl From for Diagnostic { "".to_string(), trait_path.span(), ), - DefCollectorErrorKind::MismatchTraitImplementationNumParameters { - expected_num_parameters, - actual_num_parameters, - trait_name, - method_name, - span, - } => { - let plural = if expected_num_parameters == 1 { "" } else { "s" }; - let primary_message = format!( - "`{trait_name}::{method_name}` expects {expected_num_parameters} parameter{plural}, but this method has {actual_num_parameters}"); - Diagnostic::simple_error(primary_message, "".to_string(), span) - } DefCollectorErrorKind::MismatchGenericCount { actual_generic_count, expected_generic_count, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/item_scope.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/item_scope.rs index 523def89518..178b91e1e84 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/item_scope.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/item_scope.rs @@ -1,16 +1,11 @@ use super::{namespace::PerNs, ModuleDefId, ModuleId}; use crate::{ node_interner::{FuncId, TraitId}, - Ident, + Ident, ItemVisibility, }; use std::collections::{hash_map::Entry, HashMap}; -type Scope = HashMap, (ModuleDefId, Visibility, bool /*is_prelude*/)>; - -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -pub enum Visibility { - Public, -} +type Scope = HashMap, (ModuleDefId, ItemVisibility, bool /*is_prelude*/)>; #[derive(Default, Debug, PartialEq, Eq)] pub struct ItemScope { @@ -55,12 +50,12 @@ impl ItemScope { Err((old_ident.clone(), name)) } } else { - trait_hashmap.insert(trait_id, (mod_def, Visibility::Public, is_prelude)); + trait_hashmap.insert(trait_id, (mod_def, ItemVisibility::Public, is_prelude)); Ok(()) } } else { let mut trait_hashmap = HashMap::new(); - trait_hashmap.insert(trait_id, (mod_def, Visibility::Public, is_prelude)); + trait_hashmap.insert(trait_id, (mod_def, ItemVisibility::Public, is_prelude)); map.insert(name, trait_hashmap); Ok(()) } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs index 8721bdb6c3c..1326ffca9f7 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs @@ -73,7 +73,7 @@ impl CrateDefMap { pub fn collect_defs( crate_id: CrateId, context: &mut Context, - macro_processors: Vec<&dyn MacroProcessor>, + macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { // Check if this Crate has already been compiled // XXX: There is probably a better alternative for this. @@ -90,7 +90,7 @@ impl CrateDefMap { let (ast, parsing_errors) = context.parsed_file_results(root_file_id); let mut ast = ast.into_sorted(); - for macro_processor in ¯o_processors { + for macro_processor in macro_processors { match macro_processor.process_untyped_ast(ast.clone(), &crate_id, context) { Ok(processed_ast) => { ast = processed_ast; @@ -115,13 +115,7 @@ impl CrateDefMap { }; // Now we want to populate the CrateDefMap using the DefCollector - errors.extend(DefCollector::collect( - def_map, - context, - ast, - root_file_id, - macro_processors.clone(), - )); + errors.extend(DefCollector::collect(def_map, context, ast, root_file_id, macro_processors)); errors.extend( parsing_errors.iter().map(|e| (e.clone().into(), root_file_id)).collect::>(), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/namespace.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/namespace.rs index ca14d9f8617..5e349f46e14 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/namespace.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/namespace.rs @@ -1,15 +1,16 @@ -use super::{item_scope::Visibility, ModuleDefId}; +use super::ModuleDefId; +use crate::ItemVisibility; // This works exactly the same as in r-a, just simplified #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub struct PerNs { - pub types: Option<(ModuleDefId, Visibility, bool)>, - pub values: Option<(ModuleDefId, Visibility, bool)>, + pub types: Option<(ModuleDefId, ItemVisibility, bool)>, + pub values: Option<(ModuleDefId, ItemVisibility, bool)>, } impl PerNs { pub fn types(t: ModuleDefId) -> PerNs { - PerNs { types: Some((t, Visibility::Public, false)), values: None } + PerNs { types: Some((t, ItemVisibility::Public, false)), values: None } } pub fn take_types(self) -> Option { @@ -24,7 +25,7 @@ impl PerNs { self.types.map(|it| it.0).into_iter().chain(self.values.map(|it| it.0)) } - pub fn iter_items(self) -> impl Iterator { + pub fn iter_items(self) -> impl Iterator { self.types.into_iter().chain(self.values) } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs index d2fe67da38c..30a1ba2ee34 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -64,14 +64,10 @@ pub enum ResolverError { IncorrectGenericCount { span: Span, item_name: String, actual: usize, expected: usize }, #[error("{0}")] ParserError(Box), - #[error("Function is not defined in a contract yet sets its contract visibility")] - ContractFunctionTypeInNormalFunction { span: Span }, #[error("Cannot create a mutable reference to {variable}, it was declared to be immutable")] MutableReferenceToImmutableVariable { variable: String, span: Span }, #[error("Mutable references to array indices are unsupported")] MutableReferenceToArrayElement { span: Span }, - #[error("Function is not defined in a contract yet sets is_internal")] - ContractFunctionInternalInNormalFunction { span: Span }, #[error("Numeric constants should be printed without formatting braces")] NumericConstantInFormatString { name: String, span: Span }, #[error("Closure environment must be a tuple or unit type")] @@ -80,8 +76,6 @@ pub enum ResolverError { PrivateFunctionCalled { name: String, span: Span }, #[error("{name} is not visible from the current crate")] NonCrateFunctionCalled { name: String, span: Span }, - #[error("Only sized types may be used in the entry point to a program")] - InvalidTypeForEntryPoint { span: Span }, #[error("Nested slices are not supported")] NestedSlices { span: Span }, #[error("#[recursive] attribute is only allowed on entry points to a program")] @@ -278,22 +272,12 @@ impl From for Diagnostic { ) } ResolverError::ParserError(error) => (*error).into(), - ResolverError::ContractFunctionTypeInNormalFunction { span } => Diagnostic::simple_error( - "Only functions defined within contracts can set their contract function type".into(), - "Non-contract functions cannot be 'open'".into(), - span, - ), ResolverError::MutableReferenceToImmutableVariable { variable, span } => { Diagnostic::simple_error(format!("Cannot mutably reference the immutable variable {variable}"), format!("{variable} is immutable"), span) }, ResolverError::MutableReferenceToArrayElement { span } => { Diagnostic::simple_error("Mutable references to array elements are currently unsupported".into(), "Try storing the element in a fresh variable first".into(), span) }, - ResolverError::ContractFunctionInternalInNormalFunction { span } => Diagnostic::simple_error( - "Only functions defined within contracts can set their functions to be internal".into(), - "Non-contract functions cannot be 'internal'".into(), - span, - ), ResolverError::NumericConstantInFormatString { name, span } => Diagnostic::simple_error( format!("cannot find `{name}` in this scope "), "Numeric constants should be printed without formatting braces".to_string(), @@ -309,9 +293,6 @@ impl From for Diagnostic { ResolverError::NonCrateFunctionCalled { span, name } => Diagnostic::simple_warning( format!("{name} is not visible from the current crate"), format!("{name} is only visible within its crate"), span), - ResolverError::InvalidTypeForEntryPoint { span } => Diagnostic::simple_error( - "Only sized types may be used in the entry point to a program".to_string(), - "Slices, references, or any type containing them may not be used in main or a contract function".to_string(), span), ResolverError::NestedSlices { span } => Diagnostic::simple_error( "Nested slices are not supported".into(), "Try to use a constant sized array instead".into(), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs index e6ac33053a0..9c8418daf80 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs @@ -52,7 +52,7 @@ impl From for CustomDiagnostic { pub fn resolve_import( crate_id: CrateId, - import_directive: ImportDirective, + import_directive: &ImportDirective, def_maps: &BTreeMap, ) -> Result { let def_map = &def_maps[&crate_id]; @@ -62,10 +62,10 @@ pub fn resolve_import( let module_scope = import_directive.module_id; let resolved_namespace = - resolve_path_to_ns(&import_directive, def_map, def_maps, allow_contracts) + resolve_path_to_ns(import_directive, def_map, def_maps, allow_contracts) .map_err(|error| (error, module_scope))?; - let name = resolve_path_name(&import_directive); + let name = resolve_path_name(import_directive); Ok(ResolvedImport { name, resolved_namespace, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 7f9e48353a7..00b1b443430 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -37,11 +37,11 @@ use crate::{ StatementKind, }; use crate::{ - ArrayLiteral, ContractFunctionType, Distinctness, ForRange, FunctionDefinition, - FunctionReturnType, FunctionVisibility, Generics, LValue, NoirStruct, NoirTypeAlias, Param, - Path, PathKind, Pattern, Shared, StructType, Type, TypeAlias, TypeVariable, TypeVariableKind, - UnaryOp, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, - UnresolvedTypeExpression, Visibility, ERROR_IDENT, + ArrayLiteral, Distinctness, ForRange, FunctionDefinition, FunctionReturnType, Generics, + ItemVisibility, LValue, NoirStruct, NoirTypeAlias, Param, Path, PathKind, Pattern, Shared, + StructType, Type, TypeAlias, TypeVariable, TypeVariableKind, UnaryOp, UnresolvedGenerics, + UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, + Visibility, ERROR_IDENT, }; use fm::FileId; use iter_extended::vecmap; @@ -217,6 +217,7 @@ impl<'a> Resolver<'a> { pub fn resolve_trait_function( &mut self, name: &Ident, + generics: &UnresolvedGenerics, parameters: &[(Ident, UnresolvedType)], return_type: &FunctionReturnType, where_clause: &[UnresolvedTraitConstraint], @@ -233,11 +234,9 @@ impl<'a> Resolver<'a> { let def = FunctionDefinition { name: name.clone(), attributes: Attributes::empty(), - is_open: false, - is_internal: false, is_unconstrained: false, - visibility: FunctionVisibility::Public, // Trait functions are always public - generics: Vec::new(), // self.generics should already be set + visibility: ItemVisibility::Public, // Trait functions are always public + generics: generics.clone(), parameters: vecmap(parameters, |(name, typ)| Param { visibility: Visibility::Private, pattern: Pattern::Identifier(name.clone()), @@ -911,10 +910,6 @@ impl<'a> Resolver<'a> { }); } - if self.is_entry_point_function(func) { - self.verify_type_valid_for_program_input(&typ); - } - let pattern = self.resolve_pattern(pattern, DefinitionKind::Local(None)); let typ = self.resolve_type_inner(typ, &mut generics); @@ -976,14 +971,18 @@ impl<'a> Resolver<'a> { self.interner.push_definition_type(name_ident.id, typ.clone()); - self.handle_function_type(&func_id); - self.handle_is_function_internal(&func_id); + let direct_generics = func.def.generics.iter(); + let direct_generics = direct_generics + .filter_map(|generic| self.find_generic(&generic.0.contents)) + .map(|(name, typevar, _span)| (name.clone(), typevar.clone())) + .collect(); FuncMeta { name: name_ident, kind: func.kind, location, typ, + direct_generics, trait_impl: self.current_trait_impl, parameters: parameters.into(), return_type: func.def.return_type.clone(), @@ -991,6 +990,7 @@ impl<'a> Resolver<'a> { return_distinctness: func.def.return_distinctness, has_body: !func.def.body.is_empty(), trait_constraints: self.resolve_trait_constraints(&func.def.where_clause), + is_entry_point: self.is_entry_point_function(func), } } @@ -1018,34 +1018,14 @@ impl<'a> Resolver<'a> { /// True if the `distinct` keyword is allowed on a function's return type fn distinct_allowed(&self, func: &NoirFunction) -> bool { if self.in_contract { - // "open" and "unconstrained" functions are compiled to brillig and thus duplication of + // "unconstrained" functions are compiled to brillig and thus duplication of // witness indices in their abis is not a concern. - !func.def.is_unconstrained && !func.def.is_open + !func.def.is_unconstrained } else { func.name() == MAIN_FUNCTION } } - fn handle_function_type(&mut self, function: &FuncId) { - let function_type = self.interner.function_modifiers(function).contract_function_type; - - if !self.in_contract && function_type == Some(ContractFunctionType::Open) { - let span = self.interner.function_ident(function).span(); - self.errors.push(ResolverError::ContractFunctionTypeInNormalFunction { span }); - self.interner.function_modifiers_mut(function).contract_function_type = None; - } - } - - fn handle_is_function_internal(&mut self, function: &FuncId) { - if !self.in_contract { - if self.interner.function_modifiers(function).is_internal == Some(true) { - let span = self.interner.function_ident(function).span(); - self.push_err(ResolverError::ContractFunctionInternalInNormalFunction { span }); - } - self.interner.function_modifiers_mut(function).is_internal = None; - } - } - fn declare_numeric_generics(&mut self, params: &[Type], return_type: &Type) { if self.generics.is_empty() { return; @@ -1256,13 +1236,17 @@ impl<'a> Resolver<'a> { let is_in_stdlib = self.path_resolver.module_id().krate.is_stdlib(); let assert_msg_call_path = if is_in_stdlib { ExpressionKind::Variable(Path { - segments: vec![Ident::from("resolve_assert_message")], + segments: vec![Ident::from("internal"), Ident::from("resolve_assert_message")], kind: PathKind::Crate, span, }) } else { ExpressionKind::Variable(Path { - segments: vec![Ident::from("std"), Ident::from("resolve_assert_message")], + segments: vec![ + Ident::from("std"), + Ident::from("internal"), + Ident::from("resolve_assert_message"), + ], kind: PathKind::Dep, span, }) @@ -1311,7 +1295,7 @@ impl<'a> Resolver<'a> { &mut self, func: FuncId, span: Span, - visibility: FunctionVisibility, + visibility: ItemVisibility, ) { let function_module = self.interner.function_module(func); let current_module = self.path_resolver.module_id(); @@ -1321,8 +1305,8 @@ impl<'a> Resolver<'a> { let current_module = current_module.local_id; let name = self.interner.function_name(&func).to_string(); match visibility { - FunctionVisibility::Public => (), - FunctionVisibility::Private => { + ItemVisibility::Public => (), + ItemVisibility::Private => { if !same_crate || !self.module_descendent_of_target( krate, @@ -1333,7 +1317,7 @@ impl<'a> Resolver<'a> { self.errors.push(ResolverError::PrivateFunctionCalled { span, name }); } } - FunctionVisibility::PublicCrate => { + ItemVisibility::PublicCrate => { if !same_crate { self.errors.push(ResolverError::NonCrateFunctionCalled { span, name }); } @@ -1442,9 +1426,7 @@ impl<'a> Resolver<'a> { self.interner.add_function_dependency(current_item, id); } - if self.interner.function_visibility(id) - != FunctionVisibility::Public - { + if self.interner.function_visibility(id) != ItemVisibility::Public { let span = hir_ident.location.span; self.check_can_reference_function( id, @@ -1999,89 +1981,6 @@ impl<'a> Resolver<'a> { } HirLiteral::FmtStr(str, fmt_str_idents) } - - /// Only sized types are valid to be used as main's parameters or the parameters to a contract - /// function. If the given type is not sized (e.g. contains a slice or NamedGeneric type), an - /// error is issued. - fn verify_type_valid_for_program_input(&mut self, typ: &UnresolvedType) { - match &typ.typ { - UnresolvedTypeData::FieldElement - | UnresolvedTypeData::Integer(_, _) - | UnresolvedTypeData::Bool - | UnresolvedTypeData::Unit - | UnresolvedTypeData::Error => (), - - UnresolvedTypeData::MutableReference(_) - | UnresolvedTypeData::Function(_, _, _) - | UnresolvedTypeData::FormatString(_, _) - | UnresolvedTypeData::TraitAsType(..) - | UnresolvedTypeData::Unspecified => { - let span = typ.span.expect("Function parameters should always have spans"); - self.push_err(ResolverError::InvalidTypeForEntryPoint { span }); - } - - UnresolvedTypeData::Array(length, element) => { - if let Some(length) = length { - self.verify_type_expression_valid_for_program_input(length); - } else { - let span = typ.span.expect("Function parameters should always have spans"); - self.push_err(ResolverError::InvalidTypeForEntryPoint { span }); - } - self.verify_type_valid_for_program_input(element); - } - UnresolvedTypeData::Expression(expression) => { - self.verify_type_expression_valid_for_program_input(expression); - } - UnresolvedTypeData::String(length) => { - if let Some(length) = length { - self.verify_type_expression_valid_for_program_input(length); - } else { - let span = typ.span.expect("Function parameters should always have spans"); - self.push_err(ResolverError::InvalidTypeForEntryPoint { span }); - } - } - UnresolvedTypeData::Named(path, generics, _) => { - // Since the type is named, we need to resolve it to see what it actually refers to - // in order to check whether it is valid. Since resolving it may lead to a - // resolution error, we have to truncate our error count to the previous count just - // in case. This is to ensure resolution errors are not issued twice when this type - // is later resolved properly. - let error_count = self.errors.len(); - let resolved = self.resolve_named_type(path.clone(), generics.clone(), &mut vec![]); - self.errors.truncate(error_count); - - if !resolved.is_valid_for_program_input() { - let span = typ.span.expect("Function parameters should always have spans"); - self.push_err(ResolverError::InvalidTypeForEntryPoint { span }); - } - } - UnresolvedTypeData::Tuple(elements) => { - for element in elements { - self.verify_type_valid_for_program_input(element); - } - } - UnresolvedTypeData::Parenthesized(typ) => self.verify_type_valid_for_program_input(typ), - } - } - - fn verify_type_expression_valid_for_program_input(&mut self, expr: &UnresolvedTypeExpression) { - match expr { - UnresolvedTypeExpression::Constant(_, _) => (), - UnresolvedTypeExpression::Variable(path) => { - let error_count = self.errors.len(); - let resolved = self.resolve_named_type(path.clone(), vec![], &mut vec![]); - self.errors.truncate(error_count); - - if !resolved.is_valid_for_program_input() { - self.push_err(ResolverError::InvalidTypeForEntryPoint { span: path.span() }); - } - } - UnresolvedTypeExpression::BinaryOperation(lhs, _, rhs, _) => { - self.verify_type_expression_valid_for_program_input(lhs); - self.verify_type_expression_valid_for_program_input(rhs); - } - } - } } /// Gives an error if a user tries to create a mutable reference diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs index 8f966be312b..5d546954f0d 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs @@ -8,9 +8,7 @@ use crate::{ graph::CrateId, hir::{ def_collector::{ - dc_crate::{ - check_methods_signatures, CompilationError, UnresolvedTrait, UnresolvedTraitImpl, - }, + dc_crate::{CompilationError, UnresolvedTrait, UnresolvedTraitImpl}, errors::{DefCollectorErrorKind, DuplicateType}, }, def_map::{CrateDefMap, ModuleDefId, ModuleId}, @@ -131,6 +129,7 @@ fn resolve_trait_methods( let func_id = unresolved_trait.method_ids[&name.0.contents]; let (_, func_meta) = resolver.resolve_trait_function( name, + generics, parameters, return_type, where_clause, @@ -365,6 +364,7 @@ pub(crate) fn resolve_trait_by_path( Err(_) => Err(DefCollectorErrorKind::TraitNotFound { trait_path: path }), } } + pub(crate) fn resolve_trait_impls( context: &mut Context, traits: Vec, @@ -424,17 +424,6 @@ pub(crate) fn resolve_trait_impls( new_resolver.set_self_type(Some(self_type.clone())); if let Some(trait_id) = maybe_trait_id { - check_methods_signatures( - &mut new_resolver, - &impl_methods, - trait_id, - trait_impl.trait_path.span(), - trait_impl.trait_generics, - trait_impl.generics.len(), - trait_impl.file_id, - errors, - ); - let where_clause = trait_impl .where_clause .into_iter() diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs index 96d30100d8b..7eacc8eb2d1 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -44,7 +44,7 @@ pub enum TypeCheckError { #[error("Expected type {expected} is not the same as {actual}")] TypeMismatchWithSource { expected: Type, actual: Type, span: Span, source: Source }, #[error("Expected {expected:?} found {found:?}")] - ArityMisMatch { expected: u16, found: u16, span: Span }, + ArityMisMatch { expected: usize, found: usize, span: Span }, #[error("Return type in a function cannot be public")] PublicReturnType { typ: Type, span: Span }, #[error("Cannot cast type {from}, 'as' is only for primitive field or integer types")] @@ -53,8 +53,10 @@ pub enum TypeCheckError { ExpectedFunction { found: Type, span: Span }, #[error("Type {lhs_type} has no member named {field_name}")] AccessUnknownMember { lhs_type: Type, field_name: String, span: Span }, - #[error("Function expects {expected} parameters but {found} given")] + #[error("Function expects {expected} parameters but {found} were given")] ParameterCountMismatch { expected: usize, found: usize, span: Span }, + #[error("{item} expects {expected} generics but {found} were given")] + GenericCountMismatch { item: String, expected: usize, found: usize, span: Span }, #[error("Only integer and Field types may be casted to")] UnsupportedCast { span: Span }, #[error("Index {index} is out of bounds for this tuple {lhs_type} of length {length}")] @@ -122,6 +124,16 @@ pub enum TypeCheckError { ConstrainedReferenceToUnconstrained { span: Span }, #[error("Slices cannot be returned from an unconstrained runtime to a constrained runtime")] UnconstrainedSliceReturnToConstrained { span: Span }, + #[error("Only sized types may be used in the entry point to a program")] + InvalidTypeForEntryPoint { span: Span }, + #[error("Mismatched number of parameters in trait implementation")] + MismatchTraitImplNumParameters { + actual_num_parameters: usize, + expected_num_parameters: usize, + trait_name: String, + method_name: String, + span: Span, + }, } impl TypeCheckError { @@ -191,6 +203,12 @@ impl From for Diagnostic { let msg = format!("Function expects {expected} parameter{empty_or_s} but {found} {was_or_were} given"); Diagnostic::simple_error(msg, String::new(), span) } + TypeCheckError::GenericCountMismatch { item, expected, found, span } => { + let empty_or_s = if expected == 1 { "" } else { "s" }; + let was_or_were = if found == 1 { "was" } else { "were" }; + let msg = format!("{item} expects {expected} generic{empty_or_s} but {found} {was_or_were} given"); + Diagnostic::simple_error(msg, String::new(), span) + } TypeCheckError::InvalidCast { span, .. } | TypeCheckError::ExpectedFunction { span, .. } | TypeCheckError::AccessUnknownMember { span, .. } @@ -284,6 +302,21 @@ impl From for Diagnostic { let msg = format!("Constraint for `{typ}: {trait_name}` is not needed, another matching impl is already in scope"); Diagnostic::simple_warning(msg, "Unnecessary trait constraint in where clause".into(), span) } + TypeCheckError::InvalidTypeForEntryPoint { span } => Diagnostic::simple_error( + "Only sized types may be used in the entry point to a program".to_string(), + "Slices, references, or any type containing them may not be used in main or a contract function".to_string(), span), + TypeCheckError::MismatchTraitImplNumParameters { + expected_num_parameters, + actual_num_parameters, + trait_name, + method_name, + span, + } => { + let plural = if expected_num_parameters == 1 { "" } else { "s" }; + let primary_message = format!( + "`{trait_name}::{method_name}` expects {expected_num_parameters} parameter{plural}, but this method has {actual_num_parameters}"); + Diagnostic::simple_error(primary_message, "".to_string(), span) + } } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs index 7b854e58fca..7219f4d09c6 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -863,7 +863,13 @@ impl<'interner> TypeChecker<'interner> { span: op.location.span, }); - self.comparator_operand_type_rules(x_type, y_type, op, span) + let (_, use_impl) = self.comparator_operand_type_rules(x_type, y_type, op, span)?; + + // If the size is not constant, we must fall back to a user-provided impl for + // equality on slices. + let size = x_size.follow_bindings(); + let use_impl = use_impl || size.evaluate_to_u64().is_none(); + Ok((Bool, use_impl)) } (String(x_size), String(y_size)) => { @@ -1034,9 +1040,9 @@ impl<'interner> TypeChecker<'interner> { } ret } + // ignoring env for subtype on purpose Type::Function(parameters, ret, _env) => { - // ignoring env for subtype on purpose - self.bind_function_type_impl(parameters.as_ref(), ret.as_ref(), args.as_ref(), span) + self.bind_function_type_impl(¶meters, &ret, &args, span) } Type::Error => Type::Error, found => { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs index 21d1c75a0f2..ab759f454e5 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -12,11 +12,17 @@ mod expr; mod stmt; pub use errors::TypeCheckError; +use noirc_errors::Span; use crate::{ - hir_def::{expr::HirExpression, stmt::HirStatement, traits::TraitConstraint}, + hir_def::{ + expr::HirExpression, + function::{Param, Parameters}, + stmt::HirStatement, + traits::TraitConstraint, + }, node_interner::{ExprId, FuncId, GlobalId, NodeInterner}, - Type, + Type, TypeBindings, }; use self::errors::Source; @@ -74,6 +80,7 @@ pub fn type_check_func(interner: &mut NodeInterner, func_id: FuncId) -> Vec Vec, + func_id: FuncId, + param: &Param, + errors: &mut Vec, +) { + let meta = type_checker.interner.function_meta(&func_id); + if meta.is_entry_point && !param.1.is_valid_for_program_input() { + let span = param.0.span(); + errors.push(TypeCheckError::InvalidTypeForEntryPoint { span }); + } +} + fn function_info(interner: &NodeInterner, function_body_id: &ExprId) -> (noirc_errors::Span, bool) { let (expr_span, empty_function) = if let HirExpression::Block(block) = interner.expression(function_body_id) { @@ -162,6 +185,154 @@ fn function_info(interner: &NodeInterner, function_body_id: &ExprId) -> (noirc_e (expr_span, empty_function) } +/// Checks that the type of a function in a trait impl matches the type +/// of the corresponding function declaration in the trait itself. +/// +/// To do this, given a trait such as: +/// `trait Foo { fn foo(...); }` +/// +/// And an impl such as: +/// `impl Foo for Bar { fn foo(...); } ` +/// +/// We have to substitute: +/// - Self for Bar +/// - A for D +/// - B for F +/// +/// Before we can type check. Finally, we must also check that the unification +/// result does not introduce any new bindings. This can happen if the impl +/// function's type is more general than that of the trait function. E.g. +/// `fn baz(a: A, b: B)` when the impl required `fn baz(a: A, b: A)`. +/// +/// This does not type check the body of the impl function. +pub(crate) fn check_trait_impl_method_matches_declaration( + interner: &mut NodeInterner, + function: FuncId, +) -> Vec { + let meta = interner.function_meta(&function); + let method_name = interner.function_name(&function); + let mut errors = Vec::new(); + + let definition_type = meta.typ.as_monotype(); + + let impl_ = + meta.trait_impl.expect("Trait impl function should have a corresponding trait impl"); + let impl_ = interner.get_trait_implementation(impl_); + let impl_ = impl_.borrow(); + let trait_info = interner.get_trait(impl_.trait_id); + + let mut bindings = TypeBindings::new(); + bindings.insert( + trait_info.self_type_typevar_id, + (trait_info.self_type_typevar.clone(), impl_.typ.clone()), + ); + + if trait_info.generics.len() != impl_.trait_generics.len() { + let expected = trait_info.generics.len(); + let found = impl_.trait_generics.len(); + let span = impl_.ident.span(); + let item = trait_info.name.to_string(); + errors.push(TypeCheckError::GenericCountMismatch { item, expected, found, span }); + } + + // Substitute each generic on the trait with the corresponding generic on the impl + for (generic, arg) in trait_info.generics.iter().zip(&impl_.trait_generics) { + bindings.insert(generic.id(), (generic.clone(), arg.clone())); + } + + // If this is None, the trait does not have the corresponding function. + // This error should have been caught in name resolution already so we don't + // issue an error for it here. + if let Some(trait_fn_id) = trait_info.method_ids.get(method_name) { + let trait_fn_meta = interner.function_meta(trait_fn_id); + + if trait_fn_meta.direct_generics.len() != meta.direct_generics.len() { + let expected = trait_fn_meta.direct_generics.len(); + let found = meta.direct_generics.len(); + let span = meta.name.location.span; + let item = method_name.to_string(); + errors.push(TypeCheckError::GenericCountMismatch { item, expected, found, span }); + } + + // Substitute each generic on the trait function with the corresponding generic on the impl function + for ((_, trait_fn_generic), (name, impl_fn_generic)) in + trait_fn_meta.direct_generics.iter().zip(&meta.direct_generics) + { + let arg = Type::NamedGeneric(impl_fn_generic.clone(), name.clone()); + bindings.insert(trait_fn_generic.id(), (trait_fn_generic.clone(), arg)); + } + + let (declaration_type, _) = trait_fn_meta.typ.instantiate_with_bindings(bindings, interner); + + check_function_type_matches_expected_type( + &declaration_type, + definition_type, + method_name, + &meta.parameters, + meta.name.location.span, + &trait_info.name.0.contents, + &mut errors, + ); + } + + errors +} + +fn check_function_type_matches_expected_type( + expected: &Type, + actual: &Type, + method_name: &str, + actual_parameters: &Parameters, + span: Span, + trait_name: &str, + errors: &mut Vec, +) { + let mut bindings = TypeBindings::new(); + // Shouldn't need to unify envs, they should always be equal since they're both free functions + if let (Type::Function(params_a, ret_a, _env_a), Type::Function(params_b, ret_b, _env_b)) = + (expected, actual) + { + if params_a.len() == params_b.len() { + for (i, (a, b)) in params_a.iter().zip(params_b.iter()).enumerate() { + if a.try_unify(b, &mut bindings).is_err() { + errors.push(TypeCheckError::TraitMethodParameterTypeMismatch { + method_name: method_name.to_string(), + expected_typ: a.to_string(), + actual_typ: b.to_string(), + parameter_span: actual_parameters.0[i].0.span(), + parameter_index: i + 1, + }); + } + } + + if ret_b.try_unify(ret_a, &mut bindings).is_err() { + errors.push(TypeCheckError::TypeMismatch { + expected_typ: ret_a.to_string(), + expr_typ: ret_b.to_string(), + expr_span: span, + }); + } + } else { + errors.push(TypeCheckError::MismatchTraitImplNumParameters { + actual_num_parameters: params_b.len(), + expected_num_parameters: params_a.len(), + trait_name: trait_name.to_string(), + method_name: method_name.to_string(), + span, + }); + } + } + + // If result bindings is not empty, a type variable was bound which means the two + // signatures were not a perfect match. Note that this relies on us already binding + // all the expected generics to each other prior to this check. + if !bindings.is_empty() { + let expected_typ = expected.to_string(); + let expr_typ = actual.to_string(); + errors.push(TypeCheckError::TypeMismatch { expected_typ, expr_typ, expr_span: span }); + } +} + impl<'interner> TypeChecker<'interner> { fn new(interner: &'interner mut NodeInterner) -> Self { Self { interner, errors: Vec::new(), trait_constraints: Vec::new(), current_function: None } @@ -329,6 +500,8 @@ mod test { trait_impl: None, return_type: FunctionReturnType::Default(Span::default()), trait_constraints: Vec::new(), + direct_generics: Vec::new(), + is_entry_point: true, }; interner.push_fn_meta(func_meta, func_id); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs index d3ab2a9393b..56543e8185c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs @@ -1,12 +1,14 @@ use iter_extended::vecmap; use noirc_errors::{Location, Span}; +use std::rc::Rc; + use super::expr::{HirBlockExpression, HirExpression, HirIdent}; use super::stmt::HirPattern; use super::traits::TraitConstraint; use crate::node_interner::{ExprId, NodeInterner, TraitImplId}; use crate::FunctionKind; -use crate::{Distinctness, FunctionReturnType, Type, Visibility}; +use crate::{Distinctness, FunctionReturnType, Type, TypeVariable, Visibility}; /// A Hir function is a block expression /// with a list of statements @@ -103,6 +105,12 @@ pub struct FuncMeta { /// or a Type::Forall for generic functions. pub typ: Type, + /// The set of generics that are declared directly on this function in the source code. + /// This does not include generics from an outer scope, like those introduced by + /// an `impl` block. This also does not include implicit generics added by the compiler + /// such as a trait's `Self` type variable. + pub direct_generics: Vec<(Rc, TypeVariable)>, + pub location: Location, // This flag is needed for the attribute check pass @@ -112,6 +120,10 @@ pub struct FuncMeta { /// The trait impl this function belongs to, if any pub trait_impl: Option, + + /// True if this function is an entry point to the program. + /// For non-contracts, this means the function is `main`. + pub is_entry_point: bool, } impl FuncMeta { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs index b70aa43701c..5ab036eef5b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs @@ -703,10 +703,10 @@ impl Type { | Type::TraitAsType(..) | Type::NotConstant => false, - // This function is called during name resolution before we've verified aliases - // are not cyclic. As a result, it wouldn't be safe to check this alias' definition - // to see if the aliased type is valid. - Type::Alias(..) => false, + Type::Alias(alias, generics) => { + let alias = alias.borrow(); + alias.get_type(generics).is_valid_for_program_input() + } Type::Array(length, element) => { length.is_valid_for_program_input() && element.is_valid_for_program_input() @@ -1768,9 +1768,11 @@ impl From<&Type> for PrintableType { Type::TypeVariable(_, _) => unreachable!(), Type::NamedGeneric(..) => unreachable!(), Type::Forall(..) => unreachable!(), - Type::Function(_, _, env) => { - PrintableType::Function { env: Box::new(env.as_ref().into()) } - } + Type::Function(arguments, return_type, env) => PrintableType::Function { + arguments: arguments.iter().map(|arg| arg.into()).collect(), + return_type: Box::new(return_type.as_ref().into()), + env: Box::new(env.as_ref().into()), + }, Type::MutableReference(typ) => { PrintableType::MutableReference { typ: Box::new(typ.as_ref().into()) } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs index f096c220200..3dc9d05b15e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs @@ -664,7 +664,6 @@ pub enum Keyword { Let, Mod, Mut, - Open, Pub, Return, ReturnData, @@ -706,7 +705,6 @@ impl fmt::Display for Keyword { Keyword::Let => write!(f, "let"), Keyword::Mod => write!(f, "mod"), Keyword::Mut => write!(f, "mut"), - Keyword::Open => write!(f, "open"), Keyword::Pub => write!(f, "pub"), Keyword::Return => write!(f, "return"), Keyword::ReturnData => write!(f, "return_data"), @@ -751,7 +749,6 @@ impl Keyword { "let" => Keyword::Let, "mod" => Keyword::Mod, "mut" => Keyword::Mut, - "open" => Keyword::Open, "pub" => Keyword::Pub, "return" => Keyword::Return, "return_data" => Keyword::ReturnData, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lib.rs b/noir/noir-repo/compiler/noirc_frontend/src/lib.rs index be007929fc4..1871b594ae7 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lib.rs @@ -56,14 +56,13 @@ pub mod macros_api { pub use crate::hir::def_map::ModuleDefId; pub use crate::{ hir::Context as HirContext, BlockExpression, CallExpression, CastExpression, Distinctness, - Expression, ExpressionKind, FunctionReturnType, Ident, IndexExpression, LetStatement, - Literal, MemberAccessExpression, MethodCallExpression, NoirFunction, Path, PathKind, - Pattern, Statement, UnresolvedType, UnresolvedTypeData, Visibility, + Expression, ExpressionKind, FunctionReturnType, Ident, IndexExpression, ItemVisibility, + LetStatement, Literal, MemberAccessExpression, MethodCallExpression, NoirFunction, Path, + PathKind, Pattern, Statement, UnresolvedType, UnresolvedTypeData, Visibility, }; pub use crate::{ - ForLoopStatement, ForRange, FunctionDefinition, FunctionVisibility, ImportStatement, - NoirStruct, Param, PrefixExpression, Signedness, StatementKind, StructType, Type, TypeImpl, - UnaryOp, + ForLoopStatement, ForRange, FunctionDefinition, ImportStatement, NoirStruct, Param, + PrefixExpression, Signedness, StatementKind, StructType, Type, TypeImpl, UnaryOp, }; /// Methods to process the AST before and after type checking @@ -77,12 +76,12 @@ pub mod macros_api { ) -> Result; // TODO(#4653): generalize this function - fn process_unresolved_traits_impls( + fn process_collected_defs( &self, _crate_id: &CrateId, _context: &mut HirContext, - _unresolved_traits_impls: &[UnresolvedTraitImpl], - _collected_functions: &mut Vec, + _collected_trait_impls: &[UnresolvedTraitImpl], + _collected_functions: &mut [UnresolvedFunctions], ) -> Result<(), (MacroError, FileId)>; /// Function to manipulate the AST after type checking has been completed. diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs index e4e619d5d92..7fcf8e87792 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs @@ -1,7 +1,7 @@ use acvm::FieldElement; use iter_extended::vecmap; use noirc_errors::{ - debug_info::{DebugTypes, DebugVariables}, + debug_info::{DebugFunctions, DebugTypes, DebugVariables}, Location, }; @@ -253,6 +253,7 @@ pub struct Program { /// Indicates to a backend whether a SNARK-friendly prover should be used. pub recursive: bool, pub debug_variables: DebugVariables, + pub debug_functions: DebugFunctions, pub debug_types: DebugTypes, } @@ -266,6 +267,7 @@ impl Program { return_visibility: Visibility, recursive: bool, debug_variables: DebugVariables, + debug_functions: DebugFunctions, debug_types: DebugTypes, ) -> Program { Program { @@ -276,6 +278,7 @@ impl Program { return_visibility, recursive, debug_variables, + debug_functions, debug_types, } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/debug.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/debug.rs index a8ff4399f99..cf4e0ab792e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/debug.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/debug.rs @@ -76,7 +76,7 @@ impl<'interner> Monomorphizer<'interner> { let var_type = self.interner.id_type(call.arguments[DEBUG_VALUE_ARG_SLOT]); let source_var_id = source_var_id.to_u128().into(); // then update the ID used for tracking at runtime - let var_id = self.debug_type_tracker.insert_var(source_var_id, var_type); + let var_id = self.debug_type_tracker.insert_var(source_var_id, &var_type); let interned_var_id = self.intern_var_id(var_id, &call.location); arguments[DEBUG_VAR_ID_ARG_SLOT] = self.expr(interned_var_id)?; Ok(()) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/debug_types.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/debug_types.rs index fea073d394f..16b82d1e7b9 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/debug_types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/debug_types.rs @@ -3,7 +3,8 @@ use crate::{ hir_def::types::Type, }; use noirc_errors::debug_info::{ - DebugTypeId, DebugTypes, DebugVarId, DebugVariable, DebugVariables, + DebugFnId, DebugFunction, DebugFunctions, DebugTypeId, DebugTypes, DebugVarId, DebugVariable, + DebugVariables, }; use noirc_printable_type::PrintableType; use std::collections::HashMap; @@ -30,7 +31,10 @@ pub struct DebugTypeTracker { // All instances of tracked variables variables: HashMap, - // Types of tracked variables + // Function metadata collected during instrumentation injection + functions: HashMap, + + // Types of tracked variables and functions types: HashMap, types_reverse: HashMap, @@ -43,34 +47,29 @@ impl DebugTypeTracker { DebugTypeTracker { source_variables: instrumenter.variables.clone(), source_field_names: instrumenter.field_names.clone(), + functions: instrumenter.functions.clone(), ..DebugTypeTracker::default() } } - pub fn extract_vars_and_types(&self) -> (DebugVariables, DebugTypes) { + pub fn extract_vars_and_types(&self) -> (DebugVariables, DebugFunctions, DebugTypes) { let debug_variables = self .variables .clone() .into_iter() .map(|(var_id, (source_var_id, type_id))| { - ( - var_id, - DebugVariable { - name: self.source_variables.get(&source_var_id).cloned().unwrap_or_else( - || { - unreachable!( - "failed to retrieve variable name for {source_var_id:?}" - ); - }, - ), - debug_type_id: type_id, - }, - ) + let var_name = + self.source_variables.get(&source_var_id).cloned().unwrap_or_else(|| { + unreachable!("failed to retrieve variable name for {source_var_id:?}"); + }); + (var_id, DebugVariable { name: var_name, debug_type_id: type_id }) }) .collect(); + + let debug_functions = self.functions.clone().into_iter().collect(); let debug_types = self.types.clone().into_iter().collect(); - (debug_variables, debug_types) + (debug_variables, debug_functions, debug_types) } pub fn resolve_field_index( @@ -83,19 +82,24 @@ impl DebugTypeTracker { .and_then(|field_name| get_field(cursor_type, field_name)) } - pub fn insert_var(&mut self, source_var_id: SourceVarId, var_type: Type) -> DebugVarId { - if !self.source_variables.contains_key(&source_var_id) { - unreachable!("cannot find source debug variable {source_var_id:?}"); - } - - let ptype: PrintableType = var_type.follow_bindings().into(); - let type_id = self.types_reverse.get(&ptype).copied().unwrap_or_else(|| { + fn insert_type(&mut self, the_type: &Type) -> DebugTypeId { + let ptype: PrintableType = the_type.follow_bindings().into(); + self.types_reverse.get(&ptype).copied().unwrap_or_else(|| { let type_id = DebugTypeId(self.next_type_id); self.next_type_id += 1; self.types_reverse.insert(ptype.clone(), type_id); self.types.insert(type_id, ptype); type_id - }); + }) + } + + pub fn insert_var(&mut self, source_var_id: SourceVarId, var_type: &Type) -> DebugVarId { + if !self.source_variables.contains_key(&source_var_id) { + unreachable!("cannot find source debug variable {source_var_id:?}"); + } + + let type_id = self.insert_type(var_type); + // check if we need to instantiate the var with a new type let existing_var_id = self.source_to_debug_vars.get(&source_var_id).and_then(|var_id| { let (_, existing_type_id) = self.variables.get(var_id).unwrap(); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs index ce880401d77..4938d33aff9 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -28,8 +28,8 @@ use crate::{ }, node_interner::{self, DefinitionKind, NodeInterner, StmtId, TraitImplKind, TraitMethodId}, token::FunctionAttribute, - ContractFunctionType, FunctionKind, IntegerBitSize, Signedness, Type, TypeBinding, - TypeBindings, TypeVariable, TypeVariableKind, UnaryOp, Visibility, + FunctionKind, IntegerBitSize, Signedness, Type, TypeBinding, TypeBindings, TypeVariable, + TypeVariableKind, UnaryOp, Visibility, }; use self::ast::{Definition, FuncId, Function, LocalId, Program}; @@ -165,7 +165,8 @@ pub fn monomorphize_debug( let FuncMeta { return_distinctness, return_visibility, kind, .. } = monomorphizer.interner.function_meta(&main); - let (debug_variables, debug_types) = monomorphizer.debug_type_tracker.extract_vars_and_types(); + let (debug_variables, debug_functions, debug_types) = + monomorphizer.debug_type_tracker.extract_vars_and_types(); let program = Program::new( functions, function_sig, @@ -174,6 +175,7 @@ pub fn monomorphize_debug( *return_visibility, *kind == FunctionKind::Recursive, debug_variables, + debug_functions, debug_types, ); Ok(program) @@ -310,8 +312,7 @@ impl<'interner> Monomorphizer<'interner> { Type::TraitAsType(..) => &body_return_type, _ => meta.return_type(), }); - let unconstrained = modifiers.is_unconstrained - || matches!(modifiers.contract_function_type, Some(ContractFunctionType::Open)); + let unconstrained = modifiers.is_unconstrained; let parameters = self.parameters(&meta.parameters); let body = self.expr(body_expr_id)?; @@ -1689,23 +1690,15 @@ impl<'interner> Monomorphizer<'interner> { } fn unwrap_tuple_type(typ: &HirType) -> Vec { - match typ { + match typ.follow_bindings() { HirType::Tuple(fields) => fields.clone(), - HirType::TypeVariable(binding, TypeVariableKind::Normal) => match &*binding.borrow() { - TypeBinding::Bound(binding) => unwrap_tuple_type(binding), - TypeBinding::Unbound(_) => unreachable!(), - }, other => unreachable!("unwrap_tuple_type: expected tuple, found {:?}", other), } } fn unwrap_struct_type(typ: &HirType) -> Vec<(String, HirType)> { - match typ { - HirType::Struct(def, args) => def.borrow().get_fields(args), - HirType::TypeVariable(binding, TypeVariableKind::Normal) => match &*binding.borrow() { - TypeBinding::Bound(binding) => unwrap_struct_type(binding), - TypeBinding::Unbound(_) => unreachable!(), - }, + match typ.follow_bindings() { + HirType::Struct(def, args) => def.borrow().get_fields(&args), other => unreachable!("unwrap_struct_type: expected struct, found {:?}", other), } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs index 5de43e59254..b83d2008530 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs @@ -28,8 +28,8 @@ use crate::hir_def::{ }; use crate::token::{Attributes, SecondaryAttribute}; use crate::{ - BinaryOpKind, ContractFunctionType, FunctionDefinition, FunctionVisibility, Generics, Shared, - TypeAlias, TypeBindings, TypeVariable, TypeVariableId, TypeVariableKind, + BinaryOpKind, FunctionDefinition, Generics, ItemVisibility, Shared, TypeAlias, TypeBindings, + TypeVariable, TypeVariableId, TypeVariableKind, }; /// An arbitrary number to limit the recursion depth when searching for trait impls. @@ -236,20 +236,11 @@ pub struct FunctionModifiers { pub name: String, /// Whether the function is `pub` or not. - pub visibility: FunctionVisibility, + pub visibility: ItemVisibility, pub attributes: Attributes, pub is_unconstrained: bool, - - /// This function's type in its contract. - /// If this function is not in a contract, this is always 'Secret'. - pub contract_function_type: Option, - - /// This function's contract visibility. - /// If this function is internal can only be called by itself. - /// Will be None if not in contract. - pub is_internal: Option, } impl FunctionModifiers { @@ -259,11 +250,9 @@ impl FunctionModifiers { pub fn new() -> Self { Self { name: String::new(), - visibility: FunctionVisibility::Public, + visibility: ItemVisibility::Public, attributes: Attributes::empty(), is_unconstrained: false, - is_internal: None, - contract_function_type: None, } } } @@ -759,17 +748,11 @@ impl NodeInterner { module: ModuleId, location: Location, ) -> DefinitionId { - use ContractFunctionType::*; - - // We're filling in contract_function_type and is_internal now, but these will be verified - // later during name resolution. let modifiers = FunctionModifiers { name: function.name.0.contents.clone(), visibility: function.visibility, attributes: function.attributes.clone(), is_unconstrained: function.is_unconstrained, - contract_function_type: Some(if function.is_open { Open } else { Secret }), - is_internal: Some(function.is_internal), }; self.push_function_definition(id, modifiers, module, location) } @@ -799,7 +782,7 @@ impl NodeInterner { /// /// The underlying function_visibilities map is populated during def collection, /// so this function can be called anytime afterward. - pub fn function_visibility(&self, func: FuncId) -> FunctionVisibility { + pub fn function_visibility(&self, func: FuncId) -> ItemVisibility { self.function_modifiers[&func].visibility } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/mod.rs index 0ff7819c00f..ea96dee8a47 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/mod.rs @@ -14,8 +14,8 @@ mod parser; use crate::token::{Keyword, Token}; use crate::{ast::ImportStatement, Expression, NoirStruct}; use crate::{ - Ident, LetStatement, NoirFunction, NoirTrait, NoirTraitImpl, NoirTypeAlias, Recoverable, - StatementKind, TypeImpl, UseTree, + Ident, LetStatement, ModuleDeclaration, NoirFunction, NoirTrait, NoirTraitImpl, NoirTypeAlias, + Recoverable, StatementKind, TypeImpl, UseTree, }; use chumsky::prelude::*; @@ -28,7 +28,7 @@ pub use parser::parse_program; #[derive(Debug, Clone)] pub(crate) enum TopLevelStatement { Function(NoirFunction), - Module(Ident), + Module(ModuleDeclaration), Import(UseTree), Struct(NoirStruct), Trait(NoirTrait), @@ -220,7 +220,7 @@ pub struct SortedModule { pub globals: Vec, /// Module declarations like `mod foo;` - pub module_decls: Vec, + pub module_decls: Vec, /// Full submodules as in `mod foo { ... definitions ... }` pub submodules: Vec, @@ -229,7 +229,7 @@ pub struct SortedModule { impl std::fmt::Display for SortedModule { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { for decl in &self.module_decls { - writeln!(f, "mod {decl};")?; + writeln!(f, "{decl};")?; } for import in &self.imports { @@ -309,7 +309,7 @@ pub enum ItemKind { Impl(TypeImpl), TypeAlias(NoirTypeAlias), Global(LetStatement), - ModuleDecl(Ident), + ModuleDecl(ModuleDeclaration), Submodules(ParsedSubModule), } @@ -380,8 +380,8 @@ impl SortedModule { self.imports.extend(import_stmt.desugar(None)); } - fn push_module_decl(&mut self, mod_name: Ident) { - self.module_decls.push(mod_name); + fn push_module_decl(&mut self, mod_decl: ModuleDeclaration) { + self.module_decls.push(mod_decl); } fn push_submodule(&mut self, submodule: SortedSubModule) { @@ -474,7 +474,7 @@ impl std::fmt::Display for TopLevelStatement { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { TopLevelStatement::Function(fun) => fun.fmt(f), - TopLevelStatement::Module(m) => write!(f, "mod {m}"), + TopLevelStatement::Module(m) => m.fmt(f), TopLevelStatement::Import(tree) => write!(f, "use {tree}"), TopLevelStatement::Trait(t) => t.fmt(f), TopLevelStatement::TraitImpl(i) => i.fmt(f), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs index 75f4a6359bf..383a1ffafc9 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs @@ -40,9 +40,9 @@ use crate::parser::{force, ignore_then_commit, statement_recovery}; use crate::token::{Keyword, Token, TokenKind}; use crate::{ BinaryOp, BinaryOpKind, BlockExpression, Distinctness, ForLoopStatement, ForRange, - FunctionReturnType, Ident, IfExpression, InfixExpression, LValue, Literal, NoirTypeAlias, - Param, Path, Pattern, Recoverable, Statement, TraitBound, TypeImpl, UnresolvedTraitConstraint, - UnresolvedTypeExpression, UseTree, UseTreeKind, Visibility, + FunctionReturnType, Ident, IfExpression, InfixExpression, LValue, Literal, ModuleDeclaration, + NoirTypeAlias, Param, Path, Pattern, Recoverable, Statement, TraitBound, TypeImpl, + UnresolvedTraitConstraint, UnresolvedTypeExpression, UseTree, UseTreeKind, Visibility, }; use chumsky::prelude::*; @@ -370,7 +370,9 @@ fn optional_type_annotation<'a>() -> impl NoirParser + 'a { } fn module_declaration() -> impl NoirParser { - keyword(Keyword::Mod).ignore_then(ident()).map(TopLevelStatement::Module) + keyword(Keyword::Mod) + .ignore_then(ident()) + .map(|ident| TopLevelStatement::Module(ModuleDeclaration { ident })) } fn use_statement() -> impl NoirParser { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs index 7448d84cfe1..7c365e7eb5a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs @@ -8,7 +8,7 @@ use crate::parser::labels::ParsingRuleLabel; use crate::parser::spanned; use crate::token::{Keyword, Token}; use crate::{ - Distinctness, FunctionDefinition, FunctionReturnType, FunctionVisibility, Ident, NoirFunction, + Distinctness, FunctionDefinition, FunctionReturnType, Ident, ItemVisibility, NoirFunction, Param, Visibility, }; @@ -36,9 +36,6 @@ pub(super) fn function_definition(allow_self: bool) -> impl NoirParser impl NoirParser impl NoirParser { +fn visibility_modifier() -> impl NoirParser { let is_pub_crate = (keyword(Keyword::Pub) .then_ignore(just(Token::LeftParen)) .then_ignore(keyword(Keyword::Crate)) .then_ignore(just(Token::RightParen))) - .map(|_| FunctionVisibility::PublicCrate); + .map(|_| ItemVisibility::PublicCrate); - let is_pub = keyword(Keyword::Pub).map(|_| FunctionVisibility::Public); + let is_pub = keyword(Keyword::Pub).map(|_| ItemVisibility::Public); - let is_private = empty().map(|_| FunctionVisibility::Private); + let is_private = empty().map(|_| ItemVisibility::Private); choice((is_pub_crate, is_pub, is_private)) } -/// function_modifiers: 'unconstrained'? (visibility)? 'open'? +/// function_modifiers: 'unconstrained'? (visibility)? /// /// returns (is_unconstrained, visibility, is_open) for whether each keyword was present -fn function_modifiers() -> impl NoirParser<(bool, FunctionVisibility, bool)> { +fn function_modifiers() -> impl NoirParser<(bool, ItemVisibility)> { keyword(Keyword::Unconstrained) .or_not() .then(visibility_modifier()) - .then(keyword(Keyword::Open).or_not()) - .map(|((unconstrained, visibility), open)| { - (unconstrained.is_some(), visibility, open.is_some()) - }) + .map(|(unconstrained, visibility)| (unconstrained.is_some(), visibility)) } /// non_empty_ident_list: ident ',' non_empty_ident_list diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs index 0d72fbd5303..1e2a6b4d65d 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs @@ -11,7 +11,7 @@ use crate::{ ParserErrorReason, TopLevelStatement, }, token::{Keyword, Token}, - Expression, FunctionVisibility, NoirTrait, NoirTraitImpl, TraitBound, TraitImplItem, TraitItem, + Expression, ItemVisibility, NoirTrait, NoirTraitImpl, TraitBound, TraitImplItem, TraitItem, UnresolvedTraitConstraint, UnresolvedType, }; @@ -120,15 +120,11 @@ pub(super) fn trait_implementation() -> impl NoirParser { fn trait_implementation_body() -> impl NoirParser> { let function = function::function_definition(true).validate(|mut f, span, emit| { - if f.def().is_internal - || f.def().is_unconstrained - || f.def().is_open - || f.def().visibility != FunctionVisibility::Private - { + if f.def().is_unconstrained || f.def().visibility != ItemVisibility::Private { emit(ParserError::with_reason(ParserErrorReason::TraitImplFunctionModifiers, span)); } // Trait impl functions are always public - f.def_mut().visibility = FunctionVisibility::Public; + f.def_mut().visibility = ItemVisibility::Public; TraitImplItem::Function(f) }); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs index c661cc92eef..3f78bd43ba9 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs @@ -81,7 +81,7 @@ mod test { &mut context, program.clone().into_sorted(), root_file_id, - Vec::new(), // No macro processors + &[], // No macro processors )); } (program, context, errors) @@ -535,15 +535,13 @@ mod test { assert!(errors.len() == 1, "Expected 1 error, got: {:?}", errors); for (err, _file_id) in errors { match &err { - CompilationError::DefinitionError( - DefCollectorErrorKind::MismatchTraitImplementationNumParameters { - actual_num_parameters, - expected_num_parameters, - trait_name, - method_name, - .. - }, - ) => { + CompilationError::TypeError(TypeCheckError::MismatchTraitImplNumParameters { + actual_num_parameters, + expected_num_parameters, + trait_name, + method_name, + .. + }) => { assert_eq!(actual_num_parameters, &1_usize); assert_eq!(expected_num_parameters, &2_usize); assert_eq!(method_name, "default"); @@ -1206,4 +1204,13 @@ fn lambda$f1(mut env$l1: (Field)) -> Field { "#; assert_eq!(get_program_errors(src).len(), 1); } + + #[test] + fn type_aliases_in_entry_point() { + let src = r#" + type Foo = u8; + fn main(_x: Foo) {} + "#; + assert_eq!(get_program_errors(src).len(), 0); + } } diff --git a/noir/noir-repo/compiler/noirc_printable_type/src/lib.rs b/noir/noir-repo/compiler/noirc_printable_type/src/lib.rs index 24f4f275a14..60f233cd86d 100644 --- a/noir/noir-repo/compiler/noirc_printable_type/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_printable_type/src/lib.rs @@ -33,6 +33,8 @@ pub enum PrintableType { length: u64, }, Function { + arguments: Vec, + return_type: Box, env: Box, }, MutableReference { @@ -176,8 +178,8 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { output.push_str("false"); } } - (PrintableValue::Field(_), PrintableType::Function { .. }) => { - output.push_str("<>"); + (PrintableValue::Field(_), PrintableType::Function { arguments, return_type, .. }) => { + output.push_str(&format!("< {:?}>>", arguments, return_type,)); } (_, PrintableType::MutableReference { .. }) => { output.push_str("<>"); @@ -350,7 +352,7 @@ pub fn decode_value( PrintableValue::Struct(struct_map) } - PrintableType::Function { env } => { + PrintableType::Function { env, .. } => { let field_element = field_iterator.next().unwrap(); let func_ref = PrintableValue::Field(field_element); // we want to consume the fields from the environment, but for now they are not actually printed diff --git a/noir/noir-repo/compiler/wasm/package.json b/noir/noir-repo/compiler/wasm/package.json index 67584a2def1..6dfa3215483 100644 --- a/noir/noir-repo/compiler/wasm/package.json +++ b/noir/noir-repo/compiler/wasm/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.24.0", + "version": "0.25.0", "license": "(MIT OR Apache-2.0)", "main": "dist/main.js", "types": "./dist/types/src/index.d.cts", diff --git a/noir/noir-repo/compiler/wasm/src/noir/package.ts b/noir/noir-repo/compiler/wasm/src/noir/package.ts index 81178e6ae96..2856798273a 100644 --- a/noir/noir-repo/compiler/wasm/src/noir/package.ts +++ b/noir/noir-repo/compiler/wasm/src/noir/package.ts @@ -105,7 +105,12 @@ export class Package { handles .filter((handle) => SOURCE_EXTENSIONS.find((ext) => handle.endsWith(ext))) .map(async (file) => { - const suffix = file.replace(this.#srcPath, ''); + // Github deps are directly added to the file manager, which causes them to be missing the absolute path to the source file + // and only include the extraction directory relative to the fm root directory + // This regexp ensures we remove the "real" source path for all dependencies, providing the compiler with what it expects for each source file: + // -> for bin/contract packages + // -> for libs + const suffix = file.replace(new RegExp(`.*${this.#srcPath}`), ''); return { path: this.getType() === 'lib' ? `${alias ? alias : this.#config.package.name}${suffix}` : file, source: (await fm.readFile(file, 'utf-8')).toString(), diff --git a/noir/noir-repo/compiler/wasm/src/types/noir_artifact.ts b/noir/noir-repo/compiler/wasm/src/types/noir_artifact.ts index 832a6ed9bf9..935c99043da 100644 --- a/noir/noir-repo/compiler/wasm/src/types/noir_artifact.ts +++ b/noir/noir-repo/compiler/wasm/src/types/noir_artifact.ts @@ -32,19 +32,16 @@ export interface EventAbi { fields: ABIVariable[]; } -/** The Noir function types. */ -export type NoirFunctionType = 'Open' | 'Secret' | 'Unconstrained'; - /** * The compilation result of an Noir function. */ export interface NoirFunctionEntry { /** The name of the function. */ name: string; - /** The type of the function. */ - function_type: NoirFunctionType; - /** Whether the function is internal. */ - is_internal: boolean; + /** Whether the function is unconstrained. */ + is_unconstrained: boolean; + /** The custom attributes applied to the function. */ + custom_attributes: string[]; /** The ABI of the function. */ abi: Abi; /** The bytecode of the function in base64. */ diff --git a/noir/noir-repo/compiler/wasm/test/fixtures/noir-contract/src/main.nr b/noir/noir-repo/compiler/wasm/test/fixtures/noir-contract/src/main.nr index 95824d09f4b..fc1dc8a5a17 100644 --- a/noir/noir-repo/compiler/wasm/test/fixtures/noir-contract/src/main.nr +++ b/noir/noir-repo/compiler/wasm/test/fixtures/noir-contract/src/main.nr @@ -5,7 +5,7 @@ contract TestContract { [foo::bar(param), param + pub_param] } - open fn openFunction() -> pub Field { + fn someFunction() -> pub Field { 42 } } diff --git a/noir/noir-repo/cspell.json b/noir/noir-repo/cspell.json index a96e3de901a..d961b600f40 100644 --- a/noir/noir-repo/cspell.json +++ b/noir/noir-repo/cspell.json @@ -154,6 +154,8 @@ "sdiv", "secp256k1", "secp256r1", + "Secpk", + "Secpr", "signedness", "signorecello", "smol", diff --git a/noir/noir-repo/deny.toml b/noir/noir-repo/deny.toml index 72150f08a3c..578f8427263 100644 --- a/noir/noir-repo/deny.toml +++ b/noir/noir-repo/deny.toml @@ -2,11 +2,13 @@ # More documentation for the advisories section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html [advisories] -vulnerability = "deny" -unmaintained = "warn" -unsound = "warn" +version = 2 yanked = "warn" -notice = "warn" + +ignore = [ + "RUSTSEC-2020-0168", # mach unmaintained + "RUSTSEC-2020-0016" # net2 unmaintained +] # This section is considered when running `cargo deny check bans`. # More documentation about the 'bans' section can be found here: @@ -32,9 +34,8 @@ skip = [] skip-tree = [] [licenses] -unlicensed = "deny" +version = 2 confidence-threshold = 0.9 -# copyleft = "deny" # List of explicitly allowed licenses # See https://spdx.org/licenses/ for list of possible licenses diff --git a/noir/noir-repo/docs/.markdownlint.json b/noir/noir-repo/docs/.markdownlint.json new file mode 100644 index 00000000000..40896b4542f --- /dev/null +++ b/noir/noir-repo/docs/.markdownlint.json @@ -0,0 +1,3 @@ +{ + "no-missing-space-atx": false +} diff --git a/noir/noir-repo/docs/docs/noir/standard_library/bigint.md b/noir/noir-repo/docs/docs/noir/standard_library/bigint.md new file mode 100644 index 00000000000..7d7931840cf --- /dev/null +++ b/noir/noir-repo/docs/docs/noir/standard_library/bigint.md @@ -0,0 +1,102 @@ +--- +title: Big Integers +description: How to use big integers from Noir standard library +keywords: + [ + Big Integer, + Noir programming language, + Noir libraries, + ] +--- + +The BigInt module in the standard library exposes some class of integers which do not fit (well) into a Noir native field. It implements modulo arithmetic, modulo a 'big' prime number. + +:::note + +The module can currently be considered as `Field`s with fixed modulo sizes used by a set of elliptic curves, in addition to just the native curve. [More work](https://github.com/noir-lang/noir/issues/510) is needed to achieve arbitrarily sized big integers. + +::: + +Currently 6 classes of integers (i.e 'big' prime numbers) are available in the module, namely: + +- BN254 Fq: Bn254Fq +- BN254 Fr: Bn254Fr +- Secp256k1 Fq: Secpk1Fq +- Secp256k1 Fr: Secpk1Fr +- Secp256r1 Fr: Secpr1Fr +- Secp256r1 Fq: Secpr1Fq + +Where XXX Fq and XXX Fr denote respectively the order of the base and scalar field of the (usual) elliptic curve XXX. +For instance the big integer 'Secpk1Fq' in the standard library refers to integers modulo $2^{256}-2^{32}-977$. + +Feel free to explore the source code for the other primes: + +#include_code curve_order_base noir_stdlib/src/bigint.nr rust + +## Example usage + +A common use-case is when constructing a big integer from its bytes representation, and performing arithmetic operations on it: + +#include_code big_int_example test_programs/execution_success/bigint/src/main.nr rust + +## Methods + +The available operations for each big integer are: + +### from_le_bytes + +Construct a big integer from its little-endian bytes representation. Example: + +```rust + let a = Secpk1Fq::from_le_bytes([x, y, 0, 45, 2]); + ``` + +Sure, here's the formatted version of the remaining methods: + +### to_le_bytes + +Return the little-endian bytes representation of a big integer. Example: + +```rust +let bytes = a.to_le_bytes(); +``` + +### add + +Add two big integers. Example: + +```rust +let sum = a + b; +``` + +### sub + +Subtract two big integers. Example: + +```rust +let difference = a - b; +``` + +### mul + +Multiply two big integers. Example: + +```rust +let product = a * b; +``` + +### div + +Divide two big integers. Note that division is field division and not euclidean division. Example: + +```rust +let quotient = a / b; +``` + +### eq + +Compare two big integers. Example: + +```rust +let are_equal = a == b; +``` diff --git a/noir/noir-repo/docs/docs/noir/standard_library/containers/hashmap.md b/noir/noir-repo/docs/docs/noir/standard_library/containers/hashmap.md new file mode 100644 index 00000000000..093b6d38d11 --- /dev/null +++ b/noir/noir-repo/docs/docs/noir/standard_library/containers/hashmap.md @@ -0,0 +1,270 @@ +--- +title: HashMap +keywords: [noir, map, hash, hashmap] +sidebar_position: 1 +--- + +`HashMap` is used to efficiently store and look up key-value pairs. + +`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. +Note that due to hash collisions, the actual maximum number of elements stored by any particular +hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since +every hash value will be performed modulo `MaxLen`. + +When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already +known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which +will likely change the result of the program. This behavior is set to become an error in future +versions instead. + +Example: + +```rust +// Create a mapping from Fields to u32s with a maximum length of 12 +// using a pedersen hash +let mut map: HashMap> = HashMap::default(); + +map.insert(1, 2); +map.insert(3, 4); + +let two = map.get(1).unwrap(); +``` + +## Methods + +### default + +#include_code default noir_stdlib/src/collections/map.nr rust + +Creates a fresh, empty HashMap. + +When using this function, always make sure to specify the maximum size of the hash map. + +This is the same `default` from the `Default` implementation given further below. It is +repeated here for convenience since it is the recommended way to create a hashmap. + +Example: + +#include_code default_example test_programs/execution_success/hashmap/src/main.nr rust + +Because `HashMap` has so many generic arguments that are likely to be the same throughout +your program, it may be helpful to create a type alias: + +#include_code type_alias test_programs/execution_success/hashmap/src/main.nr rust + +### with_hasher + +#include_code with_hasher noir_stdlib/src/collections/map.nr rust + +Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple +hashmaps are created with the same hasher instance. + +Example: + +#include_code with_hasher_example test_programs/execution_success/hashmap/src/main.nr rust + +### get + +#include_code get noir_stdlib/src/collections/map.nr rust + +Retrieves a value from the hashmap, returning `Option::none()` if it was not found. + +Example: + +#include_code get_example test_programs/execution_success/hashmap/src/main.nr rust + +### insert + +#include_code insert noir_stdlib/src/collections/map.nr rust + +Inserts a new key-value pair into the map. If the key was already in the map, its +previous value will be overridden with the newly provided one. + +Example: + +#include_code insert_example test_programs/execution_success/hashmap/src/main.nr rust + +### remove + +#include_code remove noir_stdlib/src/collections/map.nr rust + +Removes the given key-value pair from the map. If the key was not already present +in the map, this does nothing. + +Example: + +#include_code remove_example test_programs/execution_success/hashmap/src/main.nr rust + +### is_empty + +#include_code is_empty noir_stdlib/src/collections/map.nr rust + +True if the length of the hash map is empty. + +Example: + +#include_code is_empty_example test_programs/execution_success/hashmap/src/main.nr rust + +### len + +#include_code len noir_stdlib/src/collections/map.nr rust + +Returns the current length of this hash map. + +Example: + +#include_code len_example test_programs/execution_success/hashmap/src/main.nr rust + +### capacity + +#include_code capacity noir_stdlib/src/collections/map.nr rust + +Returns the maximum capacity of this hashmap. This is always equal to the capacity +specified in the hashmap's type. + +Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a +static capacity that does not increase as the map grows larger. Thus, this capacity +is also the maximum possible element count that can be inserted into the hashmap. +Due to hash collisions (modulo the hashmap length), it is likely the actual maximum +element count will be lower than the full capacity. + +Example: + +#include_code capacity_example test_programs/execution_success/hashmap/src/main.nr rust + +### clear + +#include_code clear noir_stdlib/src/collections/map.nr rust + +Clears the hashmap, removing all key-value pairs from it. + +Example: + +#include_code clear_example test_programs/execution_success/hashmap/src/main.nr rust + +### contains_key + +#include_code contains_key noir_stdlib/src/collections/map.nr rust + +True if the hashmap contains the given key. Unlike `get`, this will not also return +the value associated with the key. + +Example: + +#include_code contains_key_example test_programs/execution_success/hashmap/src/main.nr rust + +### entries + +#include_code entries noir_stdlib/src/collections/map.nr rust + +Returns a vector of each key-value pair present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +#include_code entries_example test_programs/execution_success/hashmap/src/main.nr rust + +### keys + +#include_code keys noir_stdlib/src/collections/map.nr rust + +Returns a vector of each key present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +#include_code keys_example test_programs/execution_success/hashmap/src/main.nr rust + +### values + +#include_code values noir_stdlib/src/collections/map.nr rust + +Returns a vector of each value present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +#include_code values_example test_programs/execution_success/hashmap/src/main.nr rust + +### iter_mut + +#include_code iter_mut noir_stdlib/src/collections/map.nr rust + +Iterates through each key-value pair of the HashMap, setting each key-value pair to the +result returned from the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If this is not desired, use `iter_values_mut` if only values need to be mutated, +or `entries` if neither keys nor values need to be mutated. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +#include_code iter_mut_example test_programs/execution_success/hashmap/src/main.nr rust + +### iter_keys_mut + +#include_code iter_keys_mut noir_stdlib/src/collections/map.nr rust + +Iterates through the HashMap, mutating each key to the result returned from +the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If only iteration is desired and the keys are not intended to be mutated, +prefer using `entries` instead. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +#include_code iter_keys_mut_example test_programs/execution_success/hashmap/src/main.nr rust + +### iter_values_mut + +#include_code iter_values_mut noir_stdlib/src/collections/map.nr rust + +Iterates through the HashMap, applying the given function to each value and mutating the +value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` +because the keys are untouched and the underlying hashmap thus does not need to be reordered. + +Example: + +#include_code iter_values_mut_example test_programs/execution_success/hashmap/src/main.nr rust + +### retain + +#include_code retain noir_stdlib/src/collections/map.nr rust + +Retains only the key-value pairs for which the given function returns true. +Any key-value pairs for which the function returns false will be removed from the map. + +Example: + +#include_code retain_example test_programs/execution_success/hashmap/src/main.nr rust + +## Trait Implementations + +### default + +#include_code default noir_stdlib/src/collections/map.nr rust + +Constructs an empty HashMap. + +Example: + +#include_code default_example test_programs/execution_success/hashmap/src/main.nr rust + +### eq + +#include_code eq noir_stdlib/src/collections/map.nr rust + +Checks if two HashMaps are equal. + +Example: + +#include_code eq_example test_programs/execution_success/hashmap/src/main.nr rust diff --git a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx index 99b7f830a20..c2c0624dfad 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx +++ b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx @@ -15,6 +15,14 @@ Verifier for EdDSA signatures fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool ``` +It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify_with_hasher` function with a parameter implementing the Hasher trait. For instance, if you want to use Poseidon2 instead, you can do the following: +```rust +use dep::std::hash::poseidon2::Poseidon2Hasher; + +let mut hasher = Poseidon2Hasher::default(); +eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher); +``` + ## eddsa::eddsa_to_pub diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/explainers/explainer-oracle.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/explainers/explainer-oracle.md new file mode 100644 index 00000000000..b84ca5dd986 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/explainers/explainer-oracle.md @@ -0,0 +1,57 @@ +--- +title: Oracles +description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. +keywords: + - Noir Programming + - Oracles + - JSON-RPC + - Foreign Call Handlers + - Constrained Functions + - Blockchain Programming +sidebar_position: 1 +--- + +If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. + +![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) + +A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? + +Oracles are functions that provide this feature. + +## Use cases + +An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. + +Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). + +In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. + +## Constraining oracles + +Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. + +To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: + +```rust +#[oracle(getNoun)] +unconstrained fn get_noun(address: Field) -> Field +``` + +This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. + +In short, **Oracles don't prove anything. Your Noir program does.** + +:::danger + +If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! + +::: + +## How to use Oracles + +On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. + +In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. + +If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/explainers/explainer-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/explainers/explainer-recursion.md new file mode 100644 index 00000000000..18846176ca7 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/explainers/explainer-recursion.md @@ -0,0 +1,176 @@ +--- +title: Recursive proofs +description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. + +keywords: + [ + "Recursive Proofs", + "Zero-Knowledge Programming", + "Noir", + "EVM Blockchain", + "Smart Contracts", + "Recursion in Noir", + "Alice and Bob Guessing Game", + "Recursive Merkle Tree", + "Reusable Components", + "Optimizing Computational Resources", + "Improving Efficiency", + "Verification Key", + "Aggregation", + "Recursive zkSNARK schemes", + "PLONK", + "Proving and Verification Keys" + ] +sidebar_position: 1 +pagination_next: how_to/how-to-recursion +--- + +In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: + +```js +function factorial(n) { + if (n === 0 || n === 1) { + return 1; + } else { + return n * factorial(n - 1); + } +} +``` + +In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: + +```md + Is `n` 1? <--------- + /\ / + / \ n = n -1 + / \ / + Yes No -------- +``` + +In Zero-Knowledge, recursion has some similarities. + +It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. + +This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. + +## Examples + +Let us look at some of these examples + +### Alice and Bob - Guessing game + +Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. + +So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. + +This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. + +As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". + +She can then generate a proof that she verified his proof, and so on. + +```md + Did you fail? <-------------------------- + / \ / + / \ n = n -1 + / \ / + Yes No / + | | / + | | / + | You win / + | / + | / +Generate proof of that / + + / + my own guess ---------------- +``` + +### Charlie - Recursive merkle tree + +Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! + +If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: + +```md + abcd + __________|______________ + | | + ab cd + _____|_____ ______|______ + | | | | + alice bob charlie daniel +``` + +Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. + +### Daniel - Reusable components + +Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. + +He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. + +## What params do I need + +As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: + +- The proof to verify +- The Verification Key of the circuit that generated the proof +- A hash of this verification key, as it's needed for some backends +- The public inputs for the proof + +:::info + +Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. + +So, taking the example of Alice and Bob and their guessing game: + +- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit +- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. + +We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. + +::: + +## Some architecture + +As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: + +### Adding some logic to a proof verification + +This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: + +- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) +- A `guessing` section, which is basically the logic part where the actual guessing happens + +In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. + +### Aggregating proofs + +In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. + +To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: + +- A `main`, non-recursive circuit with some logic +- A `recursive` circuit meant to verify two proofs in one proof + +The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. + +### Recursively verifying different circuits + +Nothing prevents you from verifying different circuits in a recursive proof, for example: + +- A `circuit1` circuit +- A `circuit2` circuit +- A `recursive` circuit + +In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) + +## How fast is it + +At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. + +Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. + +## How can I try it + +Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/index.md new file mode 100644 index 00000000000..743c4d8d634 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/index.md @@ -0,0 +1,142 @@ +--- +title: Creating a Project +description: + Learn how to create and verify your first Noir program using Nargo, a programming language for + zero-knowledge proofs. +keywords: + [ + Nargo, + Noir, + zero-knowledge proofs, + programming language, + create Noir program, + verify Noir program, + step-by-step guide, + ] +sidebar_position: 1 + +--- + +Now that we have installed Nargo, it is time to make our first hello world program! + +## Create a Project Directory + +Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home +directory to house our Noir programs. + +For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by +running: + +```sh +mkdir ~/projects +cd ~/projects +``` + +## Create Our First Nargo Project + +Now that we are in the projects directory, create a new Nargo project by running: + +```sh +nargo new hello_world +``` + +> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for +> demonstration. +> +> In production, the common practice is to name the project folder as `circuits` for better +> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, +> `test`). + +A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and +_Nargo.toml_ which contain the source code and environmental options of your Noir program +respectively. + +### Intro to Noir Syntax + +Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: + +```rust +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +The first line of the program specifies the program's inputs: + +```rust +x : Field, y : pub Field +``` + +Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the +keyword `pub` (e.g. `y`). To learn more about private and public values, check the +[Data Types](../../noir/concepts/data_types/index.md) section. + +The next line of the program specifies its body: + +```rust +assert(x != y); +``` + +The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. + +For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. + +## Build In/Output Files + +Change directory into _hello_world_ and build in/output files for your Noir program by running: + +```sh +cd hello_world +nargo check +``` + +Two additional files would be generated in your project directory: + +_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. + +## Prove Our Noir Program + +Now that the project is set up, we can create a proof of correct execution of our Noir program. + +Fill in input values for execution in the _Prover.toml_ file. For example: + +```toml +x = "1" +y = "2" +``` + +Prove the valid execution of your Noir program: + +```sh +nargo prove +``` + +A new folder _proofs_ would then be generated in your project directory, containing the proof file +`.proof`, where the project name is defined in Nargo.toml. + +The _Verifier.toml_ file would also be updated with the public values computed from program +execution (in this case the value of `y`): + +```toml +y = "0x0000000000000000000000000000000000000000000000000000000000000002" +``` + +> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. + +## Verify Our Noir Program + +Once a proof is generated, we can verify correct execution of our Noir program by verifying the +proof file. + +Verify your proof by running: + +```sh +nargo verify +``` + +The verification will complete in silence if it is successful. If it fails, it will log the +corresponding error instead. + +Congratulations, you have now created and verified a proof for your very first Noir program! + +In the [next section](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/project_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/project_breakdown.md new file mode 100644 index 00000000000..6160a102c6c --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/hello_noir/project_breakdown.md @@ -0,0 +1,199 @@ +--- +title: Project Breakdown +description: + Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML + files, and how to prove and verify your program. +keywords: + [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] +sidebar_position: 2 +--- + +This section breaks down our hello world program from the previous section. We elaborate on the project +structure and what the `prove` and `verify` commands did. + +## Anatomy of a Nargo Project + +Upon creating a new project with `nargo new` and building the in/output files with `nargo check` +commands, you would get a minimal Nargo project of the following structure: + + - src + - Prover.toml + - Verifier.toml + - Nargo.toml + +The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ +file will be generated within it. + +### Prover.toml + +_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. + +### Verifier.toml + +_Verifier.toml_ contains public in/output values computed when executing the Noir program. + +### Nargo.toml + +_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. + +Example Nargo.toml: + +```toml +[package] +name = "noir_starter" +type = "bin" +authors = ["Alice"] +compiler_version = "0.9.0" +description = "Getting started with Noir" +entry = "circuit/main.nr" +license = "MIT" + +[dependencies] +ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} +``` + +Nargo.toml for a [workspace](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +#### Package section + +The package section defines a number of fields including: + +- `name` (**required**) - the name of the package +- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract +- `authors` (optional) - authors of the project +- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) +- `description` (optional) +- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) +- `backend` (optional) +- `license` (optional) + +#### Dependencies section + +This is where you will specify any dependencies for your project. See the [Dependencies page](../../noir/modules_packages_crates/dependencies.md) for more info. + +`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or +verifier contract respectively. + +### main.nr + +The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. + +In our sample program, _main.nr_ looks like this: + +```rust +fn main(x : Field, y : Field) { + assert(x != y); +} +``` + +The parameters `x` and `y` can be seen as the API for the program and must be supplied by the +prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when +verifying the proof. + +The prover supplies the values for `x` and `y` in the _Prover.toml_ file. + +As for the program body, `assert` ensures that the condition to be satisfied (e.g. `x != y`) is +constrained by the proof of the execution of said program (i.e. if the condition was not met, the +verifier would reject the proof as an invalid proof). + +### Prover.toml + +The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and +public). + +In our hello world program the _Prover.toml_ file looks like this: + +```toml +x = "1" +y = "2" +``` + +When the command `nargo prove` is executed, two processes happen: + +1. Noir creates a proof that `x`, which holds the value of `1`, and `y`, which holds the value of `2`, + is not equal. This inequality constraint is due to the line `assert(x != y)`. + +2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. + +#### Arrays of Structs + +The following code shows how to pass an array of structs to a Noir program to generate a proof. + +```rust +// main.nr +struct Foo { + bar: Field, + baz: Field, +} + +fn main(foos: [Foo; 3]) -> pub Field { + foos[2].bar + foos[2].baz +} +``` + +Prover.toml: + +```toml +[[foos]] # foos[0] +bar = 0 +baz = 0 + +[[foos]] # foos[1] +bar = 0 +baz = 0 + +[[foos]] # foos[2] +bar = 1 +baz = 2 +``` + +#### Custom toml files + +You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. + +This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: + +```bash +nargo prove +``` + +This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: + +```bash +nargo prove -p OtherProver +``` + +## Verifying a Proof + +When the command `nargo verify` is executed, two processes happen: + +1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) + +2. If that file is found, the proof's validity is checked + +> **Note:** The validity of the proof is linked to the current Noir program; if the program is +> changed and the verifier verifies the proof, it will fail because the proof is not valid for the +> _modified_ Noir program. + +In production, the prover and the verifier are usually two separate entities. A prover would +retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the +verifier. The verifier would then retrieve the public inputs, usually from external sources, and +verify the validity of the proof against it. + +Take a private asset transfer as an example: + +A person using a browser as the prover would retrieve private inputs locally (e.g. the user's private key) and +public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof +and submit it to the verifier smart contract. + +The verifier contract would then draw the user's encrypted balance directly from the blockchain and +verify the proof submitted against it. If the verification passes, additional functions in the +verifier contract could trigger (e.g. approve the asset transfer). + +Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/_category_.json new file mode 100644 index 00000000000..0c02fb5d4d7 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 0, + "label": "Install Nargo", + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/index.md new file mode 100644 index 00000000000..4ef86aa5914 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/index.md @@ -0,0 +1,48 @@ +--- +title: Nargo Installation +description: + nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup +keywords: [ + Nargo + Noir + Rust + Cargo + Noirup + Installation + Terminal Commands + Version Check + Nightlies + Specific Versions + Branches + Noirup Repository +] +pagination_next: getting_started/hello_noir/index +--- + +`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. + +With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. + +Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. + +## Installing Noirup + +Open a terminal on your machine, and write: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Close the terminal, open another one, and run + +```bash +noirup +``` + +Done. That's it. You should have the latest version working. You can check with `nargo --version`. + +You can also install nightlies, specific versions +or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more +information. + +Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/other_install_methods.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/other_install_methods.md new file mode 100644 index 00000000000..a35e34aaf9c --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/installation/other_install_methods.md @@ -0,0 +1,254 @@ +--- +title: Alternative Install Methods +description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains other methods that don't rely on noirup, such as compiling from source, installing from binaries, and using WSL for windows +keywords: [ + Installation + Nargo + Noirup + Binaries + Compiling from Source + WSL for Windows + macOS + Linux + Nix + Direnv + Shell & editor experience + Building and testing + Uninstalling Nargo + Noir vs code extension, + ] +sidebar_position: 1 +--- + +## Encouraged Installation Method: Noirup + +Noirup is the endorsed method for installing Nargo, streamlining the process of fetching binaries or compiling from source. It supports a range of options to cater to your specific needs, from nightly builds and specific versions to compiling from various sources. + +### Installing Noirup + +First, ensure you have `noirup` installed: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +### Fetching Binaries + +With `noirup`, you can easily switch between different Nargo versions, including nightly builds: + +- **Nightly Version**: Install the latest nightly build. + + ```sh + noirup --version nightly + ``` + +- **Specific Version**: Install a specific version of Nargo. + ```sh + noirup --version + ``` + +### Compiling from Source + +`noirup` also enables compiling Nargo from various sources: + +- **From a Specific Branch**: Install from the latest commit on a branch. + + ```sh + noirup --branch + ``` + +- **From a Fork**: Install from the main branch of a fork. + + ```sh + noirup --repo + ``` + +- **From a Specific Branch in a Fork**: Install from a specific branch in a fork. + + ```sh + noirup --repo --branch + ``` + +- **From a Specific Pull Request**: Install from a specific PR. + + ```sh + noirup --pr + ``` + +- **From a Specific Commit**: Install from a specific commit. + + ```sh + noirup -C + ``` + +- **From Local Source**: Compile and install from a local directory. + ```sh + noirup --path ./path/to/local/source + ``` + +## Alternate Installation Methods (No Longer Recommended) + +While the following methods are available, they are no longer recommended. We advise using noirup for a more efficient and flexible installation experience. + +However, there are other methods for installing Nargo: + +- [Binaries](#option-1-installing-from-binaries) +- [Compiling from Source](#option-2-compile-from-source) +- [WSL for Windows](#option-3-wsl-for-windows) + +### Option 1: Installing from Binaries + +See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous +platform specific binaries. + +#### Step 1 + +Paste and run the following in the terminal to extract and install the binary: + +> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend +> `sudo` and re-run it. + +##### macOS (Apple Silicon) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.24.0/nargo-aarch64-apple-darwin.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ +echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ +source ~/.zshrc +``` + +##### macOS (Intel) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.24.0/nargo-x86_64-apple-darwin.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ +echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ +source ~/.zshrc +``` + +##### Linux (Bash) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.24.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ +echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ +source ~/.bashrc +``` + +#### Step 2 + +Check if the installation was successful by running `nargo --version`. You should get a version number. + +> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from +> Finder. Close the new terminal popped up and `nargo` should now be accessible. + +### Option 2: Compile from Source + +Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating issues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). + +Combined with direnv, which automatically sets or clears environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. + +#### Setting up your environment + +For the best experience, please follow these instructions to setup your environment: + +1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. +2. Create the file `~/.config/nix/nix.conf` with the contents: + +```ini +experimental-features = nix-command +extra-experimental-features = flakes +``` + +3. Install direnv into your Nix profile by running: + +```sh +nix profile install nixpkgs#direnv +``` + +4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). + 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. +5. Restart your shell. + +#### Shell & editor experience + +Now that your environment is set up, you can get to work on the project. + +1. Clone the repository, such as: + +```sh +git clone git@github.com:noir-lang/noir +``` + +> Replacing `noir` with whichever repository you want to work on. + +2. Navigate to the directory: + +```sh +cd noir +``` + +> Replacing `noir` with whichever repository you cloned. + +3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: + +```sh +direnv allow +``` + +4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. + +5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): + +```sh +code . +``` + +6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. + +#### Building and testing + +Assuming you are using `direnv` to populate your environment, building and testing the project can be done +with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.73.0 at the time of this writing. + +If you want to build the entire project in an isolated sandbox, you can use Nix commands: + +1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. +2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. + +#### Without `direnv` + +If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. + +Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! + +### Option 3: WSL (for Windows) + +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). + +Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. + +step 2: Follow the [Noirup instructions](#encouraged-installation-method-noirup). + +## Uninstalling Nargo + +### Noirup + +If you installed Nargo with `noirup` or through directly downloading binaries, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. + +```bash +rm -r ~/.nargo +rm -r ~/nargo +rm -r ~/noir_cache +``` + +### Nix + +If you installed Nargo with Nix or compiled it from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. + +```bash +rm ~/.nix-profile/bin/nargo +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/_category_.json new file mode 100644 index 00000000000..55804c03a71 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 2, + "label": "Tooling", + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/index.mdx new file mode 100644 index 00000000000..ac480f3c9f5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/index.mdx @@ -0,0 +1,38 @@ +--- +title: Tooling +Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects. +Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] +--- + +Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. + +## Playground + +The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org). + +## IDE tools + +When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. + +The easiest way to use these tools is by installing the [Noir VS Code extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +## Codespaces + +Some Noir repos have leveraged Codespaces in order to ease the development process. You can visit the [noir-starter](https://github.com/noir-lang/noir-starter) for an example. + + + +## GitHub Actions + +You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as +installing `noirup` and running tests in your GitHub Action `yml` file. + +See the +[config file in the Noir repo](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) for an example usage. + +## Community projects + +As an open-source project, Noir has received many contributions over time. Some of them are related with developer tooling, and you can see some of them in [Awesome Noir repository](https://github.com/noir-lang/awesome-noir#dev-tools) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/language_server.md new file mode 100644 index 00000000000..81e0356ef8a --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/language_server.md @@ -0,0 +1,43 @@ +--- +title: Language Server +description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. +keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] +sidebar_position: 0 +--- + +This section helps you install and configure the Noir Language Server. + +The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. + +## Language Server + +The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. +As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! + +If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. + +## Language Client + +The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. + +Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). +> +> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. + +When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: + +![Compile and Execute](@site/static/img/codelens_compile_execute.png) +![Run test](@site/static/img/codelens_run_test.png) + +You should also see your tests in the `testing` panel: + +![Testing panel](@site/static/img/codelens_testing_panel.png) + +### Configuration + +- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. +- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. +- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. +- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/testing.md new file mode 100644 index 00000000000..d3e0c522473 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/getting_started/tooling/testing.md @@ -0,0 +1,62 @@ +--- +title: Testing in Noir +description: Learn how to use Nargo to test your Noir program in a quick and easy way +keywords: [Nargo, testing, Noir, compile, test] +sidebar_position: 1 +--- + +You can test your Noir programs using Noir circuits. + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. + +For example if you have a program like: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test] +fn test_add() { + assert(add(2,2) == 4); + assert(add(0,1) == 1); + assert(add(1,0) == 1); +} +``` + +Running `nargo test` will test that the `test_add` function can be executed while satisfying all +the constraints which allows you to test that add returns the expected values. Test functions can't +have any arguments currently. + +### Test fail + +You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test(should_fail)] +fn test_add() { + assert(add(2,2) == 5); +} +``` + +You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: + +```rust +fn main(african_swallow_avg_speed : Field) { + assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); +} + +#[test] +fn test_king_arthur() { + main(65); +} + +#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] +fn test_bridgekeeper() { + main(32); +} + +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-oracles.md new file mode 100644 index 00000000000..0d84d992320 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-oracles.md @@ -0,0 +1,280 @@ +--- +title: How to use Oracles +description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. +keywords: + - Noir Programming + - Oracles + - Nargo + - NoirJS + - JSON RPC Server + - Foreign Call Handlers +sidebar_position: 1 +--- + +This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: + +- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. +- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. +- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. +- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). + +For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). + +## Rundown + +This guide has 3 major steps: + +1. How to modify our Noir program to make use of oracle calls as unconstrained functions +2. How to write a JSON RPC Server to resolve these oracle calls with Nargo +3. How to use them in Nargo and how to provide a custom resolver in NoirJS + +## Step 1 - Modify your Noir program + +An oracle is defined in a Noir program by defining two methods: + +- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). +- A decorated oracle method - This tells the compiler that this method is an RPC call. + +An example of an oracle that returns a `Field` would be: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(number: Field) -> Field { } + +unconstrained fn get_sqrt(number: Field) -> Field { + sqrt(number) +} +``` + +In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); +} +``` + +In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. + +:::danger + +As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); + assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! +} +``` + +::: + +:::info + +Currently, oracles only work with single params or array params. For example: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } +``` + +::: + +## Step 2 - Write an RPC server + +Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. + +Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } + +unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { + sqrt(input) +} + +fn main(input: [Field; 2]) { + let sqrt = get_sqrt(input); + assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); + assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); +} +``` + +:::info + +Why square root? + +In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. + +::: + +Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): + +```js +import { JSONRPCServer } from "json-rpc-2.0"; +import express from "express"; +import bodyParser from "body-parser"; + +const app = express(); +app.use(bodyParser.json()); + +const server = new JSONRPCServer(); +app.post("/", (req, res) => { + const jsonRPCRequest = req.body; + server.receive(jsonRPCRequest).then((jsonRPCResponse) => { + if (jsonRPCResponse) { + res.json(jsonRPCResponse); + } else { + res.sendStatus(204); + } + }); +}); + +app.listen(5555); +``` + +Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: + +```js +server.addMethod("getSqrt", async (params) => { + const values = params[0].Array.map(({ inner }) => { + return { inner: `${Math.sqrt(parseInt(inner, 16))}` }; + }); + return { values: [{ Array: values }] }; +}); +``` + +:::tip + +Brillig expects an object with an array of values. Each value is an object declaring to be `Single` or `Array` and returning a `inner` property *as a string*. For example: + +```json +{ "values": [{ "Array": [{ "inner": "1" }, { "inner": "2"}]}]} +{ "values": [{ "Single": { "inner": "1" }}]} +{ "values": [{ "Single": { "inner": "1" }}, { "Array": [{ "inner": "1", { "inner": "2" }}]}]} +``` + +If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: + +```js +interface Value { + inner: string, +} + +interface SingleForeignCallParam { + Single: Value, +} + +interface ArrayForeignCallParam { + Array: Value[], +} + +type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; + +interface ForeignCallResult { + values: ForeignCallParam[], +} +``` + +::: + +## Step 3 - Usage with Nargo + +Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test`, `nargo execute` and `nargo prove` commands by passing a value to `--oracle-resolver`. For example: + +```bash +nargo test --oracle-resolver http://localhost:5555 +``` + +This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. + +## Step 4 - Usage with NoirJS + +In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. + +For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: + +```js +const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc + +await noir.generateFinalProof(inputs, foreignCallHandler) +``` + +As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. + +:::tip + +Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? + +You don't technically have to, but then how would you run `nargo test` or `nargo prove`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. + +::: + +In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. + +For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): + +```js +import { JSONRPCClient } from "json-rpc-2.0"; + +// declaring the JSONRPCClient +const client = new JSONRPCClient((jsonRPCRequest) => { +// hitting the same JSON RPC Server we coded above + return fetch("http://localhost:5555", { + method: "POST", + headers: { + "content-type": "application/json", + }, + body: JSON.stringify(jsonRPCRequest), + }).then((response) => { + if (response.status === 200) { + return response + .json() + .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); + } else if (jsonRPCRequest.id !== undefined) { + return Promise.reject(new Error(response.statusText)); + } + }); +}); + +// declaring a function that takes the name of the foreign call (getSqrt) and the inputs +const foreignCallHandler = async (name, input) => { + // notice that the "inputs" parameter contains *all* the inputs + // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] + const oracleReturn = await client.request(name, [ + { Array: input[0].map((i) => ({ inner: i.toString("hex") })) }, + ]); + return [oracleReturn.values[0].Array.map((x) => x.inner)]; +}; + +// the rest of your NoirJS code +const input = { input: [4, 16] }; +const { witness } = await noir.execute(numbers, foreignCallHandler); +``` + +:::tip + +If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: + +```bash +yarn add cors +``` + +and use it as a middleware: + +```js +import cors from "cors"; + +const app = express(); +app.use(cors()) +``` + +::: + +## Conclusion + +Hopefully by the end of this guide, you should be able to: + +- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. +- Provide custom foreign call handlers for NoirJS. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-recursion.md new file mode 100644 index 00000000000..4c45bb87ae2 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-recursion.md @@ -0,0 +1,179 @@ +--- +title: How to use recursion on NoirJS +description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. +keywords: + [ + "NoirJS", + "EVM blockchain", + "smart contracts", + "recursion", + "solidity verifiers", + "Barretenberg backend", + "noir_js", + "backend_barretenberg", + "intermediate proofs", + "final proofs", + "nargo compile", + "json import", + "recursive circuit", + "recursive app" + ] +sidebar_position: 1 +--- + +This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: + +- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). +- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) +- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. + +It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. + +:::info + +As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. + +While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. + +In short: + +- `noir_js` generates *only* final proofs +- `backend_barretenberg` generates both types of proofs + +::: + +In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following: + +- `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. +- `recursive`: a circuit that verifies `main` + +For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. + +## Step 1: Setup + +In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. + +For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. + +It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: + +```js +const backend = new Backend(circuit, { threads: 8 }) +``` + +:::tip +You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores +::: + +## Step 2: Generating the witness and the proof for `main` + +After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. + +```js +const noir = new Noir(circuit, backend) +const { witness } = noir.execute(input) +``` + +With this witness, you are now able to generate the intermediate proof for the main circuit: + +```js +const { proof, publicInputs } = await backend.generateProof(witness) +``` + +:::warning + +Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! + +In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. + +With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. + +::: + +## Step 3 - Verification and proof artifacts + +Optionally, you are able to verify the intermediate proof: + +```js +const verified = await backend.verifyProof({ proof, publicInputs }) +``` + +This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit: + +```js +const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount) +``` + +This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. + +:::info + +The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. + +::: + +:::warning + +One common mistake is to forget *who* makes this call. + +In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! + +Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. + +::: + +## Step 4 - Recursive proof generation + +With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: + +```js +const recursiveInputs = { + verification_key: vkAsFields, // array of length 114 + proof: proofAsFields, // array of length 93 + size of public inputs + publicInputs: [mainInput.y], // using the example above, where `y` is the only public input + key_hash: vkHash, +} + +const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! +const { proof, publicInputs } = backend.generateProof(witness) +const verified = backend.verifyProof({ proof, publicInputs }) +``` + +You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! + +:::tip + +Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: + +```js +const circuits = { + main: mainJSON, + recursive: recursiveJSON +} +const backends = { + main: new BarretenbergBackend(circuits.main), + recursive: new BarretenbergBackend(circuits.recursive) +} +const noir_programs = { + main: new Noir(circuits.main, backends.main), + recursive: new Noir(circuits.recursive, backends.recursive) +} +``` + +This allows you to neatly call exactly the method you want without conflicting names: + +```js +// Alice runs this 👇 +const { witness: mainWitness } = await noir_programs.main.execute(input) +const proof = await backends.main.generateProof(mainWitness) + +// Bob runs this 👇 +const verified = await backends.main.verifyProof(proof) +const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts( + proof, + numPublicInputs, +); +const recursiveProof = await noir_programs.recursive.generateProof(recursiveInputs) +``` + +::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-solidity-verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-solidity-verifier.md new file mode 100644 index 00000000000..e3c7c1065da --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/how-to-solidity-verifier.md @@ -0,0 +1,231 @@ +--- +title: Generate a Solidity Verifier +description: + Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier + contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart + contract. Read more to find out +keywords: + [ + solidity verifier, + smart contract, + blockchain, + compiler, + plonk_vk.sol, + EVM blockchain, + verifying Noir programs, + proving backend, + Barretenberg, + ] +sidebar_position: 0 +pagination_next: tutorials/noirjs_app +--- + +Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. + +This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. + +This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: + +- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network +- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit +- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. + +## Rundown + +Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: + +1. How to generate a solidity smart contract +2. How to compile the smart contract in the RemixIDE +3. How to deploy it to a testnet + +## Step 1 - Generate a contract + +This is by far the most straight-forward step. Just run: + +```sh +nargo codegen-verifier +``` + +A new `contract` folder would then be generated in your project directory, containing the Solidity +file `plonk_vk.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. + +:::info + +It is possible to generate verifier contracts of Noir programs for other smart contract platforms as long as the proving backend supplies an implementation. + +Barretenberg, the default proving backend for Nargo, supports generation of verifier contracts, for the time being these are only in Solidity. +::: + +## Step 2 - Compiling + +We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open +Remix and create a blank workspace. + +![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) + +We will create a new file to contain the contract Nargo generated, and copy-paste its content. + +:::warning + +You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. + +::: + +To compile our the verifier, we can navigate to the compilation tab: + +![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) + +Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: + +![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) + +This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. + +:::info + +This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. + +::: + +![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) + +## Step 3 - Deploying + +At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. + +Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: + +- An `UltraVerificationKey` library which simply stores the verification key for our circuit. +- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. +- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. + +Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": + +![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) + +A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. + +:::note + +Why "UltraVerifier"? + +To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. + +In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. + +::: + +## Step 4 - Verifying + +To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: + +```solidity +function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) +``` + +When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. For `_proof`, run `nargo prove` and use the string in `proof/.proof` (adding the hex `0x` prefix). We can also copy the public input from `Verifier.toml`, as it will be properly formatted as 32-byte strings: + +``` +0x...... , [0x0000.....02] +``` + +A programmatic example of how the `verify` function is called can be seen in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): + +```solidity +function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { + // ... + bytes32[] memory publicInputs = new bytes32[](4); + publicInputs[0] = merkleRoot; + publicInputs[1] = bytes32(proposalId); + publicInputs[2] = bytes32(vote); + publicInputs[3] = nullifierHash; + require(verifier.verify(proof, publicInputs), "Invalid proof"); +``` + +:::info[Return Values] + +A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in +Noir. + +Under the hood, the return value is passed as an input to the circuit and is checked at the end of +the circuit program. + +For example, if you have Noir program like this: + +```rust +fn main( + // Public inputs + pubkey_x: pub Field, + pubkey_y: pub Field, + // Private inputs + priv_key: Field, +) -> pub Field +``` + +the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. Like before, these values are populated in Verifier.toml after running `nargo prove`. + +Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. + +In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return]`. + +::: + +:::tip[Structs] + +You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. + +For example, consider the following program: + +```rust +struct Type1 { + val1: Field, + val2: Field, +} + +struct Nested { + t1: Type1, + is_true: bool, +} + +fn main(x: pub Field, nested: pub Nested, y: pub Field) { + //... +} +``` + +The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` + +::: + +The other function you can call is our entrypoint `verify` function, as defined above. + +:::tip + +It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. + +This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. + +It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). + +::: + +## A Note on EVM chains + +ZK-SNARK verification depends on some precompiled cryptographic primitives such as Elliptic Curve Pairings (if you like complex math, you can read about EC Pairings [here](https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627)). Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. + +For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: + +- Optimism +- Arbitrum +- Polygon PoS +- Scroll +- Celo + +If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. + +## What's next + +Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). + +You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. + +You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/merkle-proof.mdx new file mode 100644 index 00000000000..34074659ac1 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/merkle-proof.mdx @@ -0,0 +1,48 @@ +--- +title: Prove Merkle Tree Membership +description: + Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a + merkle tree with a specified root, at a given index. +keywords: + [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] +--- + +Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is +in a merkle tree. + +```rust +use dep::std; + +fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { + let leaf = std::hash::hash_to_field(message); + let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); + assert(merkle_root == root); +} + +``` + +The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen +by the backend. The only requirement is that this hash function can heuristically be used as a +random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` +instead. + +```rust +let leaf = std::hash::hash_to_field(message); +``` + +The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. + +```rust +let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); +assert (merkle_root == root); +``` + +> **Note:** It is possible to re-implement the merkle tree implementation without standard library. +> However, for most usecases, it is enough. In general, the standard library will always opt to be +> as conservative as possible, while striking a balance with efficiency. + +An example, the merkle membership proof, only requires a hash function that has collision +resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient +than the even more conservative sha256. + +[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/using-devcontainers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/using-devcontainers.mdx new file mode 100644 index 00000000000..727ec6ca667 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/how_to/using-devcontainers.mdx @@ -0,0 +1,110 @@ +--- +title: Developer Containers and Codespaces +description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." +keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] +sidebar_position: 1 +--- + +Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. + +## What's a devcontainer after all? + +A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. + +There are many advantages to this: + +- It's platform and architecture agnostic +- You don't need to have an IDE installed, or Nargo, or use a terminal at all +- It's safer for using on a public machine or public network + +One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. +Enter Codespaces. + +## Codespaces + +If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? + +Nothing! Except perhaps the 30-40$ per hour it will cost you. + +The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. + +Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: + +- You can start coding Noir in less than a minute +- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be +- It makes it easy to share work with your frens +- It's fully reusable, you can stop and restart whenever you need to + +:::info + +Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. + +::: + +## Tell me it's _actually_ easy + +It is! + +Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. + + + +8 simple steps: + +#### 1. Create a new repository on GitHub. + +#### 2. Click "Start coding with Codespaces". This will use the default image. + +#### 3. Create a folder called `.devcontainer` in the root of your repository. + +#### 4. Create a Dockerfile in that folder, and paste the following code: + +```docker +FROM --platform=linux/amd64 node:lts-bookworm-slim +SHELL ["/bin/bash", "-c"] +RUN apt update && apt install -y curl bash git tar gzip libc++-dev +RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +ENV PATH="/root/.nargo/bin:$PATH" +RUN noirup +ENTRYPOINT ["nargo"] +``` +#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: + +```json +{ + "name": "Noir on Codespaces", + "build": { + "context": ".", + "dockerfile": "Dockerfile" + }, + "customizations": { + "vscode": { + "extensions": ["noir-lang.vscode-noir"] + } + } +} +``` +#### 6. Commit and push your changes + +This will pull the new image and build it, so it could take a minute or so + +#### 8. Done! +Just wait for the build to finish, and there's your easy Noir environment. + + +Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. + + + +## How do I use it? + +Using the codespace is obviously much easier than setting it up. +Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. + +:::info + +If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. +Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/index.mdx new file mode 100644 index 00000000000..75086ddcdde --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/index.mdx @@ -0,0 +1,67 @@ +--- +title: Noir Lang +hide_title: true +description: + Learn about the public alpha release of Noir, a domain specific language heavily influenced by Rust that compiles to + an intermediate language which can be compiled to an arithmetic circuit or a rank-1 constraint system. +keywords: + [Noir, + Domain Specific Language, + Rust, + Intermediate Language, + Arithmetic Circuit, + Rank-1 Constraint System, + Ethereum Developers, + Protocol Developers, + Blockchain Developers, + Proving System, + Smart Contract Language] +sidebar_position: 0 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +Noir Logo + +Noir is a Domain-Specific Language for SNARK proving systems developed by [Aztec Labs](https://aztec.network/). It allows you to generate complex Zero-Knowledge Programs (ZKP) by using simple and flexible syntax, requiring no previous knowledge on the underlying mathematics or cryptography. + +ZK programs are programs that can generate short proofs of a certain statement without revealing some details about it. You can read more about ZKPs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). + +## What's new about Noir? + +Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. + +:::info + +Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. + +However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. + +::: + +## Who is Noir for? + +Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: + + + + Noir Logo + + Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. + + + Soliditry Verifier Example + Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) + + + Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. + + + + +## Libraries + +Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. +The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. +Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/migration_notes.md new file mode 100644 index 00000000000..6bd740024e5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/migration_notes.md @@ -0,0 +1,105 @@ +--- +title: Migration notes +description: Read about migration notes from previous versions, which could solve problems while updating +keywords: [Noir, notes, migration, updating, upgrading] +--- + +Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. + +### `backend encountered an error: libc++.so.1` + +Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: + +```text +The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" +``` + +Install the `libc++-dev` library with: + +```bash +sudo apt install libc++-dev +``` + +## ≥0.19 + +### Enforcing `compiler_version` + +From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. + +To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. + +## ≥0.14 + +The index of the [for loops](noir/concepts/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: + +```rust +for i in 0..10 { + let i = i as Field; +} +``` + +## ≥v0.11.0 and Nargo backend + +From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: + +### `backend encountered an error` + +This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. + +To fix the issue: + +1. Uninstall the existing backend + +```bash +nargo backend uninstall acvm-backend-barretenberg +``` + +You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. + +2. Reinstall a compatible version of the proving backend. + +If you are using the default barretenberg backend, simply run: + +``` +nargo prove +``` + +with your Noir program. + +This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. + +### `backend encountered an error: illegal instruction` + +On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. + +To fix the issue: + +1. Uninstall the existing backend + +```bash +nargo backend uninstall acvm-backend-barretenberg +``` + +You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. + +2. Reinstall a compatible version of the proving backend. + +If you are using the default barretenberg backend, simply run: + +``` +nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz +``` + +This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. + +The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. + +Then run: + +``` +DESIRED_BINARY_VERSION=0.8.1 nargo info +``` + +This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. + +0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/_category_.json new file mode 100644 index 00000000000..7da08f8a8c5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Concepts", + "position": 0, + "collapsible": true, + "collapsed": true +} \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/assert.md new file mode 100644 index 00000000000..bcff613a695 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/assert.md @@ -0,0 +1,45 @@ +--- +title: Assert Function +description: + Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or + comparison expression that follows to be true, and what happens if the expression is false at + runtime. +keywords: [Noir programming language, assert statement, predicate expression, comparison expression] +sidebar_position: 4 +--- + +Noir includes a special `assert` function which will explicitly constrain the predicate/comparison +expression that follows to be true. If this expression is false at runtime, the program will fail to +be proven. Example: + +```rust +fn main(x : Field, y : Field) { + assert(x == y); +} +``` + +> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. + +You can optionally provide a message to be logged when the assertion fails: + +```rust +assert(x == y, "x and y are not equal"); +``` + +Aside string literals, the optional message can be a format string or any other type supported as input for Noir's [print](../standard_library/logging.md) functions. This feature lets you incorporate runtime variables into your failed assertion logs: + +```rust +assert(x == y, f"Expected x == y, but got {x} == {y}"); +``` + +Using a variable as an assertion message directly: + +```rust +struct myStruct { + myField: Field +} + +let s = myStruct { myField: y }; +assert(s.myField == x, s); +``` + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/comments.md new file mode 100644 index 00000000000..b51a85f5c94 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/comments.md @@ -0,0 +1,33 @@ +--- +title: Comments +description: + Learn how to write comments in Noir programming language. A comment is a line of code that is + ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments + are supported in Noir. +keywords: [Noir programming language, comments, single-line comments, multi-line comments] +sidebar_position: 10 +--- + +A comment is a line in your codebase which the compiler ignores, however it can be read by +programmers. + +Here is a single line comment: + +```rust +// This is a comment and is ignored +``` + +`//` is used to tell the compiler to ignore the rest of the line. + +Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. + +Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. + +```rust +/* + This is a block comment describing a complex function. +*/ +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/control_flow.md new file mode 100644 index 00000000000..4ce65236db3 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/control_flow.md @@ -0,0 +1,45 @@ +--- +title: Control Flow +description: + Learn how to use loops and if expressions in the Noir programming language. Discover the syntax + and examples for for loops and if-else statements. +keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] +sidebar_position: 2 +--- + +## Loops + +Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple +times. + +The following block of code between the braces is run 10 times. + +```rust +for i in 0..10 { + // do something +}; +``` + +The index for loops is of type `u64`. + +## If Expressions + +Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required +for the statement's conditional to be surrounded by parentheses. + +```rust +let a = 0; +let mut x: u32 = 0; + +if a == 0 { + if a != 0 { + x = 6; + } else { + x = 2; + } +} else { + x = 5; + assert(x == 5); +} +assert(x == 2); +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_bus.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_bus.md new file mode 100644 index 00000000000..e54fc861257 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_bus.md @@ -0,0 +1,21 @@ +--- +title: Data Bus +sidebar_position: 13 +--- +**Disclaimer** this feature is experimental, do not use it! + +The data bus is an optimization that the backend can use to make recursion more efficient. +In order to use it, you must define some inputs of the program entry points (usually the `main()` +function) with the `call_data` modifier, and the return values with the `return_data` modifier. +These modifiers are incompatible with `pub` and `mut` modifiers. + +## Example + +```rust +fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { + let a = z[x]; + a+y +} +``` + +As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md new file mode 100644 index 00000000000..a8bd338e736 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md @@ -0,0 +1,251 @@ +--- +title: Arrays +description: + Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. +keywords: + [ + noir, + array type, + methods, + examples, + indexing, + ] +sidebar_position: 4 +--- + +An array is one way of grouping together values into one compound type. Array types can be inferred +or explicitly specified via the syntax `[; ]`: + +```rust +fn main(x : Field, y : Field) { + let my_arr = [x, y]; + let your_arr: [Field; 2] = [x, y]; +} +``` + +Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. + +Array elements can be accessed using indexing: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + + let first = a[0]; + let second = a[1]; +} +``` + +All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group +a `Field` value and a `u8` value together for example. + +You can write mutable arrays, like: + +```rust +fn main() { + let mut arr = [1, 2, 3, 4, 5]; + assert(arr[0] == 1); + + arr[0] = 42; + assert(arr[0] == 42); +} +``` + +You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. + +```rust +let array: [Field; 32] = [0; 32]; +``` + +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: + +```rust +let array: [Field; 32] = [0; 32]; +let sl = array.as_slice() +``` + +You can define multidimensional arrays: + +```rust +let array : [[Field; 2]; 2]; +let element = array[0][0]; +``` +However, multidimensional slices are not supported. For example, the following code will error at compile time: +```rust +let slice : [[Field]] = []; +``` + +## Types + +You can create arrays of primitive types or structs. There is not yet support for nested arrays +(arrays of arrays) or arrays of structs that contain arrays. + +## Methods + +For convenience, the STD provides some ready-to-use, common methods for arrays. +Each of these functions are located within the generic impl `impl [T; N] {`. +So anywhere `self` appears, it refers to the variable `self: [T; N]`. + +### len + +Returns the length of an array + +```rust +fn len(self) -> Field +``` + +example + +```rust +fn main() { + let array = [42, 42]; + assert(array.len() == 2); +} +``` + +### sort + +Returns a new sorted array. The original array remains untouched. Notice that this function will +only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting +logic it uses internally is optimized specifically for these values. If you need a sort function to +sort any type, you should use the function `sort_via` described below. + +```rust +fn sort(self) -> [T; N] +``` + +example + +```rust +fn main() { + let arr = [42, 32]; + let sorted = arr.sort(); + assert(sorted == [32, 42]); +} +``` + +### sort_via + +Sorts the array with a custom comparison function + +```rust +fn sort_via(self, ordering: fn(T, T) -> bool) -> [T; N] +``` + +example + +```rust +fn main() { + let arr = [42, 32] + let sorted_ascending = arr.sort_via(|a, b| a < b); + assert(sorted_ascending == [32, 42]); // verifies + + let sorted_descending = arr.sort_via(|a, b| a > b); + assert(sorted_descending == [32, 42]); // does not verify +} +``` + +### map + +Applies a function to each element of the array, returning a new array containing the mapped elements. + +```rust +fn map(self, f: fn(T) -> U) -> [U; N] +``` + +example + +```rust +let a = [1, 2, 3]; +let b = a.map(|a| a * 2); // b is now [2, 4, 6] +``` + +### fold + +Applies a function to each element of the array, returning the final accumulated value. The first +parameter is the initial value. + +```rust +fn fold(self, mut accumulator: U, f: fn(U, T) -> U) -> U +``` + +This is a left fold, so the given function will be applied to the accumulator and first element of +the array, then the second, and so on. For a given call the expected result would be equivalent to: + +```rust +let a1 = [1]; +let a2 = [1, 2]; +let a3 = [1, 2, 3]; + +let f = |a, b| a - b; +a1.fold(10, f) //=> f(10, 1) +a2.fold(10, f) //=> f(f(10, 1), 2) +a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) +``` + +example: + +```rust + +fn main() { + let arr = [2, 2, 2, 2, 2]; + let folded = arr.fold(0, |a, b| a + b); + assert(folded == 10); +} + +``` + +### reduce + +Same as fold, but uses the first element as starting element. + +```rust +fn reduce(self, f: fn(T, T) -> T) -> T +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 2]; + let reduced = arr.reduce(|a, b| a + b); + assert(reduced == 10); +} +``` + +### all + +Returns true if all the elements satisfy the given predicate + +```rust +fn all(self, predicate: fn(T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 2]; + let all = arr.all(|a| a == 2); + assert(all); +} +``` + +### any + +Returns true if any of the elements satisfy the given predicate + +```rust +fn any(self, predicate: fn(T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 5]; + let any = arr.any(|a| a == 5); + assert(any); +} + +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md new file mode 100644 index 00000000000..69826fcd724 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md @@ -0,0 +1,31 @@ +--- +title: Booleans +description: + Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. +keywords: + [ + noir, + boolean type, + methods, + examples, + logical operations, + ] +sidebar_position: 2 +--- + + +The `bool` type in Noir has two possible values: `true` and `false`: + +```rust +fn main() { + let t = true; + let f: bool = false; +} +``` + +> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for +> `false` in _Verifier.toml_. + +The boolean type is most commonly used in conditionals like `if` expressions and `assert` +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/fields.md new file mode 100644 index 00000000000..99b4aa63549 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/fields.md @@ -0,0 +1,192 @@ +--- +title: Fields +description: + Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. +keywords: + [ + noir, + field type, + methods, + examples, + best practices, + ] +sidebar_position: 0 +--- + +The field type corresponds to the native field type of the proving backend. + +The size of a Noir field depends on the elliptic curve's finite field for the proving backend +adopted. For example, a field would be a 254-bit integer when paired with the default backend that +spans the Grumpkin curve. + +Fields support integer arithmetic and are often used as the default numeric type in Noir: + +```rust +fn main(x : Field, y : Field) { + let z = x + y; +} +``` + +`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new +private value `z` constrained to be equal to `x + y`. + +If proving efficiency is of priority, fields should be used as a default for solving problems. +Smaller integer types (e.g. `u64`) incur extra range constraints. + +## Methods + +After declaring a Field, you can use these common methods on it: + +### to_le_bits + +Transforms the field into an array of bits, Little Endian. + +```rust +fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_le_bits(32); +} +``` + +### to_be_bits + +Transforms the field into an array of bits, Big Endian. + +```rust +fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_be_bits(32); +} +``` + +### to_le_bytes + +Transforms into an array of bytes, Little Endian + +```rust +fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_le_bytes(4); +} +``` + +### to_be_bytes + +Transforms into an array of bytes, Big Endian + +```rust +fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_be_bytes(4); +} +``` + +### to_le_radix + +Decomposes into a vector over the specified base, Little Endian + +```rust +fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_le_radix(256, 4); +} +``` + +### to_be_radix + +Decomposes into a vector over the specified base, Big Endian + +```rust +fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_be_radix(256, 4); +} +``` + +### pow_32 + +Returns the value to the power of the specified exponent + +```rust +fn pow_32(self, exponent: Field) -> Field +``` + +example: + +```rust +fn main() { + let field = 2 + let pow = field.pow_32(4); + assert(pow == 16); +} +``` + +### assert_max_bit_size + +Adds a constraint to specify that the field can be represented with `bit_size` number of bits + +```rust +fn assert_max_bit_size(self, bit_size: u32) +``` + +example: + +```rust +fn main() { + let field = 2 + field.assert_max_bit_size(32); +} +``` + +### sgn0 + +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. + +```rust +fn sgn0(self) -> u1 +``` + + +### lt + +Returns true if the field is less than the other field + +```rust +pub fn lt(self, another: Field) -> bool +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/function_types.md new file mode 100644 index 00000000000..f6121af17e2 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/function_types.md @@ -0,0 +1,26 @@ +--- +title: Function types +sidebar_position: 10 +--- + +Noir supports higher-order functions. The syntax for a function type is as follows: + +```rust +fn(arg1_type, arg2_type, ...) -> return_type +``` + +Example: + +```rust +fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field + assert(f() == 100); +} + +fn main() { + assert_returns_100(|| 100); // ok + assert_returns_100(|| 150); // fails +} +``` + +A function type also has an optional capture environment - this is necessary to support closures. +See [Lambdas](../lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/index.md new file mode 100644 index 00000000000..97b3b2cb094 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/index.md @@ -0,0 +1,110 @@ +--- +title: Data Types +description: + Get a clear understanding of the two categories of Noir data types - primitive types and compound + types. Learn about their characteristics, differences, and how to use them in your Noir + programming. +keywords: + [ + noir, + data types, + primitive types, + compound types, + private types, + public types, + ] +--- + +Every value in Noir has a type, which determines which operations are valid for it. + +All values in Noir are fundamentally composed of `Field` elements. For a more approachable +developing experience, abstractions are added on top to introduce different data types in Noir. + +Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound +types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or +public. + +## Private & Public Types + +A **private value** is known only to the Prover, while a **public value** is known by both the +Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All +primitive types (including individual fields of compound types) in Noir are private by default, and +can be marked public when certain values are intended to be revealed to the Verifier. + +> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once +> the proofs are verified on-chain the values can be considered known to everyone that has access to +> that blockchain. + +Public data types are treated no differently to private types apart from the fact that their values +will be revealed in proofs generated. Simply changing the value of a public type will not change the +circuit (where the same goes for changing values of private types as well). + +_Private values_ are also referred to as _witnesses_ sometimes. + +> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different +> meaning than when applied to a function (e.g. `pub fn foo() {}`). +> +> The former is a visibility modifier for the Prover to interpret if a value should be made known to +> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a +> function should be made accessible to external Noir programs like in other languages. + +### pub Modifier + +All data types in Noir are private by default. Types are explicitly declared as public using the +`pub` modifier: + +```rust +fn main(x : Field, y : pub Field) -> pub Field { + x + y +} +``` + +In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note +that visibility is handled **per variable**, so it is perfectly valid to have one input that is +private and another that is public. + +> **Note:** Public types can only be declared through parameters on `main`. + +## Type Aliases + +A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: + +```rust +type Id = u8; + +fn main() { + let id: Id = 1; + let zero: u8 = 0; + assert(zero + 1 == id); +} +``` + +Type aliases can also be used with [generics](@site/docs/noir/concepts/generics.md): + +```rust +type Id = Size; + +fn main() { + let id: Id = 1; + let zero: u32 = 0; + assert(zero + 1 == id); +} +``` + +Type aliases can even refer to other aliases. An error will be issued if they form a cycle: + +```rust +// Ok! +type A = B; +type B = Field; + +type Bad1 = Bad2; + +// error: Dependency cycle found +type Bad2 = Bad1; +// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 +``` + +### BigInt + +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/integers.md new file mode 100644 index 00000000000..4d58d96fed5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/integers.md @@ -0,0 +1,155 @@ +--- +title: Integers +description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. +keywords: [noir, integer types, methods, examples, arithmetic] +sidebar_position: 1 +--- + +An integer type is a range constrained field type. The Noir frontend supports both unsigned and signed integer types. The allowed sizes are 1, 8, 32 and 64 bits. + +:::info + +When an integer is defined in Noir without a specific type, it will default to `Field`. + +The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. + +::: + +## Unsigned Integers + +An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): + +```rust +fn main() { + let x: u8 = 1; + let y: u8 = 1; + let z = x + y; + assert (z == 2); +} +``` + +The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). + +## Signed Integers + +A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): + +```rust +fn main() { + let x: i8 = -1; + let y: i8 = -1; + let z = x + y; + assert (z == -2); +} +``` + +The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). + +## 128 bits Unsigned Integers + +The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: +- You cannot cast between a native integer and `U128` +- There is a higher performance cost when using `U128`, compared to a native type. + +Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. + +```rust +fn main() { + let x = U128::from_integer(23); + let y = U128::from_hex("0x7"); + let z = x + y; + assert(z.to_integer() == 30); +} +``` + +`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. +You can construct a U128 from its limbs: +```rust +fn main(x: u64, y: u64) { + let x = U128::from_u64s_be(x,y); + assert(z.hi == x as Field); + assert(z.lo == y as Field); +} +``` + +Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. +Apart from this, most operations will work as usual: + +```rust +fn main(x: U128, y: U128) { + // multiplication + let c = x * y; + // addition and subtraction + let c = c - x + y; + // division + let c = x / y; + // bit operation; + let c = x & y | y; + // bit shift + let c = x << y; + // comparisons; + let c = x < y; + let c = x == y; +} +``` + +## Overflows + +Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: + +```rust +fn main(x: u8, y: u8) { + let z = x + y; +} +``` + +With: + +```toml +x = "255" +y = "1" +``` + +Would result in: + +``` +$ nargo prove +error: Assertion failed: 'attempt to add with overflow' +┌─ ~/src/main.nr:9:13 +│ +│ let z = x + y; +│ ----- +│ += Call stack: + ... +``` + +A similar error would happen with signed integers: + +```rust +fn main() { + let x: i8 = -118; + let y: i8 = -11; + let z = x + y; +} +``` + +### Wrapping methods + +Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: + +```rust +fn wrapping_add(x: T, y: T) -> T; +fn wrapping_sub(x: T, y: T) -> T; +fn wrapping_mul(x: T, y: T) -> T; +``` + +Example of how it is used: + +```rust +use dep::std; + +fn main(x: u8, y: u8) -> pub u8 { + std::wrapping_add(x, y) +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/references.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/references.md new file mode 100644 index 00000000000..a5293d11cfb --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/references.md @@ -0,0 +1,23 @@ +--- +title: References +sidebar_position: 9 +--- + +Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. + +Example: + +```rust +fn main() { + let mut x = 2; + + // you can reference x as &mut and pass it to multiplyBy2 + multiplyBy2(&mut x); +} + +// you can access &mut here +fn multiplyBy2(x: &mut Field) { + // and dereference it with * + *x = *x * 2; +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/slices.mdx new file mode 100644 index 00000000000..4a6ee816aa2 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/slices.mdx @@ -0,0 +1,147 @@ +--- +title: Slices +description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. +keywords: [noir, slice type, methods, examples, subarrays] +sidebar_position: 5 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. + +```rust +use dep::std::slice; + +fn main() -> pub Field { + let mut slice: [Field] = [0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +View the corresponding test file [here][test-file]. + +[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr + +## Methods + +For convenience, the STD provides some ready-to-use, common methods for slices: + +### push_back + +Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. + +```rust +fn push_back(_self: [T], _elem: T) -> [T] +``` + +example: + +```rust +fn main() -> pub Field { + let mut slice: [Field] = [0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +View the corresponding test file [here][test-file]. + +### push_front + +Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. + +```rust +fn push_front(_self: Self, _elem: T) -> Self +``` + +Example: + +```rust +let mut new_slice: [Field] = []; +new_slice = new_slice.push_front(20); +assert(new_slice[0] == 20); // returns true +``` + +View the corresponding test file [here][test-file]. + +### pop_front + +Returns a tuple of two items, the first element of the array and the rest of the array. + +```rust +fn pop_front(_self: Self) -> (T, Self) +``` + +Example: + +```rust +let (first_elem, rest_of_slice) = slice.pop_front(); +``` + +View the corresponding test file [here][test-file]. + +### pop_back + +Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. + +```rust +fn pop_back(_self: Self) -> (Self, T) +``` + +Example: + +```rust +let (popped_slice, last_elem) = slice.pop_back(); +``` + +View the corresponding test file [here][test-file]. + +### append + +Loops over a slice and adds it to the end of another. + +```rust +fn append(mut self, other: Self) -> Self +``` + +Example: + +```rust +let append = [1, 2].append([3, 4, 5]); +``` + +### insert + +Inserts an element at a specified index and shifts all following elements by 1. + +```rust +fn insert(_self: Self, _index: Field, _elem: T) -> Self +``` + +Example: + +```rust +new_slice = rest_of_slice.insert(2, 100); +assert(new_slice[2] == 100); +``` + +View the corresponding test file [here][test-file]. + +### remove + +Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. + +```rust +fn remove(_self: Self, _index: Field) -> (Self, T) +``` + +Example: + +```rust +let (remove_slice, removed_elem) = slice.remove(3); +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md new file mode 100644 index 00000000000..311dfd64416 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md @@ -0,0 +1,80 @@ +--- +title: Strings +description: + Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. +keywords: + [ + noir, + string type, + methods, + examples, + concatenation, + ] +sidebar_position: 3 +--- + + +The string type is a fixed length value defined with `str`. + +You can use strings in `assert()` functions or print them with +`println()`. See more about [Logging](../../standard_library/logging). + +```rust +use dep::std; + +fn main(message : pub str<11>, hex_as_string : str<4>) { + println(message); + assert(message == "hello world"); + assert(hex_as_string == "0x41"); +} +``` + +You can convert a `str` to a byte array by calling `as_bytes()` +or a vector by calling `as_bytes_vec()`. + +```rust +fn main() { + let message = "hello world"; + let message_bytes = message.as_bytes(); + let mut message_vec = message.as_bytes_vec(); + assert(message_bytes.len() == 11); + assert(message_bytes[0] == 104); + assert(message_bytes[0] == message_vec.get(0)); +} +``` + +## Escape characters + +You can use escape characters for your strings: + +| Escape Sequence | Description | +|-----------------|-----------------| +| `\r` | Carriage Return | +| `\n` | Newline | +| `\t` | Tab | +| `\0` | Null Character | +| `\"` | Double Quote | +| `\\` | Backslash | + +Example: + +```rust +let s = "Hello \"world" // prints "Hello "world" +let s = "hey \tyou"; // prints "hey you" +``` + +## Raw strings + +A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. + +Escape characters are *not* processed within raw strings. All contents are interpreted literally. + +Example: + +```rust +let s = r"Hello world"; +let s = r#"Simon says "hello world""#; + +// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes +let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/structs.md new file mode 100644 index 00000000000..dbf68c99813 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/structs.md @@ -0,0 +1,70 @@ +--- +title: Structs +description: + Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. +keywords: + [ + noir, + struct type, + methods, + examples, + data structures, + ] +sidebar_position: 8 +--- + +A struct also allows for grouping multiple values of different types. Unlike tuples, we can also +name each field. + +> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the +> field type of Noir. + +Defining a struct requires giving it a name and listing each field within as `: ` pairs: + +```rust +struct Animal { + hands: Field, + legs: Field, + eyes: u8, +} +``` + +An instance of a struct can then be created with actual values in `: ` pairs in any +order. Struct fields are accessible using their given names: + +```rust +fn main() { + let legs = 4; + + let dog = Animal { + eyes: 2, + hands: 0, + legs, + }; + + let zero = dog.hands; +} +``` + +Structs can also be destructured in a pattern, binding each field to a new variable: + +```rust +fn main() { + let Animal { hands, legs: feet, eyes } = get_octopus(); + + let ten = hands + feet + eyes as u8; +} + +fn get_octopus() -> Animal { + let octopus = Animal { + hands: 0, + legs: 8, + eyes: 2, + }; + + octopus +} +``` + +The new variables can be bound with names different from the original struct field names, as +showcased in the `legs --> feet` binding in the example above. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/tuples.md new file mode 100644 index 00000000000..2ec5c9c4113 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/tuples.md @@ -0,0 +1,48 @@ +--- +title: Tuples +description: + Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. +keywords: + [ + noir, + tuple type, + methods, + examples, + multi-value containers, + ] +sidebar_position: 7 +--- + +A tuple collects multiple values like an array, but with the added ability to collect values of +different types: + +```rust +fn main() { + let tup: (u8, u64, Field) = (255, 500, 1000); +} +``` + +One way to access tuple elements is via destructuring using pattern matching: + +```rust +fn main() { + let tup = (1, 2); + + let (one, two) = tup; + + let three = one + two; +} +``` + +Another way to access tuple elements is via direct member access, using a period (`.`) followed by +the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to +the second and so on: + +```rust +fn main() { + let tup = (5, 6, 7, 8); + + let five = tup.0; + let eight = tup.3; +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/distinct.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/distinct.md new file mode 100644 index 00000000000..6c993b8b5e0 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/distinct.md @@ -0,0 +1,64 @@ +--- +title: Distinct Witnesses +sidebar_position: 11 +--- + +The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures +that the witnesses being returned as public inputs are all unique. + +The `distinct` keyword is only used for return values on program entry points (usually the `main()` +function). + +When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. + +You can read more about the problem this solves +[here](https://github.com/noir-lang/noir/issues/1183). + +## Example + +Without the `distinct` keyword, the following program + +```rust +fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { + let a = 1; + let b = 1; + [x + 1, y, a, b] +} +``` + +compiles to + +```json +{ + //... + "abi": { + //... + "param_witnesses": { "x": [1], "y": [2] }, + "return_witnesses": [3, 2, 4, 4] + } +} +``` + +Whereas (with the `distinct` keyword) + +```rust +fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { + let a = 1; + let b = 1; + [x + 1, y, a, b] +} +``` + +compiles to + +```json +{ + //... + "abi": { + //... + "param_witnesses": { "x": [1], "y": [2] }, + //... + "return_witnesses": [3, 4, 5, 6] + } +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/functions.md new file mode 100644 index 00000000000..48aba9cd058 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/functions.md @@ -0,0 +1,226 @@ +--- +title: Functions +description: + Learn how to declare functions and methods in Noir, a programming language with Rust semantics. + This guide covers parameter declaration, return types, call expressions, and more. +keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] +sidebar_position: 1 +--- + +Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. + +To declare a function the `fn` keyword is used. + +```rust +fn foo() {} +``` + +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: + +```rust +pub fn foo() {} +``` + +You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: + +```rust +pub(crate) fn foo() {} //foo can only be called within its crate +``` + +All parameters in a function must have a type and all types are known at compile time. The parameter +is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. + +```rust +fn foo(x : Field, y : Field){} +``` + +The return type of a function can be stated by using the `->` arrow notation. The function below +states that the foo function must return a `Field`. If the function returns no value, then the arrow +is omitted. + +```rust +fn foo(x : Field, y : Field) -> Field { + x + y +} +``` + +Note that a `return` keyword is unneeded in this case - the last expression in a function's body is +returned. + +## Main function + +If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: + +```rust +fn main(x : Field) // this is fine: passing a Field +fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time +fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 +fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 + +fn main(x : Vec) // can't compile, has variable size +fn main(x : [Field]) // can't compile, has variable size +fn main(....// i think you got it by now +``` + +Keep in mind [tests](../../getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: + +```rust +fn main(x : [Field]) { + assert(x[0] == 1); +} + +#[test] +fn test_one() { + main([1, 2]); +} +``` + +```bash +$ nargo test +[testing] Running 1 test functions +[testing] Testing test_one... ok +[testing] All tests passed + +$ nargo check +The application panicked (crashed). +Message: Cannot have variable sized arrays as a parameter to main +``` + +## Call Expressions + +Calling a function in Noir is executed by using the function name and passing in the necessary +arguments. + +Below we show how to call the `foo` function from the `main` function using a call expression: + +```rust +fn main(x : Field, y : Field) { + let z = foo(x); +} + +fn foo(x : Field) -> Field { + x + x +} +``` + +## Methods + +You can define methods in Noir on any struct type in scope. + +```rust +struct MyStruct { + foo: Field, + bar: Field, +} + +impl MyStruct { + fn new(foo: Field) -> MyStruct { + MyStruct { + foo, + bar: 2, + } + } + + fn sum(self) -> Field { + self.foo + self.bar + } +} + +fn main() { + let s = MyStruct::new(40); + assert(s.sum() == 42); +} +``` + +Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as +follows: + +```rust +assert(MyStruct::sum(s) == 42); +``` + +It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: + +```rust +struct Foo {} + +impl Foo { + fn foo(self) -> Field { 1 } +} + +impl Foo { + fn foo(self) -> Field { 2 } +} + +fn main() { + let f1: Foo = Foo{}; + let f2: Foo = Foo{}; + assert(f1.foo() + f2.foo() == 3); +} +``` + +Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. + +```rust +// Including this impl in the same project as the above snippet would +// cause an overlapping impls error +impl Foo { + fn foo(self) -> Field { 3 } +} +``` + +## Lambdas + +Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +See [Lambdas](./lambdas.md) for more details. + +## Attributes + +Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. + +Supported attributes include: + +- **builtin**: the function is implemented by the compiler, for efficiency purposes. +- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` +- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. +- **test**: mark the function as unit tests. See [Tests](../../getting_started/tooling/testing.md) for more details + +### Field Attribute + +The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. +The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. +As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. + +Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. + +```rust +#[field(bn254)] +fn foo() -> u32 { + 1 +} + +#[field(23)] +fn foo() -> u32 { + 2 +} + +// This commented code would not compile as foo would be defined twice because it is the same field as bn254 +// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] +// fn foo() -> u32 { +// 2 +// } + +#[field(bls12_381)] +fn foo() -> u32 { + 3 +} +``` + +If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md new file mode 100644 index 00000000000..ddd42bf1f9b --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md @@ -0,0 +1,106 @@ +--- +title: Generics +description: Learn how to use Generics in Noir +keywords: [Noir, Rust, generics, functions, structs] +sidebar_position: 7 +--- + +Generics allow you to use the same functions with multiple different concrete data types. You can +read more about the concept of generics in the Rust documentation +[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). + +Here is a trivial example showing the identity function that supports any type. In Rust, it is +common to refer to the most general type as `T`. We follow the same convention in Noir. + +```rust +fn id(x: T) -> T { + x +} +``` + +## In Structs + +Generics are useful for specifying types in structs. For example, we can specify that a field in a +struct will be of a certain generic type. In this case `value` is of type `T`. + +```rust +struct RepeatedValue { + value: T, + count: Field, +} + +impl RepeatedValue { + fn print(self) { + for _i in 0 .. self.count { + println(self.value); + } + } +} + +fn main() { + let repeated = RepeatedValue { value: "Hello!", count: 2 }; + repeated.print(); +} +``` + +The `print` function will print `Hello!` an arbitrary number of times, twice in this case. + +If we want to be generic over array lengths (which are type-level integers), we can use numeric +generics. Using these looks just like using regular generics, but these generics can resolve to +integers at compile-time, rather than resolving to types. Here's an example of a struct that is +generic over the size of the array it contains internally: + +```rust +struct BigInt { + limbs: [u32; N], +} + +impl BigInt { + // `N` is in scope of all methods in the impl + fn first(first: BigInt, second: BigInt) -> Self { + assert(first.limbs != second.limbs); + first + + fn second(first: BigInt, second: Self) -> Self { + assert(first.limbs != second.limbs); + second + } +} +``` + +## Calling functions on generic parameters + +Since a generic type `T` can represent any type, how can we call functions on the underlying type? +In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" + +This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +any type `T` that implements the `Eq` trait for equality: + +```rust +fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool + where T: Eq +{ + if (array1.len() == 0) | (array2.len() == 0) { + true + } else { + array1[0] == array2[0] + } +} + +fn main() { + assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); + + // We can use first_element_is_equal for arrays of any type + // as long as we have an Eq impl for the types we pass in + let array = [MyStruct::new(), MyStruct::new()]; + assert(array_eq(array, array, MyStruct::eq)); +} + +impl Eq for MyStruct { + fn eq(self, other: MyStruct) -> bool { + self.foo == other.foo + } +} +``` + +You can find more details on traits and trait implementations on the [traits page](../concepts/traits). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/globals.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/globals.md new file mode 100644 index 00000000000..063a3d89248 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/globals.md @@ -0,0 +1,72 @@ +--- +title: Global Variables +description: + Learn about global variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, globals, global variables, constants] +sidebar_position: 8 +--- + +## Globals + + +Noir supports global variables. The global's type can be inferred by the compiler entirely: + +```rust +global N = 5; // Same as `global N: Field = 5` + +global TUPLE = (3, 2); + +fn main() { + assert(N == 5); + assert(N == TUPLE.0 + TUPLE.1); +} +``` + +:::info + +Globals can be defined as any expression, so long as they don't depend on themselves - otherwise there would be a dependency cycle! For example: + +```rust +global T = foo(T); // dependency error +``` + +::: + + +If they are initialized to a literal integer, globals can be used to specify an array's length: + +```rust +global N: Field = 2; + +fn main(y : [Field; N]) { + assert(y[0] == y[1]) +} +``` + +A global from another module can be imported or referenced externally like any other name: + +```rust +global N = 20; + +fn main() { + assert(my_submodule::N != N); +} + +mod my_submodule { + global N: Field = 10; +} +``` + +When a global is used, Noir replaces the name with its definition on each occurrence. +This means globals defined using function calls will repeat the call each time they're used: + +```rust +global RESULT = foo(); + +fn foo() -> [Field; 100] { ... } +``` + +This is usually fine since Noir will generally optimize any function call that does not +refer to a program input into a constant. It should be kept in mind however, if the called +function performs side-effects like `println`, as these will still occur on each use. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/lambdas.md new file mode 100644 index 00000000000..be3c7e0b5ca --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/lambdas.md @@ -0,0 +1,81 @@ +--- +title: Lambdas +description: Learn how to use anonymous functions in Noir programming language. +keywords: [Noir programming language, lambda, closure, function, anonymous function] +sidebar_position: 9 +--- + +## Introduction + +Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +A block can be used as the body of a lambda, allowing you to declare local variables inside it: + +```rust +let cool = || { + let x = 100; + let y = 100; + x + y +} + +assert(cool() == 200); +``` + +## Closures + +Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: + +```rust +fn main() { + let x = 100; + let closure = || x + 150; + assert(closure() == 250); +} +``` + +## Passing closures to higher-order functions + +It may catch you by surprise that the following code fails to compile: + +```rust +fn foo(f: fn () -> Field) -> Field { + f() +} + +fn main() { + let (x, y) = (50, 50); + assert(foo(|| x + y) == 100); // error :( +} +``` + +The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` +expects a regular function as an argument - those are incompatible. +:::note + +Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. + +E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. + +::: +The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - +in this example that's `(Field, Field)`. + +The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called +with closures with any environment, as well as with regular functions: + +```rust +fn foo(f: fn[Env]() -> Field) -> Field { + f() +} + +fn main() { + let (x, y) = (50, 50); + assert(foo(|| x + y) == 100); // compiles fine + assert(foo(|| 60) == 60); // compiles fine +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/mutability.md new file mode 100644 index 00000000000..fdeef6a87c5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/mutability.md @@ -0,0 +1,121 @@ +--- +title: Mutability +description: + Learn about mutable variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, mutability in noir, mutable variables] +sidebar_position: 8 +--- + +Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned +to via an assignment expression. + +```rust +let x = 2; +x = 3; // error: x must be mutable to be assigned to + +let mut y = 3; +let y = 4; // OK +``` + +The `mut` modifier can also apply to patterns: + +```rust +let (a, mut b) = (1, 2); +a = 11; // error: a must be mutable to be assigned to +b = 12; // OK + +let mut (c, d) = (3, 4); +c = 13; // OK +d = 14; // OK + +// etc. +let MyStruct { x: mut y } = MyStruct { x: a }; +// y is now in scope +``` + +Note that mutability in noir is local and everything is passed by value, so if a called function +mutates its parameters then the parent function will keep the old value of the parameters. + +```rust +fn main() -> pub Field { + let x = 3; + helper(x); + x // x is still 3 +} + +fn helper(mut x: i32) { + x = 4; +} +``` + +## Non-local mutability + +Non-local mutability can be achieved through the mutable reference type `&mut T`: + +```rust +fn set_to_zero(x: &mut Field) { + *x = 0; +} + +fn main() { + let mut y = 42; + set_to_zero(&mut y); + assert(*y == 0); +} +``` + +When creating a mutable reference, the original variable being referred to (`y` in this +example) must also be mutable. Since mutable references are a reference type, they must +be explicitly dereferenced via `*` to retrieve the underlying value. Note that this yields +a copy of the value, so mutating this copy will not change the original value behind the +reference: + +```rust +fn main() { + let mut x = 1; + let x_ref = &mut x; + + let mut y = *x_ref; + let y_ref = &mut y; + + x = 2; + *x_ref = 3; + + y = 4; + *y_ref = 5; + + assert(x == 3); + assert(*x_ref == 3); + assert(y == 5); + assert(*y_ref == 5); +} +``` + +Note that types in Noir are actually deeply immutable so the copy that occurs when +dereferencing is only a conceptual copy - no additional constraints will occur. + +Mutable references can also be stored within structs. Note that there is also +no lifetime parameter on these unlike rust. This is because the allocated memory +always lasts the entire program - as if it were an array of one element. + +```rust +struct Foo { + x: &mut Field +} + +impl Foo { + fn incr(mut self) { + *self.x += 1; + } +} + +fn main() { + let foo = Foo { x: &mut 0 }; + foo.incr(); + assert(*foo.x == 1); +} +``` + +In general, you should avoid non-local & shared mutability unless it is needed. Sticking +to only local mutability will improve readability and potentially improve compiler optimizations as well. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/ops.md new file mode 100644 index 00000000000..60425cb8994 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/ops.md @@ -0,0 +1,98 @@ +--- +title: Logical Operations +description: + Learn about the supported arithmetic and logical operations in the Noir programming language. + Discover how to perform operations on private input types, integers, and booleans. +keywords: + [ + Noir programming language, + supported operations, + arithmetic operations, + logical operations, + predicate operators, + bitwise operations, + short-circuiting, + backend, + ] +sidebar_position: 3 +--- + +# Operations + +## Table of Supported Operations + +| Operation | Description | Requirements | +| :-------- | :------------------------------------------------------------: | -------------------------------------: | +| + | Adds two private input types together | Types must be private input | +| - | Subtracts two private input types together | Types must be private input | +| \* | Multiplies two private input types together | Types must be private input | +| / | Divides two private input types together | Types must be private input | +| ^ | XOR two private input types together | Types must be integer | +| & | AND two private input types together | Types must be integer | +| \| | OR two private input types together | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | +| >> | Right shift an integer by another integer amount | Types must be integer | +| ! | Bitwise not of a value | Type must be integer or boolean | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | +| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | +| == | returns a bool if one value is equal to the other | Both types must not be constants | +| != | returns a bool if one value is not equal to the other | Both types must not be constants | + +### Predicate Operators + +`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. +This differs from the operations such as `+` where the operands are used in _computation_. + +### Bitwise Operations Example + +```rust +fn main(x : Field) { + let y = x as u32; + let z = y & y; +} +``` + +`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise +`&`. + +> `x & x` would not compile as `x` is a `Field` and not an integer type. + +### Logical Operators + +Noir has no support for the logical operators `||` and `&&`. This is because encoding the +short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can +use the bitwise operators `|` and `&` which operate identically for booleans, just without the +short-circuiting. + +```rust +let my_val = 5; + +let mut flag = 1; +if (my_val > 6) | (my_val == 0) { + flag = 0; +} +assert(flag == 1); + +if (my_val != 10) & (my_val < 50) { + flag = 0; +} +assert(flag == 0); +``` + +### Shorthand operators + +Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: + +```rust +let mut i = 0; +i = i + 1; +``` + +could be written as: + +```rust +let mut i = 0; +i += 1; +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/oracles.md new file mode 100644 index 00000000000..2e6a6818d48 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/oracles.md @@ -0,0 +1,23 @@ +--- +title: Oracles +description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. +keywords: + - Noir + - Oracles + - RPC Calls + - Unconstrained Functions + - Programming + - Blockchain +sidebar_position: 6 +--- + +Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. + +Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) + +You can declare an Oracle through the `#[oracle()]` flag. Example: + +```rust +#[oracle(get_number_sequence)] +unconstrained fn get_number_sequence(_size: Field) -> [Field] {} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/shadowing.md new file mode 100644 index 00000000000..5ce6130d201 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/shadowing.md @@ -0,0 +1,44 @@ +--- +title: Shadowing +sidebar_position: 12 +--- + +Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. + +For example, the following function is valid in Noir: + +```rust +fn main() { + let x = 5; + + { + let x = x * 2; + assert (x == 10); + } + + assert (x == 5); +} +``` + +In this example, a variable x is first defined with the value 5. + +The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. + +When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. + +## Temporal mutability + +One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. + +```rust +fn main() { + let age = 30; + // age = age + 5; // Would error as `age` is immutable by default. + + let mut age = age + 5; // Temporarily mutates `age` with a new value. + + let age = age; // Locks `age`'s mutability again. + + assert (age == 35); +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/traits.md new file mode 100644 index 00000000000..ef1445a5907 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/traits.md @@ -0,0 +1,389 @@ +--- +title: Traits +description: + Traits in Noir can be used to abstract out a common interface for functions across + several data types. +keywords: [noir programming language, traits, interfaces, generic, protocol] +sidebar_position: 14 +--- + +## Overview + +Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines +the interface of several methods contained within the trait. Types can then implement this trait by providing +implementations for these methods. For example in the program: + +```rust +struct Rectangle { + width: Field, + height: Field, +} + +impl Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +fn log_area(r: Rectangle) { + println(r.area()); +} +``` + +We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this +function to work on `Triangle`s as well?: + +```rust +struct Triangle { + width: Field, + height: Field, +} + +impl Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can +introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: + +```rust +trait Area { + fn area(self) -> Field; +} + +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing +impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined +by the `Area` trait. + +```rust +impl Area for Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +impl Area for Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Now we have a working program that is generic over any type of Shape that is used! Others can even use this program +as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. + +## Where Clauses + +As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements +a trait, we can add a where clause to the generic function. + +```rust +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` +operator. Similarly, we can have multiple trait constraints by separating each with a comma: + +```rust +fn foo(elements: [T], thing: U) where + T: Default + Add + Eq, + U: Bar, +{ + let mut sum = T::default(); + + for element in elements { + sum += element; + } + + if sum == T::default() { + thing.bar(); + } +} +``` + +## Generic Implementations + +You can add generics to a trait implementation by adding the generic list after the `impl` keyword: + +```rust +trait Second { + fn second(self) -> Field; +} + +impl Second for (T, Field) { + fn second(self) -> Field { + self.1 + } +} +``` + +You can also implement a trait for every type this way: + +```rust +trait Debug { + fn debug(self); +} + +impl Debug for T { + fn debug(self) { + println(self); + } +} + +fn main() { + 1.debug(); +} +``` + +### Generic Trait Implementations With Where Clauses + +Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. +For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` +will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. +For example, here is the implementation for array equality: + +```rust +impl Eq for [T; N] where T: Eq { + // Test if two arrays have the same elements. + // Because both arrays must have length N, we know their lengths already match. + fn eq(self, other: Self) -> bool { + let mut result = true; + + for i in 0 .. self.len() { + // The T: Eq constraint is needed to call == on the array elements here + result &= self[i] == other[i]; + } + + result + } +} +``` + +## Generic Traits + +Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in +scope of every item within the trait. + +```rust +trait Into { + // Convert `self` to type `T` + fn into(self) -> T; +} +``` + +When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime +when referencing a generic trait (e.g. in a `where` clause). + +```rust +struct MyStruct { + array: [Field; 2], +} + +impl Into<[Field; 2]> for MyStruct { + fn into(self) -> [Field; 2] { + self.array + } +} + +fn as_array(x: T) -> [Field; 2] + where T: Into<[Field; 2]> +{ + x.into() +} + +fn main() { + let array = [1, 2]; + let my_struct = MyStruct { array }; + + assert_eq(as_array(my_struct), array); +} +``` + +## Trait Methods With No `self` + +A trait can contain any number of methods, each of which have access to the `Self` type which represents each type +that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. +For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type +but doesn't need to take any parameters: + +```rust +trait Default { + fn default() -> Self; +} +``` + +Implementing this trait can be done similarly to any other trait: + +```rust +impl Default for Field { + fn default() -> Field { + 0 + } +} + +struct MyType {} + +impl Default for MyType { + fn default() -> Field { + MyType {} + } +} +``` + +However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. +Instead, we'll need to refer to the function directly. This can be done either by referring to the +specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later +case, type inference determines the impl that is selected. + +```rust +let my_struct = MyStruct::default(); + +let x: Field = Default::default(); +let result = x + Default::default(); +``` + +:::warning + +```rust +let _ = Default::default(); +``` + +If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be +arbitrarily selected. This occurs most often when the result of a trait function call with no parameters +is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, +always refer to it via the implementation type's namespace - e.g. `MyType::default()`. +This is set to change to an error in future Noir versions. + +::: + +## Default Method Implementations + +A trait can also have default implementations of its methods by giving a body to the desired functions. +Note that this body must be valid for all types that may implement the trait. As a result, the only +valid operations on `self` will be operations valid for any type or other operations on the trait itself. + +```rust +trait Numeric { + fn add(self, other: Self) -> Self; + + // Default implementation of double is (self + self) + fn double(self) -> Self { + self.add(self) + } +} +``` + +When implementing a trait with default functions, a type may choose to implement only the required functions: + +```rust +impl Numeric for Field { + fn add(self, other: Field) -> Field { + self + other + } +} +``` + +Or it may implement the optional methods as well: + +```rust +impl Numeric for u32 { + fn add(self, other: u32) -> u32 { + self + other + } + + fn double(self) -> u32 { + self * 2 + } +} +``` + +## Impl Specialization + +When implementing traits for a generic type it is possible to implement the trait for only a certain combination +of generics. This can be either as an optimization or because those specific generics are required to implement the trait. + +```rust +trait Sub { + fn sub(self, other: Self) -> Self; +} + +struct NonZero { + value: T, +} + +impl Sub for NonZero { + fn sub(self, other: Self) -> Self { + let value = self.value - other.value; + assert(value != 0); + NonZero { value } + } +} +``` + +## Overlapping Implementations + +Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. +This means if a trait `Foo` is already implemented +by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other +type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create +any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given +method call. + +```rust +trait Trait {} + +// Previous impl defined here +impl Trait for (A, B) {} + +// error: Impl for type `(Field, Field)` overlaps with existing impl +impl Trait for (Field, Field) {} +``` + +## Trait Coherence + +Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create +impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same +program. + +The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared +in the crate the impl is in. + +In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does +not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. +While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its +own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the +library your choices are to either submit a patch to the library or use the newtype pattern. + +### The Newtype Pattern + +The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type +that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create +impls for any trait we need on it. + +```rust +struct Wrapper { + foo: dep::some_library::Foo, +} + +impl Default for Wrapper { + fn default() -> Wrapper { + Wrapper { + foo: dep::some_library::Foo::new(), + } + } +} +``` + +Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated +to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and +unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/unconstrained.md new file mode 100644 index 00000000000..89d12c1c971 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/unconstrained.md @@ -0,0 +1,95 @@ +--- +title: Unconstrained Functions +description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." + +keywords: [Noir programming language, unconstrained, open] +sidebar_position: 5 +--- + +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. + +## Why? + +Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. + +Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. + +Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. + +A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. + +## Example + +An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. + +Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. + +```rust +fn main(num: u72) -> pub [u8; 8] { + let mut out: [u8; 8] = [0; 8]; + for i in 0..8 { + out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; + } + + out +} +``` + +``` +Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 +Backend circuit size: 3619 +``` + +A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the AND against 0xff. This saves us ~480 gates in total. + +```rust +fn main(num: u72) -> pub [u8; 8] { + let mut out: [u8; 8] = [0; 8]; + for i in 0..8 { + out[i] = (num >> (56 - (i * 8)) as u8; + } + + out +} +``` + +``` +Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 +Backend circuit size: 3143 +``` + +Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. + +It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. + +We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: + +```rust +fn main(num: u72) -> pub [u8; 8] { + let out = u72_to_u8(num); + + let mut reconstructed_num: u72 = 0; + for i in 0..8 { + reconstructed_num += (out[i] as u72 << (56 - (8 * i))); + } + assert(num == reconstructed_num); + out +} + +unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { + let mut out: [u8; 8] = [0; 8]; + for i in 0..8 { + out[i] = (num >> (56 - (i * 8))) as u8; + } + out +} +``` + +``` +Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 +Backend circuit size: 2902 +``` + +This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). + +Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/_category_.json new file mode 100644 index 00000000000..1debcfe7675 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Modules, Packages and Crates", + "position": 2, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/crates_and_packages.md new file mode 100644 index 00000000000..95ee9f52ab2 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/crates_and_packages.md @@ -0,0 +1,43 @@ +--- +title: Crates and Packages +description: Learn how to use Crates and Packages in your Noir project +keywords: [Nargo, dependencies, package management, crates, package] +sidebar_position: 0 +--- + +## Crates + +A crate is the smallest amount of code that the Noir compiler considers at a time. +Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. + +### Crate Types + +A Noir crate can come in several forms: binaries, libraries or contracts. + +#### Binaries + +_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. + +#### Libraries + +_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. + +#### Contracts + +Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). + +### Crate Root + +Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. + +## Packages + +A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. + +A package _must_ contain either a library or a binary crate, but not both. + +### Differences from Cargo Packages + +One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. + +In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md new file mode 100644 index 00000000000..04c1703d929 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md @@ -0,0 +1,124 @@ +--- +title: Dependencies +description: + Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub + and use them easily in your project. +keywords: [Nargo, dependencies, GitHub, package management, versioning] +sidebar_position: 1 +--- + +Nargo allows you to upload packages to GitHub and use them as dependencies. + +## Specifying a dependency + +Specifying a dependency requires a tag to a specific commit and the git url to the url containing +the package. + +Currently, there are no requirements on the tag contents. If requirements are added, it would follow +semver 2.0 guidelines. + +> Note: Without a `tag` , there would be no versioning and dependencies would change each time you +> compile your project. + +For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: + +```toml +# Nargo.toml + +[dependencies] +ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} +``` + +If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: + +```toml +# Nargo.toml + +[dependencies] +easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "noir-contracts/contracts/easy_private_token_contract"} +``` + +## Specifying a local dependency + +You can also specify dependencies that are local to your machine. + +For example, this file structure has a library and binary crate + +```tree +├── binary_crate +│   ├── Nargo.toml +│   └── src +│   └── main.nr +└── lib_a + ├── Nargo.toml + └── src + └── lib.nr +``` + +Inside of the binary crate, you can specify: + +```toml +# Nargo.toml + +[dependencies] +lib_a = { path = "../lib_a" } +``` + +## Importing dependencies + +You can import a dependency to a Noir file using the following syntax. For example, to import the +ecrecover-noir library and local lib_a referenced above: + +```rust +use dep::ecrecover; +use dep::lib_a; +``` + +You can also import only the specific parts of dependency that you want to use, like so: + +```rust +use dep::std::hash::sha256; +use dep::std::scalar_mul::fixed_base_embedded_curve; +``` + +Lastly, as demonstrated in the +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +can import multiple items in the same line by enclosing them in curly braces: + +```rust +use dep::std::ec::tecurve::affine::{Curve, Point}; +``` + +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. + +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. + +## Dependencies of Dependencies + +Note that when you import a dependency, you also get access to all of the dependencies of that package. + +For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: + +```rust +use dep::phy_vector; + +fn main(x : Field, y : pub Field) { + //... + let f = phy_vector::fraction::toFraction(true, 2, 1); + //... +} +``` + +## Available Libraries + +Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). + +Some libraries that are available today include: + +- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library +- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) +- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers +- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address +- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees +- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir +- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/modules.md new file mode 100644 index 00000000000..ae822a1cff4 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/modules.md @@ -0,0 +1,105 @@ +--- +title: Modules +description: + Learn how to organize your files using modules in Noir, following the same convention as Rust's + module system. Examples included. +keywords: [Noir, Rust, modules, organizing files, sub-modules] +sidebar_position: 2 +--- + +Noir's module system follows the same convention as the _newer_ version of Rust's module system. + +## Purpose of Modules + +Modules are used to organize files. Without modules all of your code would need to live in a single +file. In Noir, the compiler does not automatically scan all of your files to detect modules. This +must be done explicitly by the developer. + +## Examples + +### Importing a module in the crate root + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::hello_world(); +} +``` + +Filename : `src/foo.nr` + +```rust +fn from_foo() {} +``` + +In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module +declaration `mod foo` which prompts it to look for a foo.nr file. + +Visually this module hierarchy looks like the following : + +``` +crate + ├── main + │ + └── foo + └── from_foo + +``` + +### Importing a module throughout the tree + +All modules are accessible from the `crate::` namespace. + +``` +crate + ├── bar + ├── foo + └── main + +``` + +In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. + +### Sub-modules + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::from_foo(); +} +``` + +Filename : `src/foo.nr` + +```rust +mod bar; +fn from_foo() {} +``` + +Filename : `src/foo/bar.nr` + +```rust +fn from_bar() {} +``` + +In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule +of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the +compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` + +Visually the module hierarchy looks as follows: + +``` +crate + ├── main + │ + └── foo + ├── from_foo + └── bar + └── from_bar +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/workspaces.md new file mode 100644 index 00000000000..67a1dafa372 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/workspaces.md @@ -0,0 +1,40 @@ +--- +title: Workspaces +sidebar_position: 3 +--- + +Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. + +Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. + +For a project with the following structure: + +```tree +├── crates +│   ├── a +│   │   ├── Nargo.toml +│   │   └── src +│   │   └── main.nr +│   └── b +│   ├── Nargo.toml +│   └── src +│   └── main.nr +├── Nargo.toml +└── Prover.toml +``` + +You can define a workspace in Nargo.toml like so: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. + +`default-member` indicates which package various commands process by default. + +Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. + +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/_category_.json new file mode 100644 index 00000000000..af04c0933fd --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Standard Library", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md new file mode 100644 index 00000000000..eae8744abf0 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md @@ -0,0 +1,31 @@ +--- +title: Black Box Functions +description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. +keywords: [noir, black box functions] +--- + +Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. + +The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. + +## Function list + +Here is a list of the current black box functions: + +- [SHA256](./cryptographic_primitives/hashes#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr) +- [Blake2s](./cryptographic_primitives/hashes#blake2s) +- [Blake3](./cryptographic_primitives/hashes#blake3) +- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) +- AND +- XOR +- RANGE +- [Keccak256](./cryptographic_primitives/hashes#keccak256) +- [Recursive proof verification](./recursion) + +Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. + +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/bn254.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/bn254.md new file mode 100644 index 00000000000..3294f005dbb --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/bn254.md @@ -0,0 +1,46 @@ +--- +title: Bn254 Field Library +--- + +Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. + +## decompose + +```rust +fn decompose(x: Field) -> (Field, Field) {} +``` + +Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. + + +## assert_gt + +```rust +fn assert_gt(a: Field, b: Field) {} +``` + +Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. + +## assert_lt + +```rust +fn assert_lt(a: Field, b: Field) {} +``` + +Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. + +## gt + +```rust +fn gt(a: Field, b: Field) -> bool {} +``` + +Returns true if a > b. + +## lt + +```rust +fn lt(a: Field, b: Field) -> bool {} +``` + +Returns true if a < b. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/boundedvec.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/boundedvec.md new file mode 100644 index 00000000000..ce4529f6e57 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/boundedvec.md @@ -0,0 +1,326 @@ +--- +title: Bounded Vectors +keywords: [noir, vector, bounded vector, slice] +sidebar_position: 1 +--- + +A `BoundedVec` is a growable storage similar to a `Vec` except that it +is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented +via slices and thus is not subject to the same restrictions slices are (notably, nested +slices - and thus nested vectors as well - are disallowed). + +Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by +pushing an additional element is also more efficient - the length only needs to be increased +by one. + +For these reasons `BoundedVec` should generally be preferred over `Vec` when there +is a reasonable maximum bound that can be placed on the vector. + +Example: + +```rust +let mut vector: BoundedVec = BoundedVec::new(); +for i in 0..5 { + vector.push(i); +} +assert(vector.len() == 5); +assert(vector.max_len() == 10); +``` + +## Methods + +### new + +```rust +pub fn new() -> Self +``` + +Creates a new, empty vector of length zero. + +Since this container is backed by an array internally, it still needs an initial value +to give each element. To resolve this, each element is zeroed internally. This value +is guaranteed to be inaccessible unless `get_unchecked` is used. + +Example: + +```rust +let empty_vector: BoundedVec = BoundedVec::new(); +assert(empty_vector.len() == 0); +``` + +Note that whenever calling `new` the maximum length of the vector should always be specified +via a type signature: + +```rust title="new_example" showLineNumbers +fn foo() -> BoundedVec { + // Ok! MaxLen is specified with a type annotation + let v1: BoundedVec = BoundedVec::new(); + let v2 = BoundedVec::new(); + + // Ok! MaxLen is known from the type of foo's return value + v2 +} + +fn bad() { + let mut v3 = BoundedVec::new(); + + // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. + v3.push(5); +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L11-L27 + + +This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions +but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a constraint failure at runtime when the vec is pushed to. + +### get + +```rust +pub fn get(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero. + +If the given index is equal to or greater than the length of the vector, this +will issue a constraint failure. + +Example: + +```rust +fn foo(v: BoundedVec) { + let first = v.get(0); + let last = v.get(v.len() - 1); + assert(first != last); +} +``` + +### get_unchecked + +```rust +pub fn get_unchecked(mut self: Self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero, without +performing a bounds check. + +Since this function does not perform a bounds check on length before accessing the element, +it is unsafe! Use at your own risk! + +Example: + +```rust title="get_unchecked_example" showLineNumbers +fn sum_of_first_three(v: BoundedVec) -> u32 { + // Always ensure the length is larger than the largest + // index passed to get_unchecked + assert(v.len() > 2); + let first = v.get_unchecked(0); + let second = v.get_unchecked(1); + let third = v.get_unchecked(2); + first + second + third +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L54-L64 + + + +### push + +```rust +pub fn push(&mut self, elem: T) { +``` + +Pushes an element to the end of the vector. This increases the length +of the vector by one. + +Panics if the new length of the vector will be greater than the max length. + +Example: + +```rust title="bounded-vec-push-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + v.push(1); + v.push(2); + + // Panics with failed assertion "push out of bounds" + v.push(3); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L68-L76 + + +### pop + +```rust +pub fn pop(&mut self) -> T +``` + +Pops the element at the end of the vector. This will decrease the length +of the vector by one. + +Panics if the vector is empty. + +Example: + +```rust title="bounded-vec-pop-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.push(1); + v.push(2); + + let two = v.pop(); + let one = v.pop(); + + assert(two == 2); + assert(one == 1); + // error: cannot pop from an empty vector + // let _ = v.pop(); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L81-L93 + + +### len + +```rust +pub fn len(self) -> u64 { +``` + +Returns the current length of this vector + +Example: + +```rust title="bounded-vec-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + assert(v.len() == 0); + + v.push(100); + assert(v.len() == 1); + + v.push(200); + v.push(300); + v.push(400); + assert(v.len() == 4); + + let _ = v.pop(); + let _ = v.pop(); + assert(v.len() == 2); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L98-L113 + + +### max_len + +```rust +pub fn max_len(_self: BoundedVec) -> u64 { +``` + +Returns the maximum length of this vector. This is always +equal to the `MaxLen` parameter this vector was initialized with. + +Example: + +```rust title="bounded-vec-max-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.max_len() == 5); + v.push(10); + assert(v.max_len() == 5); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L118-L124 + + +### storage + +```rust +pub fn storage(self) -> [T; MaxLen] { +``` + +Returns the internal array within this vector. +Since arrays in Noir are immutable, mutating the returned storage array will not mutate +the storage held internally by this vector. + +Note that uninitialized elements may be zeroed out! + +Example: + +```rust title="bounded-vec-storage-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.storage() == [0, 0, 0, 0, 0]); + + v.push(57); + assert(v.storage() == [57, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L129-L136 + + +### extend_from_array + +```rust +pub fn extend_from_array(&mut self, array: [T; Len]) +``` + +Pushes each element from the given array to this vector. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-array-example" showLineNumbers +let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([2, 4]); + + assert(vec.len == 2); + assert(vec.get(0) == 2); + assert(vec.get(1) == 4); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L141-L148 + + +### extend_from_bounded_vec + +```rust +pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) +``` + +Pushes each element from the other vector to this vector. The length of +the other vector is left unchanged. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-bounded-vec-example" showLineNumbers +let mut v1: BoundedVec = BoundedVec::new(); + let mut v2: BoundedVec = BoundedVec::new(); + + v2.extend_from_array([1, 2, 3]); + v1.extend_from_bounded_vec(v2); + + assert(v1.storage() == [1, 2, 3, 0, 0]); + assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L153-L162 + + +### any + +```rust +pub fn any(self, predicate: fn[Env](T) -> bool) -> bool +``` + +Returns true if the given predicate returns true for any element +in this vector. + +Example: + +```rust title="bounded-vec-any-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.extend_from_array([2, 4, 6]); + + let all_even = !v.any(|elem: u32| elem % 2 != 0); + assert(all_even); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L229-L235 + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/hashmap.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/hashmap.md new file mode 100644 index 00000000000..91604af765d --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/hashmap.md @@ -0,0 +1,569 @@ +--- +title: HashMap +keywords: [noir, map, hash, hashmap] +sidebar_position: 1 +--- + +`HashMap` is used to efficiently store and look up key-value pairs. + +`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. +Note that due to hash collisions, the actual maximum number of elements stored by any particular +hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since +every hash value will be performed modulo `MaxLen`. + +When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already +known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which +will likely change the result of the program. This behavior is set to become an error in future +versions instead. + +Example: + +```rust +// Create a mapping from Fields to u32s with a maximum length of 12 +// using a pedersen hash +let mut map: HashMap> = HashMap::default(); + +map.insert(1, 2); +map.insert(3, 4); + +let two = map.get(1).unwrap(); +``` + +## Methods + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Creates a fresh, empty HashMap. + +When using this function, always make sure to specify the maximum size of the hash map. + +This is the same `default` from the `Default` implementation given further below. It is +repeated here for convenience since it is the recommended way to create a hashmap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +Because `HashMap` has so many generic arguments that are likely to be the same throughout +your program, it may be helpful to create a type alias: + +```rust title="type_alias" showLineNumbers +type MyMap = HashMap>; +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L196-L198 + + +### with_hasher + +```rust title="with_hasher" showLineNumbers +pub fn with_hasher(_build_hasher: B) -> Self + where + B: BuildHasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L82-L86 + + +Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple +hashmaps are created with the same hasher instance. + +Example: + +```rust title="with_hasher_example" showLineNumbers +let my_hasher: BuildHasherDefault = Default::default(); + let hashmap: HashMap> = HashMap::with_hasher(my_hasher); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L207-L211 + + +### get + +```rust title="get" showLineNumbers +pub fn get( + self, + key: K + ) -> Option + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L278-L287 + + +Retrieves a value from the hashmap, returning `Option::none()` if it was not found. + +Example: + +```rust title="get_example" showLineNumbers +fn get_example(map: HashMap>) { + let x = map.get(12); + + if x.is_some() { + assert(x.unwrap() == 42); + } +} +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L299-L307 + + +### insert + +```rust title="insert" showLineNumbers +pub fn insert( + &mut self, + key: K, + value: V + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L313-L323 + + +Inserts a new key-value pair into the map. If the key was already in the map, its +previous value will be overridden with the newly provided one. + +Example: + +```rust title="insert_example" showLineNumbers +let mut map: HashMap> = HashMap::default(); + map.insert(12, 42); + assert(map.len() == 1); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L213-L217 + + +### remove + +```rust title="remove" showLineNumbers +pub fn remove( + &mut self, + key: K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L356-L365 + + +Removes the given key-value pair from the map. If the key was not already present +in the map, this does nothing. + +Example: + +```rust title="remove_example" showLineNumbers +map.remove(12); + assert(map.is_empty()); + + // If a key was not present in the map, remove does nothing + map.remove(12); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L221-L228 + + +### is_empty + +```rust title="is_empty" showLineNumbers +pub fn is_empty(self) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L115-L117 + + +True if the length of the hash map is empty. + +Example: + +```rust title="is_empty_example" showLineNumbers +assert(map.is_empty()); + + map.insert(1, 2); + assert(!map.is_empty()); + + map.remove(1); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L230-L238 + + +### len + +```rust title="len" showLineNumbers +pub fn len(self) -> u64 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L264-L266 + + +Returns the current length of this hash map. + +Example: + +```rust title="len_example" showLineNumbers +// This is equivalent to checking map.is_empty() + assert(map.len() == 0); + + map.insert(1, 2); + map.insert(3, 4); + map.insert(5, 6); + assert(map.len() == 3); + + // 3 was already present as a key in the hash map, so the length is unchanged + map.insert(3, 7); + assert(map.len() == 3); + + map.remove(1); + assert(map.len() == 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L240-L255 + + +### capacity + +```rust title="capacity" showLineNumbers +pub fn capacity(_self: Self) -> u64 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L271-L273 + + +Returns the maximum capacity of this hashmap. This is always equal to the capacity +specified in the hashmap's type. + +Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a +static capacity that does not increase as the map grows larger. Thus, this capacity +is also the maximum possible element count that can be inserted into the hashmap. +Due to hash collisions (modulo the hashmap length), it is likely the actual maximum +element count will be lower than the full capacity. + +Example: + +```rust title="capacity_example" showLineNumbers +let empty_map: HashMap> = HashMap::default(); + assert(empty_map.len() == 0); + assert(empty_map.capacity() == 42); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L257-L261 + + +### clear + +```rust title="clear" showLineNumbers +pub fn clear(&mut self) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L93-L95 + + +Clears the hashmap, removing all key-value pairs from it. + +Example: + +```rust title="clear_example" showLineNumbers +assert(!map.is_empty()); + map.clear(); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L263-L267 + + +### contains_key + +```rust title="contains_key" showLineNumbers +pub fn contains_key( + self, + key: K + ) -> bool + where + K: Hash + Eq, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L101-L110 + + +True if the hashmap contains the given key. Unlike `get`, this will not also return +the value associated with the key. + +Example: + +```rust title="contains_key_example" showLineNumbers +if map.contains_key(7) { + let value = map.get(7); + assert(value.is_some()); + } else { + println("No value for key 7!"); + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L269-L276 + + +### entries + +```rust title="entries" showLineNumbers +pub fn entries(self) -> BoundedVec<(K, V), N> { +``` +> Source code: noir_stdlib/src/collections/map.nr#L123-L125 + + +Returns a vector of each key-value pair present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="entries_example" showLineNumbers +let entries = map.entries(); + + // The length of a hashmap may not be compile-time known, so we + // need to loop over its capacity instead + for i in 0..map.capacity() { + if i < entries.len() { + let (key, value) = entries.get(i); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L310-L321 + + +### keys + +```rust title="keys" showLineNumbers +pub fn keys(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L144-L146 + + +Returns a vector of each key present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="keys_example" showLineNumbers +let keys = map.keys(); + + for i in 0..keys.max_len() { + if i < keys.len() { + let key = keys.get_unchecked(i); + let value = map.get(key).unwrap_unchecked(); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L323-L333 + + +### values + +```rust title="values" showLineNumbers +pub fn values(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L164-L166 + + +Returns a vector of each value present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="values_example" showLineNumbers +let values = map.values(); + + for i in 0..values.max_len() { + if i < values.len() { + let value = values.get_unchecked(i); + println(f"Found value {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L335-L344 + + +### iter_mut + +```rust title="iter_mut" showLineNumbers +pub fn iter_mut( + &mut self, + f: fn(K, V) -> (K, V) + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L183-L192 + + +Iterates through each key-value pair of the HashMap, setting each key-value pair to the +result returned from the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If this is not desired, use `iter_values_mut` if only values need to be mutated, +or `entries` if neither keys nor values need to be mutated. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_mut_example" showLineNumbers +// Add 1 to each key in the map, and double the value associated with that key. + map.iter_mut(|k, v| (k + 1, v * 2)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L348-L351 + + +### iter_keys_mut + +```rust title="iter_keys_mut" showLineNumbers +pub fn iter_keys_mut( + &mut self, + f: fn(K) -> K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L208-L217 + + +Iterates through the HashMap, mutating each key to the result returned from +the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If only iteration is desired and the keys are not intended to be mutated, +prefer using `entries` instead. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_keys_mut_example" showLineNumbers +// Double each key, leaving the value associated with that key untouched + map.iter_keys_mut(|k| k * 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L353-L356 + + +### iter_values_mut + +```rust title="iter_values_mut" showLineNumbers +pub fn iter_values_mut(&mut self, f: fn(V) -> V) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L233-L235 + + +Iterates through the HashMap, applying the given function to each value and mutating the +value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` +because the keys are untouched and the underlying hashmap thus does not need to be reordered. + +Example: + +```rust title="iter_values_mut_example" showLineNumbers +// Halve each value + map.iter_values_mut(|v| v / 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L358-L361 + + +### retain + +```rust title="retain" showLineNumbers +pub fn retain(&mut self, f: fn(K, V) -> bool) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L247-L249 + + +Retains only the key-value pairs for which the given function returns true. +Any key-value pairs for which the function returns false will be removed from the map. + +Example: + +```rust title="retain_example" showLineNumbers +map.retain(|k, v| (k != 0) & (v != 0)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L281-L283 + + +## Trait Implementations + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Constructs an empty HashMap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +### eq + +```rust title="eq" showLineNumbers +impl Eq for HashMap +where + K: Eq + Hash, + V: Eq, + B: BuildHasher, + H: Hasher +{ + fn eq(self, other: HashMap) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L426-L435 + + +Checks if two HashMaps are equal. + +Example: + +```rust title="eq_example" showLineNumbers +let mut map1: HashMap> = HashMap::default(); + let mut map2: HashMap> = HashMap::default(); + + map1.insert(1, 2); + map1.insert(3, 4); + + map2.insert(3, 4); + map2.insert(1, 2); + + assert(map1 == map2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L285-L296 + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/index.md new file mode 100644 index 00000000000..ea84c6d5c21 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/index.md @@ -0,0 +1,5 @@ +--- +title: Containers +description: Container types provided by Noir's standard library for storing and retrieving data +keywords: [containers, data types, vec, hashmap] +--- diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/vec.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/vec.mdx new file mode 100644 index 00000000000..1954f05bc76 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/containers/vec.mdx @@ -0,0 +1,151 @@ +--- +title: Vectors +description: Delve into the Vec data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. +keywords: [noir, vector type, methods, examples, dynamic arrays] +sidebar_position: 6 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A vector is a collection type similar to Rust's `Vec` type. In Noir, it is a convenient way to use slices as mutable arrays. + +Example: + +```rust +let mut vector: Vec = Vec::new(); +for i in 0..5 { + vector.push(i); +} +assert(vector.len() == 5); +``` + +## Methods + +### new + +Creates a new, empty vector. + +```rust +pub fn new() -> Self +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` + +### from_slice + +Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. + +```rust +pub fn from_slice(slice: [T]) -> Self +``` + +Example: + +```rust +let arr: [Field] = [1, 2, 3]; +let vector_from_slice = Vec::from_slice(arr); +assert(vector_from_slice.len() == 3); +``` + +### len + +Returns the number of elements in the vector. + +```rust +pub fn len(self) -> Field +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` + +### get + +Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. + +```rust +pub fn get(self, index: Field) -> T +``` + +Example: + +```rust +let vector: Vec = Vec::from_slice([10, 20, 30]); +assert(vector.get(1) == 20); +``` + +### push + +Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. + +```rust +pub fn push(&mut self, elem: T) +``` + +Example: + +```rust +let mut vector: Vec = Vec::new(); +vector.push(10); +assert(vector.len() == 1); +``` + +### pop + +Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. + +```rust +pub fn pop(&mut self) -> T +``` + +Example: + +```rust +let mut vector = Vec::from_slice([10, 20]); +let popped_elem = vector.pop(); +assert(popped_elem == 20); +assert(vector.len() == 1); +``` + +### insert + +Inserts an element at a specified index, shifting subsequent elements to the right. + +```rust +pub fn insert(&mut self, index: Field, elem: T) +``` + +Example: + +```rust +let mut vector = Vec::from_slice([10, 30]); +vector.insert(1, 20); +assert(vector.get(1) == 20); +``` + +### remove + +Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. + +```rust +pub fn remove(&mut self, index: Field) -> T +``` + +Example: + +```rust +let mut vector = Vec::from_slice([10, 20, 30]); +let removed_elem = vector.remove(1); +assert(removed_elem == 20); +assert(vector.len() == 2); +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ec_primitives.md new file mode 100644 index 00000000000..d2b42d67b7c --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ec_primitives.md @@ -0,0 +1,102 @@ +--- +title: Elliptic Curve Primitives +keywords: [cryptographic primitives, Noir project] +sidebar_position: 4 +--- + +Data structures and methods on them that allow you to carry out computations involving elliptic +curves over the (mathematical) field corresponding to `Field`. For the field currently at our +disposal, applications would involve a curve embedded in BN254, e.g. the +[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). + +## Data structures + +### Elliptic curve configurations + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic +curve you want to use, which would be specified using any one of the methods +`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the +defining equation together with a generator point as parameters. You can find more detail in the +comments in +[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but +the gist of it is that the elliptic curves of interest are usually expressed in one of the standard +forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, +you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly +together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates +requiring more coordinates but allowing for more efficient implementations of elliptic curve +operations). Conversions between all of these forms are provided, and under the hood these +conversions are done whenever an operation is more efficient in a different representation (or a +mixed coordinate representation is employed). + +### Points + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the +elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` +does indeed lie on `c` by calling `c.contains(p1)`. + +## Methods + +(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use +`std::ec::tecurve::affine::Point`) + +- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is + zero by calling `p.is_zero()`. +- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling + `p1.eq(p2)`. +- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two + points is accomplished by calling `c.add(p1,p2)`. +- **Negation**: For a point `p: Point`, `p.negate()` is its negation. +- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by + calling `c.subtract(p1,p2)`. +- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, + scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit + array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` +- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, + multi-scalar multiplication is given by `c.msm(n,p)`. +- **Coordinate representation conversions**: The `into_group` method converts a point or curve + configuration in the affine representation to one in the CurveGroup representation, and + `into_affine` goes in the other direction. +- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent + and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their + configurations or points. `swcurve` is more general and a curve c of one of the other two types + may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying + on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling + `c.map_into_swcurve(p)`. +- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a + `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of + the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where + `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to + satisfy are specified in the comments + [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). + +## Examples + +The +[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) +illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more +interesting examples in Noir would be: + +Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key +from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, +for example, this code would do: + +```rust +use dep::std::ec::tecurve::affine::{Curve, Point}; + +fn bjj_pub_key(priv_key: Field) -> Point +{ + + let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); + + let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); + + bjj.mul(priv_key,base_pt) +} +``` + +This would come in handy in a Merkle proof. + +- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash + function. See + [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for + the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx new file mode 100644 index 00000000000..4bf09cef178 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -0,0 +1,60 @@ +--- +title: ECDSA Signature Verification +description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves +keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] +sidebar_position: 3 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. + +## ecdsa_secp256k1::verify_signature + +Verifier for ECDSA Secp256k1 signatures + +```rust title="ecdsa_secp256k1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 + + +example: + +```rust +fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { + let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); +} +``` + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures + +```rust title="ecdsa_secp256r1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 + + +example: + +```rust +fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { + let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); +} +``` + + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/eddsa.mdx new file mode 100644 index 00000000000..c2c0624dfad --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/eddsa.mdx @@ -0,0 +1,37 @@ +--- +title: EdDSA Verification +description: Learn about the cryptographic primitives regarding EdDSA +keywords: [cryptographic primitives, Noir project, eddsa, signatures] +sidebar_position: 5 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## eddsa::eddsa_poseidon_verify + +Verifier for EdDSA signatures + +```rust +fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool +``` + +It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify_with_hasher` function with a parameter implementing the Hasher trait. For instance, if you want to use Poseidon2 instead, you can do the following: +```rust +use dep::std::hash::poseidon2::Poseidon2Hasher; + +let mut hasher = Poseidon2Hasher::default(); +eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher); +``` + + + +## eddsa::eddsa_to_pub + +Private to public key conversion. + +Returns `(pub_key_x, pub_key_y)` + +```rust +fn eddsa_to_pub(secret : Field) -> (Field, Field) +``` + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/hashes.mdx new file mode 100644 index 00000000000..119d8ccc70e --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -0,0 +1,251 @@ +--- +title: Hash methods +description: + Learn about the cryptographic primitives ready to use for any Noir project, including sha256, + blake2s, pedersen, mimc_bn254 and mimc +keywords: + [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## sha256 + +Given an array of bytes, returns the resulting sha256 hash. + +```rust title="sha256" showLineNumbers +pub fn sha256(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L9-L11 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::sha256(x); +} +``` + + + +## blake2s + +Given an array of bytes, returns an array with the Blake2 hash + +```rust title="blake2s" showLineNumbers +pub fn blake2s(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L15-L17 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake2s(x); +} +``` + + + +## blake3 + +Given an array of bytes, returns an array with the Blake3 hash + +```rust title="blake3" showLineNumbers +pub fn blake3(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L21-L23 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake3(x); +} +``` + + + +## pedersen_hash + +Given an array of Fields, returns the Pedersen hash. + +```rust title="pedersen_hash" showLineNumbers +pub fn pedersen_hash(input: [Field; N]) -> Field +``` +> Source code: noir_stdlib/src/hash.nr#L46-L48 + + +example: + +```rust title="pedersen-hash" showLineNumbers +use dep::std; + +fn main(x: Field, y: Field, expected_hash: Field) { + let hash = std::hash::pedersen_hash([x, y]); + assert_eq(hash, expected_hash); +} +``` +> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L8 + + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. + +```rust title="pedersen_commitment" showLineNumbers +struct PedersenPoint { + x : Field, + y : Field, +} + +pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint +``` +> Source code: noir_stdlib/src/hash.nr#L26-L33 + + +example: + +```rust title="pedersen-commitment" showLineNumbers +use dep::std; + +fn main(x: Field, y: Field, expected_commitment: std::hash::PedersenPoint) { + let commitment = std::hash::pedersen_commitment([x, y]); + assert_eq(commitment.x, expected_commitment.x); + assert_eq(commitment.y, expected_commitment.y); +} +``` +> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L9 + + + + +## keccak256 + +Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes +(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes +of the input. + +```rust title="keccak256" showLineNumbers +pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L71-L73 + + +example: + +```rust title="keccak256" showLineNumbers +use dep::std; + +fn main(x: Field, result: [u8; 32]) { + // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field + // The padding is taken care of by the program + let digest = std::hash::keccak256([x as u8], 1); + assert(digest == result); + + //#1399: variable message size + let message_size = 4; + let hash_a = std::hash::keccak256([1, 2, 3, 4], message_size); + let hash_b = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size); + + assert(hash_a == hash_b); + + let message_size_big = 8; + let hash_c = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); + + assert(hash_a != hash_c); +} +``` +> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L22 + + + + +## poseidon + +Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify +how many inputs are there to your Poseidon function. + +```rust +// example for hash_1, hash_2 accepts an array of length 2, etc +fn hash_1(input: [Field; 1]) -> Field +``` + +example: + +```rust title="poseidon" showLineNumbers +use dep::std::hash::poseidon; +use dep::std::hash::poseidon2; + +fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { + let hash1 = poseidon::bn254::hash_2(x1); + assert(hash1 == y1); + + let hash2 = poseidon::bn254::hash_4(x2); + assert(hash2 == y2); + + let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); + assert(hash3 == y3); +} +``` +> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L15 + + +## poseidon 2 + +Given an array of Fields, returns a new Field with the Poseidon2 Hash. Contrary to the Poseidon +function, there is only one hash and you can specify a message_size to hash only the first +`message_size` bytes of the input, + +```rust +// example for hashing the first three elements of the input +Poseidon2::hash(input, 3); +``` + +The above example for Poseidon also includes Poseidon2. + +## mimc_bn254 and mimc + +`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by +providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if +you're willing to input your own constants: + +```rust +fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field +``` + +otherwise, use the `mimc_bn254` method: + +```rust +fn mimc_bn254(array: [Field; N]) -> Field +``` + +example: + +```rust + +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::mimc::mimc_bn254(x); +} +``` + +## hash_to_field + +```rust +fn hash_to_field(_input : [Field; N]) -> Field {} +``` + +Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return +a value which can be represented as a `Field`. + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/index.md new file mode 100644 index 00000000000..650f30165d5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/index.md @@ -0,0 +1,14 @@ +--- +title: Cryptographic Primitives +description: + Learn about the cryptographic primitives ready to use for any Noir project +keywords: + [ + cryptographic primitives, + Noir project, + ] +--- + +The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. + +Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/scalar.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/scalar.mdx new file mode 100644 index 00000000000..df411ca5443 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/scalar.mdx @@ -0,0 +1,33 @@ +--- +title: Scalar multiplication +description: See how you can perform scalar multiplications over a fixed base in Noir +keywords: [cryptographic primitives, Noir project, scalar multiplication] +sidebar_position: 1 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## scalar_mul::fixed_base_embedded_curve + +Performs scalar multiplication over the embedded curve whose coordinates are defined by the +configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. + +```rust title="fixed_base_embedded_curve" showLineNumbers +pub fn fixed_base_embedded_curve( + low: Field, + high: Field +) -> [Field; 2] +``` +> Source code: noir_stdlib/src/scalar_mul.nr#L27-L32 + + +example + +```rust +fn main(x : Field) { + let scal = std::scalar_mul::fixed_base_embedded_curve(x); + println(scal); +} +``` + + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/schnorr.mdx new file mode 100644 index 00000000000..ae12e6c12dc --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/cryptographic_primitives/schnorr.mdx @@ -0,0 +1,45 @@ +--- +title: Schnorr Signatures +description: Learn how you can verify Schnorr signatures using Noir +keywords: [cryptographic primitives, Noir project, schnorr, signatures] +sidebar_position: 2 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## schnorr::verify_signature + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). + +```rust title="schnorr_verify" showLineNumbers +pub fn verify_signature( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/schnorr.nr#L2-L9 + + +where `_signature` can be generated like so using the npm package +[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) + +```js +const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); +const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); + +... + +const barretenberg = await BarretenbergWasm.new(); +const schnorr = new Schnorr(barretenberg); +const pubKey = schnorr.computePublicKey(privateKey); +const message = ... +const signature = Array.from( + schnorr.constructSignature(hash, privateKey).toBuffer() +); + +... +``` + + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/logging.md new file mode 100644 index 00000000000..db75ef9f86f --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/logging.md @@ -0,0 +1,78 @@ +--- +title: Logging +description: + Learn how to use the println statement for debugging in Noir with this tutorial. Understand the + basics of logging in Noir and how to implement it in your code. +keywords: + [ + noir logging, + println statement, + print statement, + debugging in noir, + noir std library, + logging tutorial, + basic logging in noir, + noir logging implementation, + noir debugging techniques, + rust, + ] +--- + +The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. + +You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). + +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. + +Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: + +```rust +struct Person { + age: Field, + height: Field, +} + +fn main(age: Field, height: Field) { + let person = Person { + age: age, + height: height, + }; + println(person); + println(age + height); + println("Hello world!"); +} +``` + +You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: + +```rust + let fmt_str = f"i: {i}, j: {j}"; + println(fmt_str); + + let s = myStruct { y: x, x: y }; + println(s); + + println(f"i: {i}, s: {s}"); + + println(x); + println([x, y]); + + let foo = fooStruct { my_struct: s, foo: 15 }; + println(f"s: {s}, foo: {foo}"); + + println(15); // prints 0x0f, implicit Field + println(-1 as u8); // prints 255 + println(-1 as i8); // prints -1 +``` + +Examples shown above are interchangeable between the two `print` statements: + +```rust +let person = Person { age : age, height : height }; + +println(person); +print(person); + +println("Hello world!"); // Prints with a newline at the end of the input +print("Hello world!"); // Prints the input and keeps cursor on the same line +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/merkle_trees.md new file mode 100644 index 00000000000..fa488677884 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/merkle_trees.md @@ -0,0 +1,58 @@ +--- +title: Merkle Trees +description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. +keywords: + [ + Merkle trees in Noir, + Noir programming language, + check membership, + computing root from leaf, + Noir Merkle tree implementation, + Merkle tree tutorial, + Merkle tree code examples, + Noir libraries, + pedersen hash., + ] +--- + +## compute_merkle_root + +Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](./cryptographic_primitives/hashes.mdx#pedersen_hash). + +```rust +fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field +``` + +example: + +```rust +/** + // these values are for this example only + index = "0" + priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" + secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" + note_hash_path = [ + "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", + "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", + "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" + ] + */ +fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { + + let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); + let pubkey_x = pubkey[0]; + let pubkey_y = pubkey[1]; + let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); + + let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); + println(root); +} +``` + +To check merkle tree membership: + +1. Include a merkle root as a program input. +2. Compute the merkle root of a given leaf, index and hash path. +3. Assert the merkle roots are equal. + +For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/options.md new file mode 100644 index 00000000000..a1bd4e1de5f --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/options.md @@ -0,0 +1,101 @@ +--- +title: Option Type +--- + +The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. + +```rust +struct Option { + None, + Some(T), +} +``` + +The `Option` type, already imported into your Noir program, can be used directly: + +```rust +fn main() { + let none = Option::none(); + let some = Option::some(3); +} +``` + +See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. + +## Methods + +### none + +Constructs a none value. + +### some + +Constructs a some wrapper around a given value. + +### is_none + +Returns true if the Option is None. + +### is_some + +Returns true of the Option is Some. + +### unwrap + +Asserts `self.is_some()` and returns the wrapped value. + +### unwrap_unchecked + +Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. + +### unwrap_or + +Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. + +### unwrap_or_else + +Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. + +### expect + +Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value. The custom message is expected to be a format string. + +### map + +If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. + +### map_or + +If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. + +### map_or_else + +If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. + +### and + +Returns None if self is None. Otherwise, this returns `other`. + +### and_then + +If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. + +### or + +If self is Some, return self. Otherwise, return `other`. + +### or_else + +If self is Some, return self. Otherwise, return `default()`. + +### xor + +If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. + +### filter + +Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. + +### flatten + +Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md new file mode 100644 index 00000000000..9337499dac8 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md @@ -0,0 +1,88 @@ +--- +title: Recursive Proofs +description: Learn about how to write recursive proofs in Noir. +keywords: [recursion, recursive proofs, verification_key, verify_proof] +--- + +Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. + +Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) + +## The `#[recursive]` Attribute + +In Noir, the `#[recursive]` attribute is used to indicate that a circuit is designed for recursive proof generation. When applied, it informs the compiler and the tooling that the circuit should be compiled in a way that makes its proofs suitable for recursive verification. This attribute eliminates the need for manual flagging of recursion at the tooling level, streamlining the proof generation process for recursive circuits. + +### Example usage with `#[recursive]` + +```rust +#[recursive] +fn main(x: Field, y: pub Field) { + assert(x == y, "x and y are not equal"); +} + +// This marks the circuit as recursion-friendly and indicates that proofs generated from this circuit +// are intended for recursive verification. +``` + +By incorporating this attribute directly in the circuit's definition, tooling like Nargo and NoirJS can automatically execute recursive-specific duties for Noir programs (e.g. recursive-friendly proof artifact generation) without additional flags or configurations. + +## Verifying Recursive Proofs + +```rust +#[foreign(verify_proof)] +fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field) {} +``` + +:::info + +This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. + +::: + +## Example usage + +```rust +use dep::std; + +fn main( + verification_key : [Field; 114], + proof : [Field; 93], + public_inputs : [Field; 1], + key_hash : Field, + proof_b : [Field; 93], +) { + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash + ); + + std::verify_proof( + verification_key.as_slice(), + proof_b.as_slice(), + public_inputs.as_slice(), + key_hash + ); +} +``` + +You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). + +## Parameters + +### `verification_key` + +The verification key for the zk program that is being verified. + +### `proof` + +The proof for the zk program that is being verified. + +### `public_inputs` + +These represent the public inputs of the proof we are verifying. + +### `key_hash` + +A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/traits.md new file mode 100644 index 00000000000..ba9fa2ee841 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/traits.md @@ -0,0 +1,399 @@ +--- +title: Traits +description: Noir's stdlib provides a few commonly used traits. +keywords: [traits, trait, interface, protocol, default, add, eq] +--- + +## `std::default` + +### `std::default::Default` + +```rust title="default-trait" showLineNumbers +trait Default { + fn default() -> Self; +} +``` +> Source code: noir_stdlib/src/default.nr#L1-L5 + + +Constructs a default value of a type. + +Implementations: +```rust +impl Default for Field { .. } + +impl Default for i8 { .. } +impl Default for i16 { .. } +impl Default for i32 { .. } +impl Default for i64 { .. } + +impl Default for u8 { .. } +impl Default for u16 { .. } +impl Default for u32 { .. } +impl Default for u64 { .. } + +impl Default for () { .. } +impl Default for bool { .. } + +impl Default for [T; N] + where T: Default { .. } + +impl Default for (A, B) + where A: Default, B: Default { .. } + +impl Default for (A, B, C) + where A: Default, B: Default, C: Default { .. } + +impl Default for (A, B, C, D) + where A: Default, B: Default, C: Default, D: Default { .. } + +impl Default for (A, B, C, D, E) + where A: Default, B: Default, C: Default, D: Default, E: Default { .. } +``` + +For primitive integer types, the return value of `default` is `0`. Container +types such as arrays are filled with default values of their element type. + + +## `std::convert` + +### `std::convert::From` + +```rust title="from-trait" showLineNumbers +trait From { + fn from(input: T) -> Self; +} +``` +> Source code: noir_stdlib/src/convert.nr#L1-L5 + + +The `From` trait defines how to convert from a given type `T` to the type on which the trait is implemented. + +The Noir standard library provides a number of implementations of `From` between primitive types. +```rust title="from-impls" showLineNumbers +// Unsigned integers + +impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } + +impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } +impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } + +impl From for Field { fn from(value: u8) -> Field { value as Field } } +impl From for Field { fn from(value: u32) -> Field { value as Field } } +impl From for Field { fn from(value: u64) -> Field { value as Field } } + +// Signed integers + +impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } + +impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } +impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } + +// Booleans +impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } +impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } +impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } +impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } +impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } +impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } +impl From for Field { fn from(value: bool) -> Field { value as Field } } +``` +> Source code: noir_stdlib/src/convert.nr#L25-L52 + + +#### When to implement `From` + +As a general rule of thumb, `From` may be implemented in the [situations where it would be suitable in Rust](https://doc.rust-lang.org/std/convert/trait.From.html#when-to-implement-from): + +- The conversion is *infallible*: Noir does not provide an equivalent to Rust's `TryFrom`, if the conversion can fail then provide a named method instead. +- The conversion is *lossless*: semantically, it should not lose or discard information. For example, `u32: From` can losslessly convert any `u16` into a valid `u32` such that the original `u16` can be recovered. On the other hand, `u16: From` should not be implemented as `2**16` is a `u32` which cannot be losslessly converted into a `u16`. +- The conversion is *value-preserving*: the conceptual kind and meaning of the resulting value is the same, even though the Noir type and technical representation might be different. While it's possible to infallibly and losslessly convert a `u8` into a `str<2>` hex representation, `4u8` and `"04"` are too different for `str<2>: From` to be implemented. +- The conversion is *obvious*: it's the only reasonable conversion between the two types. If there's ambiguity on how to convert between them such that the same input could potentially map to two different values then a named method should be used. For instance rather than implementing `U128: From<[u8; 16]>`, the methods `U128::from_le_bytes` and `U128::from_be_bytes` are used as otherwise the endianness of the array would be ambiguous, resulting in two potential values of `U128` from the same byte array. + +One additional recommendation specific to Noir is: +- The conversion is *efficient*: it's relatively cheap to convert between the two types. Due to being a ZK DSL, it's more important to avoid unnecessary computation compared to Rust. If the implementation of `From` would encourage users to perform unnecessary conversion, resulting in additional proving time, then it may be preferable to expose functionality such that this conversion may be avoided. + +### `std::convert::Into` + +The `Into` trait is defined as the reciprocal of `From`. It should be easy to convince yourself that if we can convert to type `A` from type `B`, then it's possible to convert type `B` into type `A`. + +For this reason, implementing `From` on a type will automatically generate a matching `Into` implementation. One should always prefer implementing `From` over `Into` as implementing `Into` will not generate a matching `From` implementation. + +```rust title="into-trait" showLineNumbers +trait Into { + fn into(input: Self) -> T; +} + +impl Into for U where T: From { + fn into(input: U) -> T { + T::from(input) + } +} +``` +> Source code: noir_stdlib/src/convert.nr#L13-L23 + + +`Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. + + +## `std::cmp` + +### `std::cmp::Eq` + +```rust title="eq-trait" showLineNumbers +trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L1-L5 + + +Returns `true` if `self` is equal to `other`. Implementing this trait on a type +allows the type to be used with `==` and `!=`. + +Implementations: +```rust +impl Eq for Field { .. } + +impl Eq for i8 { .. } +impl Eq for i16 { .. } +impl Eq for i32 { .. } +impl Eq for i64 { .. } + +impl Eq for u8 { .. } +impl Eq for u16 { .. } +impl Eq for u32 { .. } +impl Eq for u64 { .. } + +impl Eq for () { .. } +impl Eq for bool { .. } + +impl Eq for [T; N] + where T: Eq { .. } + +impl Eq for (A, B) + where A: Eq, B: Eq { .. } + +impl Eq for (A, B, C) + where A: Eq, B: Eq, C: Eq { .. } + +impl Eq for (A, B, C, D) + where A: Eq, B: Eq, C: Eq, D: Eq { .. } + +impl Eq for (A, B, C, D, E) + where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } +``` + +### `std::cmp::Ord` + +```rust title="ord-trait" showLineNumbers +trait Ord { + fn cmp(self, other: Self) -> Ordering; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L92-L96 + + +`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, +`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. +Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be +used on values of the type. + +Implementations: + +```rust +impl Ord for u8 { .. } +impl Ord for u16 { .. } +impl Ord for u32 { .. } +impl Ord for u64 { .. } + +impl Ord for i8 { .. } +impl Ord for i16 { .. } +impl Ord for i32 { .. } + +impl Ord for i64 { .. } + +impl Ord for () { .. } +impl Ord for bool { .. } + +impl Ord for [T; N] + where T: Ord { .. } + +impl Ord for (A, B) + where A: Ord, B: Ord { .. } + +impl Ord for (A, B, C) + where A: Ord, B: Ord, C: Ord { .. } + +impl Ord for (A, B, C, D) + where A: Ord, B: Ord, C: Ord, D: Ord { .. } + +impl Ord for (A, B, C, D, E) + where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } +``` + +## `std::ops` + +### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` + +These traits abstract over addition, subtraction, multiplication, and division respectively. +Implementing these traits for a given type will also allow that type to be used with the corresponding operator +for that trait (`+` for Add, etc) in addition to the normal method names. + +```rust title="add-trait" showLineNumbers +trait Add { + fn add(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L1-L5 + +```rust title="sub-trait" showLineNumbers +trait Sub { + fn sub(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L17-L21 + +```rust title="mul-trait" showLineNumbers +trait Mul { + fn mul(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L33-L37 + +```rust title="div-trait" showLineNumbers +trait Div { + fn div(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L49-L53 + + +The implementations block below is given for the `Add` trait, but the same types that implement +`Add` also implement `Sub`, `Mul`, and `Div`. + +Implementations: +```rust +impl Add for Field { .. } + +impl Add for i8 { .. } +impl Add for i16 { .. } +impl Add for i32 { .. } +impl Add for i64 { .. } + +impl Add for u8 { .. } +impl Add for u16 { .. } +impl Add for u32 { .. } +impl Add for u64 { .. } +``` + +### `std::ops::Rem` + +```rust title="rem-trait" showLineNumbers +trait Rem{ + fn rem(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L65-L69 + + +`Rem::rem(a, b)` is the remainder function returning the result of what is +left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator +to be used with the implementation type. + +Unlike other numeric traits, `Rem` is not implemented for `Field`. + +Implementations: +```rust +impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } +impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } +impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } +impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } + +impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } +impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } +impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } +impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } +``` + +### `std::ops::{ BitOr, BitAnd, BitXor }` + +```rust title="bitor-trait" showLineNumbers +trait BitOr { + fn bitor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L79-L83 + +```rust title="bitand-trait" showLineNumbers +trait BitAnd { + fn bitand(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L95-L99 + +```rust title="bitxor-trait" showLineNumbers +trait BitXor { + fn bitxor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L111-L115 + + +Traits for the bitwise operations `|`, `&`, and `^`. + +Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively +to be used with the type. + +The implementations block below is given for the `BitOr` trait, but the same types that implement +`BitOr` also implement `BitAnd` and `BitXor`. + +Implementations: +```rust +impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } + +impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } +impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } +impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } +impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } + +impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } +impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } +impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } +impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } +``` + +### `std::ops::{ Shl, Shr }` + +```rust title="shl-trait" showLineNumbers +trait Shl { + fn shl(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L127-L131 + +```rust title="shr-trait" showLineNumbers +trait Shr { + fn shr(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops.nr#L142-L146 + + +Traits for a bit shift left and bit shift right. + +Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. +Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. + +Note that bit shifting is not currently implemented for signed types. + +The implementations block below is given for the `Shl` trait, but the same types that implement +`Shl` also implement `Shr`. + +Implementations: +```rust +impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } +impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } +impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } +impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/zeroed.md new file mode 100644 index 00000000000..97dab02dac2 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/zeroed.md @@ -0,0 +1,25 @@ +--- +title: Zeroed Function +description: + The zeroed function returns a zeroed value of any type. +keywords: + [ + zeroed + ] +--- + +Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. + +You can access the function at `std::unsafe::zeroed`. + +This function currently supports the following types: + +- Field +- Bool +- Uint +- Array +- String +- Tuple +- Function + +Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/_category_.json new file mode 100644 index 00000000000..5b6a20a609a --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 4, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/nargo_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/nargo_commands.md new file mode 100644 index 00000000000..8a309ef4e7e --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/reference/nargo_commands.md @@ -0,0 +1,380 @@ +--- +title: Nargo +description: + Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, + generate Solidity verifier smart contract and compile into JSON file containing ACIR + representation and ABI of circuit. +keywords: + [ + Nargo, + Noir CLI, + Noir Prover, + Noir Verifier, + generate Solidity verifier, + compile JSON file, + ACIR representation, + ABI of circuit, + TypeScript, + ] +sidebar_position: 0 +--- + +# Command-Line Help for `nargo` + +This document contains the help content for the `nargo` command-line program. + +**Command Overview:** + +* [`nargo`↴](#nargo) +* [`nargo backend`↴](#nargo-backend) +* [`nargo backend current`↴](#nargo-backend-current) +* [`nargo backend ls`↴](#nargo-backend-ls) +* [`nargo backend use`↴](#nargo-backend-use) +* [`nargo backend install`↴](#nargo-backend-install) +* [`nargo backend uninstall`↴](#nargo-backend-uninstall) +* [`nargo check`↴](#nargo-check) +* [`nargo fmt`↴](#nargo-fmt) +* [`nargo codegen-verifier`↴](#nargo-codegen-verifier) +* [`nargo compile`↴](#nargo-compile) +* [`nargo new`↴](#nargo-new) +* [`nargo init`↴](#nargo-init) +* [`nargo execute`↴](#nargo-execute) +* [`nargo prove`↴](#nargo-prove) +* [`nargo verify`↴](#nargo-verify) +* [`nargo test`↴](#nargo-test) +* [`nargo info`↴](#nargo-info) +* [`nargo lsp`↴](#nargo-lsp) + +## `nargo` + +Noir's package manager + +**Usage:** `nargo ` + +###### **Subcommands:** + +* `backend` — Install and select custom backends used to generate and verify proofs +* `check` — Checks the constraint system for errors +* `fmt` — Format the Noir files in a workspace +* `codegen-verifier` — Generates a Solidity verifier smart contract for the program +* `compile` — Compile the program and its secret execution trace into ACIR format +* `new` — Create a Noir project in a new directory +* `init` — Create a Noir project in the current directory +* `execute` — Executes a circuit to calculate its return value +* `prove` — Create proof for this program. The proof is returned as a hex encoded string +* `verify` — Given a proof and a program, verify whether the proof is valid +* `test` — Run the tests for this program +* `info` — Provides detailed information on a circuit +* `lsp` — Starts the Noir LSP server + +###### **Options:** + + + + +## `nargo backend` + +Install and select custom backends used to generate and verify proofs + +**Usage:** `nargo backend ` + +###### **Subcommands:** + +* `current` — Prints the name of the currently active backend +* `ls` — Prints the list of currently installed backends +* `use` — Select the backend to use +* `install` — Install a new backend from a URL +* `uninstall` — Uninstalls a backend + + + +## `nargo backend current` + +Prints the name of the currently active backend + +**Usage:** `nargo backend current` + + + +## `nargo backend ls` + +Prints the list of currently installed backends + +**Usage:** `nargo backend ls` + + + +## `nargo backend use` + +Select the backend to use + +**Usage:** `nargo backend use ` + +###### **Arguments:** + +* `` + + + +## `nargo backend install` + +Install a new backend from a URL + +**Usage:** `nargo backend install ` + +###### **Arguments:** + +* `` — The name of the backend to install +* `` — The URL from which to download the backend + + + +## `nargo backend uninstall` + +Uninstalls a backend + +**Usage:** `nargo backend uninstall ` + +###### **Arguments:** + +* `` — The name of the backend to uninstall + + + +## `nargo check` + +Checks the constraint system for errors + +**Usage:** `nargo check [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to check +* `--workspace` — Check all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo fmt` + +Format the Noir files in a workspace + +**Usage:** `nargo fmt [OPTIONS]` + +###### **Options:** + +* `--check` — Run noirfmt in check mode + + + +## `nargo codegen-verifier` + +Generates a Solidity verifier smart contract for the program + +**Usage:** `nargo codegen-verifier [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to codegen +* `--workspace` — Codegen all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo compile` + +Compile the program and its secret execution trace into ACIR format + +**Usage:** `nargo compile [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to compile +* `--workspace` — Compile all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo new` + +Create a Noir project in a new directory + +**Usage:** `nargo new [OPTIONS] ` + +###### **Arguments:** + +* `` — The path to save the new project + +###### **Options:** + +* `--name ` — Name of the package [default: package directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo init` + +Create a Noir project in the current directory + +**Usage:** `nargo init [OPTIONS]` + +###### **Options:** + +* `--name ` — Name of the package [default: current directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo execute` + +Executes a circuit to calculate its return value + +**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` + +###### **Arguments:** + +* `` — Write the execution witness to named file + +###### **Options:** + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `--package ` — The name of the package to execute +* `--workspace` — Execute all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo prove` + +Create proof for this program. The proof is returned as a hex encoded string + +**Usage:** `nargo prove [OPTIONS]` + +###### **Options:** + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier + + Default value: `Verifier` +* `--verify` — Verify proof after proving +* `--package ` — The name of the package to prove +* `--workspace` — Prove all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo verify` + +Given a proof and a program, verify whether the proof is valid + +**Usage:** `nargo verify [OPTIONS]` + +###### **Options:** + +* `-v`, `--verifier-name ` — The name of the toml file which contains the inputs for the verifier + + Default value: `Verifier` +* `--package ` — The name of the package verify +* `--workspace` — Verify all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo test` + +Run the tests for this program + +**Usage:** `nargo test [OPTIONS] [TEST_NAME]` + +###### **Arguments:** + +* `` — If given, only tests with names containing this string will be run + +###### **Options:** + +* `--show-output` — Display output of `println` statements +* `--exact` — Only run tests that match exactly +* `--package ` — The name of the package to test +* `--workspace` — Test all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo info` + +Provides detailed information on a circuit + +Current information provided: 1. The number of ACIR opcodes 2. Counts the final number gates in the circuit used by a backend + +**Usage:** `nargo info [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to detail +* `--workspace` — Detail all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo lsp` + +Starts the Noir LSP server + +Starts an LSP server which allows IDEs such as VS Code to display diagnostics in Noir source. + +VS Code Noir Language Support: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir + +**Usage:** `nargo lsp` + + + +
+ + + This document was generated automatically by + clap-markdown. + + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/tutorials/noirjs_app.md new file mode 100644 index 00000000000..ad76dd255cc --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/tutorials/noirjs_app.md @@ -0,0 +1,279 @@ +--- +title: Building a web app with NoirJS +description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment. +keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs, app] +sidebar_position: 0 +pagination_next: noir/concepts/data_types/index +--- + +NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Setup + +:::note + +Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.19.x matches `noir_js@0.19.x`, etc. + +In this guide, we will be pinned to 0.19.4. + +::: + +Before we start, we want to make sure we have Node and Nargo installed. + +We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). + +As for `Nargo`, we can follow the the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Easy enough. Onwards! + +## Our project + +ZK is a powerful technology. An app that doesn't reveal one of the inputs to *anyone* is almost unbelievable, yet Noir makes it as easy as a single line of code. + +In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! + +### Nargo + +Run: + +```nargo new circuit``` + +And... That's about it. Your program is ready to be compiled and run. + +To compile, let's `cd` into the `circuit` folder to enter our project, and call: + +```nargo compile``` + +This compiles our circuit into `json` format and add it to a new `target` folder. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit <---- our working directory + ├── Nargo.toml + ├── src + │ └── main.nr + └── target + └── circuit.json +``` + +::: + +### Node and Vite + +If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the +[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. + +Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. + +To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". + +You should see `vite-project` appear in your root folder. This seems like a good time to `cd` into it and install our NoirJS packages: + +```bash +npm i @noir-lang/backend_barretenberg@0.19.4 @noir-lang/noir_js@0.19.4 +``` + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...etc... +└── vite-project <---- our working directory + └── ...etc... +``` + +::: + +#### Some cleanup + +`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `index.html`, `main.js` and `package.json`. I feel lighter already. + +![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) + +## HTML + +Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: + +```html + + + + + + +

Noir app

+
+ + +
+
+

Logs

+

Proof

+
+ + +``` + +It *could* be a beautiful UI... Depending on which universe you live in. + +## Some good old vanilla Javascript + +Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). + +Start by pasting in this boilerplate code: + +```js +const setup = async () => { + await Promise.all([ + import("@noir-lang/noirc_abi").then(module => + module.default(new URL("@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm", import.meta.url).toString()) + ), + import("@noir-lang/acvm_js").then(module => + module.default(new URL("@noir-lang/acvm_js/web/acvm_js_bg.wasm", import.meta.url).toString()) + ) + ]); +} + +function display(container, msg) { + const c = document.getElementById(container); + const p = document.createElement('p'); + p.textContent = msg; + c.appendChild(p); +} + +document.getElementById('submitGuess').addEventListener('click', async () => { + try { + // here's where love happens + } catch(err) { + display("logs", "Oh 💔 Wrong guess") + } +}); + +``` + +The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 + +As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...same as above +└── vite-project + ├── main.js + ├── package.json + └── index.html +``` + +You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. + +::: + +## Some NoirJS + +We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: + +```ts +import circuit from '../circuit/target/circuit.json'; +``` + +[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: + +```js +import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { Noir } from '@noir-lang/noir_js'; +``` + +And instantiate them inside our try-catch block: + +```ts +// try { +const backend = new BarretenbergBackend(circuit); +const noir = new Noir(circuit, backend); +// } +``` + +:::note + +For the remainder of the tutorial, everything will be happening inside the `try` block + +::: + +## Our app + +Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: + +```js +const x = parseInt(document.getElementById('guessInput').value); +const input = { x, y: 2 }; +``` + +Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: + +```js +await setup(); // let's squeeze our wasm inits here + +display('logs', 'Generating proof... ⌛'); +const proof = await noir.generateFinalProof(input); +display('logs', 'Generating proof... ✅'); +display('results', proof.proof); +``` + +You're probably eager to see stuff happening, so go and run your app now! + +From your terminal, run `npm run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. + +![Getting Started 0](@site/static/img/noir_getting_started_1.png) + +Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! + +By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. + +## Verifying + +Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: + +```js +display('logs', 'Verifying proof... ⌛'); +const verification = await noir.verifyFinalProof(proof); +if (verification) display('logs', 'Verifying proof... ✅'); +``` + +You have successfully generated a client-side Noir web app! + +![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) + +## Further Reading + +You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. + +You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.25.0-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.25.0-sidebars.json new file mode 100644 index 00000000000..b16f79cc176 --- /dev/null +++ b/noir/noir-repo/docs/versioned_sidebars/version-v0.25.0-sidebars.json @@ -0,0 +1,83 @@ +{ + "sidebar": [ + { + "type": "doc", + "id": "index" + }, + { + "type": "category", + "label": "Getting Started", + "items": [ + { + "type": "autogenerated", + "dirName": "getting_started" + } + ] + }, + { + "type": "category", + "label": "The Noir Language", + "items": [ + { + "type": "autogenerated", + "dirName": "noir" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "category", + "label": "How To Guides", + "items": [ + { + "type": "autogenerated", + "dirName": "how_to" + } + ] + }, + { + "type": "category", + "label": "Explainers", + "items": [ + { + "type": "autogenerated", + "dirName": "explainers" + } + ] + }, + { + "type": "category", + "label": "Tutorials", + "items": [ + { + "type": "autogenerated", + "dirName": "tutorials" + } + ] + }, + { + "type": "category", + "label": "Reference", + "items": [ + { + "type": "autogenerated", + "dirName": "reference" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "doc", + "id": "migration_notes", + "label": "Migration notes" + } + ] +} diff --git a/noir/noir-repo/flake.nix b/noir/noir-repo/flake.nix index 5125dad06be..785d5aead56 100644 --- a/noir/noir-repo/flake.nix +++ b/noir/noir-repo/flake.nix @@ -73,7 +73,7 @@ # Configuration shared between builds config = { # x-release-please-start-version - version = "0.24.0"; + version = "0.25.0"; # x-release-please-end src = pkgs.lib.cleanSourceWith { diff --git a/noir/noir-repo/noir_stdlib/src/bigint.nr b/noir/noir-repo/noir_stdlib/src/bigint.nr index 98237a54779..e7fc28ba39b 100644 --- a/noir/noir-repo/noir_stdlib/src/bigint.nr +++ b/noir/noir-repo/noir_stdlib/src/bigint.nr @@ -1,6 +1,7 @@ use crate::ops::{Add, Sub, Mul, Div}; use crate::cmp::Eq; +// docs:start:curve_order_base global bn254_fq = [0x47, 0xFD, 0x7C, 0xD8, 0x16, 0x8C, 0x20, 0x3C, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, 0x97, 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30]; global bn254_fr = [0x01, 0x00, 0x00, 0x00, 0x3F, 0x59, 0x1F, 0x43, 0x09, 0x97, 0xB9, 0x79, 0x48, 0xE8, 0x33, 0x28, @@ -13,6 +14,7 @@ global secpr1_fq = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF]; global secpr1_fr = [0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3, 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,0xFF, 0xFF, 0xFF, 0xFF]; +// docs:end:curve_order_base struct BigInt { pointer: u32, diff --git a/noir/noir-repo/noir_stdlib/src/collections/map.nr b/noir/noir-repo/noir_stdlib/src/collections/map.nr index 056299b4238..2d76acf1f3a 100644 --- a/noir/noir-repo/noir_stdlib/src/collections/map.nr +++ b/noir/noir-repo/noir_stdlib/src/collections/map.nr @@ -3,6 +3,7 @@ use crate::collections::vec::Vec; use crate::option::Option; use crate::default::Default; use crate::hash::{Hash, Hasher, BuildHasher}; +use crate::collections::bounded_vec::BoundedVec; // We use load factor α_max = 0.75. // Upon exceeding it, assert will fail in order to inform the user @@ -78,21 +79,26 @@ impl Slot { // it is very unlikely to be after - performance will be heavily degraded. impl HashMap { // Creates a new instance of HashMap with specified BuildHasher. + // docs:start:with_hasher pub fn with_hasher(_build_hasher: B) -> Self where B: BuildHasher { + // docs:end:with_hasher let _table = [Slot::default(); N]; let _len = 0; Self { _table, _len, _build_hasher } } // Clears the map, removing all key-value entries. + // docs:start:clear pub fn clear(&mut self) { + // docs:end:clear self._table = [Slot::default(); N]; self._len = 0; } // Returns true if the map contains a value for the specified key. + // docs:start:contains_key pub fn contains_key( self, key: K @@ -101,89 +107,80 @@ impl HashMap { K: Hash + Eq, B: BuildHasher, H: Hasher { + // docs:end:contains_key self.get(key).is_some() } // Returns true if the map contains no elements. + // docs:start:is_empty pub fn is_empty(self) -> bool { + // docs:end:is_empty self._len == 0 } - // Get the Option<(K, V) array of valid entries - // with a length of map capacity. First len() elements - // are safe to unwrap_unchecked(), whilst remaining - // are guaranteed to be Option::none(). - // - // This design is reasoned by compile-time limitations and - // temporary nested slices ban. - pub fn entries(self) -> [Option<(K, V)>; N] { - let mut entries = [Option::none(); N]; - let mut valid_amount = 0; + // Returns a BoundedVec of all valid entries in this HashMap. + // The length of the returned vector will always match the length of this HashMap. + // docs:start:entries + pub fn entries(self) -> BoundedVec<(K, V), N> { + // docs:end:entries + let mut entries = BoundedVec::new(); for slot in self._table { if slot.is_valid() { - entries[valid_amount] = slot.key_value(); - valid_amount += 1; + // SAFETY: slot.is_valid() should ensure there is a valid key-value pairing here + let key_value = slot.key_value().unwrap_unchecked(); + entries.push(key_value); } } - let msg = f"Amount of valid elements should have been {self._len} times, but got {valid_amount}."; - assert(valid_amount == self._len, msg); + let msg = f"Amount of valid elements should have been {self._len} times, but got {entries.len()}."; + assert(entries.len() == self._len, msg); entries } - // Get the Option array of valid keys - // with a length of map capacity. First len() elements - // are safe to unwrap_unchecked(), whilst remaining - // are guaranteed to be Option::none(). - // - // This design is reasoned by compile-time limitations and - // temporary nested slices ban. - pub fn keys(self) -> [Option; N] { - let mut keys = [Option::none(); N]; - let mut valid_amount = 0; + // Returns a BoundedVec containing all the keys within this HashMap. + // The length of the returned vector will always match the length of this HashMap. + // docs:start:keys + pub fn keys(self) -> BoundedVec { + // docs:end:keys + let mut keys = BoundedVec::new(); for slot in self._table { if slot.is_valid() { let (key, _) = slot.key_value_unchecked(); - keys[valid_amount] = Option::some(key); - valid_amount += 1; + keys.push(key); } } - let msg = f"Amount of valid elements should have been {self._len} times, but got {valid_amount}."; - assert(valid_amount == self._len, msg); + let msg = f"Amount of valid elements should have been {self._len} times, but got {keys.len()}."; + assert(keys.len() == self._len, msg); keys } - // Get the Option array of valid values - // with a length of map capacity. First len() elements - // are safe to unwrap_unchecked(), whilst remaining - // are guaranteed to be Option::none(). - // - // This design is reasoned by compile-time limitations and - // temporary nested slices ban. - pub fn values(self) -> [Option; N] { - let mut values = [Option::none(); N]; - let mut valid_amount = 0; + // Returns a BoundedVec containing all the values within this HashMap. + // The length of the returned vector will always match the length of this HashMap. + // docs:start:values + pub fn values(self) -> BoundedVec { + // docs:end:values + let mut values = BoundedVec::new(); for slot in self._table { if slot.is_valid() { let (_, value) = slot.key_value_unchecked(); - values[valid_amount] = Option::some(value); - valid_amount += 1; + values.push(value); } } - let msg = f"Amount of valid elements should have been {self._len} times, but got {valid_amount}."; - assert(valid_amount == self._len, msg); + let msg = f"Amount of valid elements should have been {self._len} times, but got {values.len()}."; + assert(values.len() == self._len, msg); values } // For each key-value entry applies mutator function. + // docs:start:iter_mut pub fn iter_mut( &mut self, f: fn(K, V) -> (K, V) @@ -192,12 +189,13 @@ impl HashMap { K: Eq + Hash, B: BuildHasher, H: Hasher { + // docs:end:iter_mut let mut entries = self.entries(); let mut new_map = HashMap::with_hasher(self._build_hasher); for i in 0..N { if i < self._len { - let entry = entries[i].unwrap_unchecked(); + let entry = entries.get_unchecked(i); let (key, value) = f(entry.0, entry.1); new_map.insert(key, value); } @@ -207,6 +205,7 @@ impl HashMap { } // For each key applies mutator function. + // docs:start:iter_keys_mut pub fn iter_keys_mut( &mut self, f: fn(K) -> K @@ -215,12 +214,13 @@ impl HashMap { K: Eq + Hash, B: BuildHasher, H: Hasher { + // docs:end:iter_keys_mut let mut entries = self.entries(); let mut new_map = HashMap::with_hasher(self._build_hasher); for i in 0..N { if i < self._len { - let entry = entries[i].unwrap_unchecked(); + let entry = entries.get_unchecked(i); let (key, value) = (f(entry.0), entry.1); new_map.insert(key, value); } @@ -230,7 +230,9 @@ impl HashMap { } // For each value applies mutator function. + // docs:start:iter_values_mut pub fn iter_values_mut(&mut self, f: fn(V) -> V) { + // docs:end:iter_values_mut for i in 0..N { let mut slot = self._table[i]; if slot.is_valid() { @@ -242,7 +244,9 @@ impl HashMap { } // Retains only the elements specified by the predicate. + // docs:start:retain pub fn retain(&mut self, f: fn(K, V) -> bool) { + // docs:end:retain for index in 0..N { let mut slot = self._table[index]; if slot.is_valid() { @@ -257,16 +261,21 @@ impl HashMap { } // Amount of active key-value entries. + // docs:start:len pub fn len(self) -> u64 { + // docs:end:len self._len } // Get the compile-time map capacity. + // docs:start:capacity pub fn capacity(_self: Self) -> u64 { + // docs:end:capacity N } // Get the value by key. If it does not exist, returns none(). + // docs:start:get pub fn get( self, key: K @@ -275,6 +284,7 @@ impl HashMap { K: Eq + Hash, B: BuildHasher, H: Hasher { + // docs:end:get let mut result = Option::none(); let hash = self.hash(key); @@ -300,6 +310,7 @@ impl HashMap { } // Insert key-value entry. In case key was already present, value is overridden. + // docs:start:insert pub fn insert( &mut self, key: K, @@ -309,6 +320,7 @@ impl HashMap { K: Eq + Hash, B: BuildHasher, H: Hasher { + // docs:end:insert self.assert_load_factor(); let hash = self.hash(key); @@ -340,7 +352,8 @@ impl HashMap { } } - // Remove key-value entry. If key is not present, HashMap remains unchanged. + // Removes a key-value entry. If key is not present, HashMap remains unchanged. + // docs:start:remove pub fn remove( &mut self, key: K @@ -349,6 +362,7 @@ impl HashMap { K: Eq + Hash, B: BuildHasher, H: Hasher { + // docs:end:remove let hash = self.hash(key); let mut break = false; @@ -409,6 +423,7 @@ impl HashMap { // Equality class on HashMap has to test that they have // equal sets of key-value entries, // thus one is a subset of the other and vice versa. +// docs:start:eq impl Eq for HashMap where K: Eq + Hash, @@ -416,7 +431,8 @@ where B: BuildHasher, H: Hasher { - fn eq(self, other: HashMap) -> bool{ + fn eq(self, other: HashMap) -> bool { +// docs:end:eq let mut equal = false; if self.len() == other.len(){ @@ -443,12 +459,14 @@ where } } +// docs:start:default impl Default for HashMap where B: BuildHasher + Default, H: Hasher + Default { - fn default() -> Self{ + fn default() -> Self { +// docs:end:default let _build_hasher = B::default(); let map: HashMap = HashMap::with_hasher(_build_hasher); map diff --git a/noir/noir-repo/noir_stdlib/src/eddsa.nr b/noir/noir-repo/noir_stdlib/src/eddsa.nr index 966bc1da2a1..3aff6043ffd 100644 --- a/noir/noir-repo/noir_stdlib/src/eddsa.nr +++ b/noir/noir-repo/noir_stdlib/src/eddsa.nr @@ -1,6 +1,8 @@ use crate::hash::poseidon; use crate::ec::consts::te::baby_jubjub; use crate::ec::tecurve::affine::Point as TEPoint; +use crate::hash::{Hash, Hasher, BuildHasher, BuildHasherDefault}; +use crate::hash::poseidon::PoseidonHasher; // Returns true if signature is valid pub fn eddsa_poseidon_verify( @@ -11,6 +13,28 @@ pub fn eddsa_poseidon_verify( signature_r8_y: Field, message: Field ) -> bool { + let mut hasher = PoseidonHasher::default(); + eddsa_verify_with_hasher( + pub_key_x, + pub_key_y, + signature_s, + signature_r8_x, + signature_r8_y, + message, + &mut hasher + ) +} + +pub fn eddsa_verify_with_hasher( + pub_key_x: Field, + pub_key_y: Field, + signature_s: Field, + signature_r8_x: Field, + signature_r8_y: Field, + message: Field, + hasher: &mut H +) -> bool +where H: Hasher { // Verifies by testing: // S * B8 = R8 + H(R8, A, m) * A8 let bjj = baby_jubjub(); @@ -23,7 +47,12 @@ pub fn eddsa_poseidon_verify( // Ensure S < Subgroup Order assert(signature_s.lt(bjj.suborder)); // Calculate the h = H(R, A, msg) - let hash: Field = poseidon::bn254::hash_5([signature_r8_x, signature_r8_y, pub_key_x, pub_key_y, message]); + signature_r8_x.hash(hasher); + signature_r8_y.hash(hasher); + pub_key_x.hash(hasher); + pub_key_y.hash(hasher); + message.hash(hasher); + let hash: Field = (*hasher).finish(); // Calculate second part of the right side: right2 = h*8*A // Multiply by 8 by doubling 3 times. This also ensures that the result is in the subgroup. let pub_key_mul_2 = bjj.curve.add(pub_key, pub_key); diff --git a/noir/noir-repo/noir_stdlib/src/hash/mimc.nr b/noir/noir-repo/noir_stdlib/src/hash/mimc.nr index 10c0a48917c..db8a32d7909 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/mimc.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/mimc.nr @@ -1,3 +1,6 @@ +use crate::hash::Hasher; +use crate::default::Default; + // mimc-p/p implementation // constants are (publicly generated) random numbers, for instance using keccak as a ROM. // You must use constants generated for the native field @@ -16,13 +19,8 @@ fn mimc(x: Field, k: Field, constants: [Field; N], exp: Field) -> Field { } global MIMC_BN254_ROUNDS = 91; -//mimc implementation with hardcoded parameters for BN254 curve. -#[field(bn254)] -pub fn mimc_bn254(array: [Field; N]) -> Field { - //mimc parameters - let exponent = 7; - //generated from seed "mimc" using keccak256 - let constants: [Field; MIMC_BN254_ROUNDS] = [ +//generated from seed "mimc" using keccak256 +global MIMC_BN254_CONSTANTS: [Field; MIMC_BN254_ROUNDS] = [ 0, 20888961410941983456478427210666206549300505294776164667214940546594746570981, 15265126113435022738560151911929040668591755459209400716467504685752745317193, @@ -116,10 +114,46 @@ pub fn mimc_bn254(array: [Field; N]) -> Field { 13602139229813231349386885113156901793661719180900395818909719758150455500533 ]; +//mimc implementation with hardcoded parameters for BN254 curve. +#[field(bn254)] +pub fn mimc_bn254(array: [Field; N]) -> Field { + let exponent = 7; let mut r = 0; for elem in array { - let h = mimc(elem, r, constants, exponent); + let h = mimc(elem, r, MIMC_BN254_CONSTANTS, exponent); r = r + elem + h; } r } + +struct MimcHasher{ + _state: [Field], + _len: u64, +} + +impl Hasher for MimcHasher { + #[field(bn254)] + fn finish(self) -> Field { + let exponent = 7; + let mut r = 0; + for i in 0..self._len { + let h = mimc(self._state[i], r, MIMC_BN254_CONSTANTS, exponent); + r = r + self._state[i] + h; + } + r + } + + fn write(&mut self, input: [Field]){ + self._state = self._state.append(input); + self._len += input.len(); + } +} + +impl Default for MimcHasher{ + fn default() -> Self{ + MimcHasher{ + _state: [], + _len: 0, + } + } +} diff --git a/noir/noir-repo/noir_stdlib/src/hash/poseidon.nr b/noir/noir-repo/noir_stdlib/src/hash/poseidon.nr index b1a7c4a2367..7f99ad36316 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/poseidon.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/poseidon.nr @@ -1,5 +1,7 @@ mod bn254; // Instantiations of Poseidon for prime field of the same order as BN254 use crate::field::modulus_num_bits; +use crate::hash::Hasher; +use crate::default::Default; struct PoseidonConfig { t: Field, // Width, i.e. state size @@ -100,3 +102,77 @@ fn apply_matrix(a: [Field; M], x: [Field; N]) -> [Field; N] { y } + +struct PoseidonHasher{ + _state: [Field], + _len: u64, +} + +impl Hasher for PoseidonHasher { + #[field(bn254)] + fn finish(self) -> Field { + let mut result = 0; + assert(self._len < 16); + if self._len == 1 { + result = bn254::hash_1([self._state[0]]); + } + if self._len == 2 { + result = bn254::hash_2([self._state[0],self._state[1]]); + } + if self._len == 3 { + result = bn254::hash_3([self._state[0],self._state[1],self._state[2]]); + } + if self._len == 4 { + result = bn254::hash_4([self._state[0],self._state[1],self._state[2],self._state[3]]); + } + if self._len == 5 { + result = bn254::hash_5([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4]]); + } + if self._len == 6 { + result = bn254::hash_6([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5]]); + } + if self._len == 7 { + result = bn254::hash_7([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6]]); + } + if self._len == 8 { + result = bn254::hash_8([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7]]); + } + if self._len == 9 { + result = bn254::hash_9([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8]]); + } + if self._len == 10 { + result = bn254::hash_10([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9]]); + } + if self._len == 11 { + result = bn254::hash_11([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10]]); + } + if self._len == 12 { + result = bn254::hash_12([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10], self._state[11]]); + } + if self._len == 13 { + result = bn254::hash_13([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10], self._state[11], self._state[12]]); + } + if self._len == 14 { + result = bn254::hash_14([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10], self._state[11], self._state[12], self._state[13]]); + } + if self._len == 15 { + result = bn254::hash_15([self._state[0],self._state[1],self._state[2],self._state[3],self._state[4], self._state[5], self._state[6], self._state[7], self._state[8], self._state[9], self._state[10], self._state[11], self._state[12], self._state[13], self._state[14]]); + } + + result + } + + fn write(&mut self, input: [Field]){ + self._state = self._state.append(input); + self._len += input.len(); + } +} + +impl Default for PoseidonHasher{ + fn default() -> Self{ + PoseidonHasher{ + _state: [], + _len: 0, + } + } +} diff --git a/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr b/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr index 40eea029e82..52229f18dbd 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr @@ -1,3 +1,6 @@ +use crate::hash::Hasher; +use crate::default::Default; + global RATE = 3; struct Poseidon2 { @@ -9,7 +12,7 @@ struct Poseidon2 { impl Poseidon2 { - pub fn hash(input: [Field; N], message_size: u32) -> Field { + pub fn hash(input: [Field; N], message_size: u64) -> Field { if message_size == N { Poseidon2::hash_internal(input, N, false) } else { @@ -92,12 +95,12 @@ impl Poseidon2 { result } - fn hash_internal(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field { + fn hash_internal(input: [Field; N], in_len: u64, is_variable_length: bool) -> Field { let two_pow_64 = 18446744073709551616; let iv : Field = (in_len as Field) * two_pow_64; let mut sponge = Poseidon2::new(iv); for i in 0..input.len() { - if i as u32 < in_len { + if i < in_len { sponge.absorb(input[i]); } } @@ -111,3 +114,33 @@ impl Poseidon2 { sponge.squeeze() } } + +struct Poseidon2Hasher{ + _state: [Field], + _len: u64, +} + +impl Hasher for Poseidon2Hasher { + fn finish(self) -> Field { + let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64) + let mut sponge = Poseidon2::new(iv); + for i in 0..self._len { + sponge.absorb(self._state[i]); + } + sponge.squeeze() + } + + fn write(&mut self, input: [Field]){ + self._state = self._state.append(input); + self._len += input.len(); + } +} + +impl Default for Poseidon2Hasher{ + fn default() -> Self{ + Poseidon2Hasher{ + _state: [], + _len: 0, + } + } +} diff --git a/noir/noir-repo/noir_stdlib/src/internal.nr b/noir/noir-repo/noir_stdlib/src/internal.nr new file mode 100644 index 00000000000..8d5c01dda7f --- /dev/null +++ b/noir/noir-repo/noir_stdlib/src/internal.nr @@ -0,0 +1,12 @@ +// This file contains functions which should only be used in calls injected by the Noir compiler. +// These functions should not be called manually in user code. +// +// Changes to this file will not be considered breaking. + +#[oracle(assert_message)] +unconstrained fn assert_message_oracle(_input: T) {} +unconstrained pub fn resolve_assert_message(input: T, condition: bool) { + if !condition { + assert_message_oracle(input); + } +} diff --git a/noir/noir-repo/noir_stdlib/src/lib.nr b/noir/noir-repo/noir_stdlib/src/lib.nr index ebde4b88858..90c04472066 100644 --- a/noir/noir-repo/noir_stdlib/src/lib.nr +++ b/noir/noir-repo/noir_stdlib/src/lib.nr @@ -26,6 +26,7 @@ mod default; mod prelude; mod uint128; mod bigint; +mod internal; // Oracle calls are required to be wrapped in an unconstrained function // Thus, the only argument to the `println` oracle is expected to always be an ident diff --git a/noir/noir-repo/noirc_macros/Cargo.toml b/noir/noir-repo/noirc_macros/Cargo.toml deleted file mode 100644 index 699e6b01cae..00000000000 --- a/noir/noir-repo/noirc_macros/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "noirc_macros" -version.workspace = true -authors.workspace = true -edition.workspace = true -rust-version.workspace = true -license.workspace = true -repository.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -noirc_frontend.workspace = true -iter-extended.workspace = true \ No newline at end of file diff --git a/noir/noir-repo/noirc_macros/src/lib.rs b/noir/noir-repo/noirc_macros/src/lib.rs deleted file mode 100644 index 9a916843200..00000000000 --- a/noir/noir-repo/noirc_macros/src/lib.rs +++ /dev/null @@ -1,73 +0,0 @@ -use noirc_frontend::hir::def_collector::dc_crate::UnresolvedFunctions; -use noirc_frontend::hir::def_collector::dc_crate::UnresolvedTraitImpl; -use noirc_frontend::macros_api::parse_program; -use noirc_frontend::macros_api::HirContext; -use noirc_frontend::macros_api::SortedModule; -use noirc_frontend::macros_api::{CrateId, FileId}; -use noirc_frontend::macros_api::{MacroError, MacroProcessor}; - -pub struct AssertMessageMacro; - -impl MacroProcessor for AssertMessageMacro { - fn process_untyped_ast( - &self, - ast: SortedModule, - crate_id: &CrateId, - _context: &HirContext, - ) -> Result { - transform(ast, crate_id) - } - - fn process_unresolved_traits_impls( - &self, - _crate_id: &CrateId, - _context: &mut HirContext, - _unresolved_traits_impls: &[UnresolvedTraitImpl], - _collected_functions: &mut Vec, - ) -> Result<(), (MacroError, FileId)> { - Ok(()) - } - - // This macro does not need to process any information after name resolution - fn process_typed_ast( - &self, - _crate_id: &CrateId, - _context: &mut HirContext, - ) -> Result<(), (MacroError, FileId)> { - Ok(()) - } -} - -fn transform(ast: SortedModule, crate_id: &CrateId) -> Result { - let ast = add_resolve_assert_message_funcs(ast, crate_id)?; - - Ok(ast) -} - -fn add_resolve_assert_message_funcs( - mut ast: SortedModule, - crate_id: &CrateId, -) -> Result { - if !crate_id.is_stdlib() { - return Ok(ast); - } - let assert_message_oracles = " - #[oracle(assert_message)] - unconstrained fn assert_message_oracle(_input: T) {} - unconstrained pub fn resolve_assert_message(input: T, condition: bool) { - if !condition { - assert_message_oracle(input); - } - }"; - - let (assert_msg_funcs_ast, errors) = parse_program(assert_message_oracles); - assert_eq!(errors.len(), 0, "Failed to parse Noir macro code. This is either a bug in the compiler or the Noir macro code"); - - let assert_msg_funcs_ast = assert_msg_funcs_ast.into_sorted(); - - for func in assert_msg_funcs_ast.functions { - ast.functions.push(func) - } - - Ok(ast) -} diff --git a/noir/noir-repo/test_programs/compile_success_contract/simple_contract/src/main.nr b/noir/noir-repo/test_programs/compile_success_contract/simple_contract/src/main.nr index 4ef12cb890d..7412e1386bf 100644 --- a/noir/noir-repo/test_programs/compile_success_contract/simple_contract/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_contract/simple_contract/src/main.nr @@ -8,9 +8,6 @@ contract Foo { fn quadruple(x: Field) -> pub Field { x * 4 } - open fn skibbidy(x: Field) -> pub Field { - x * 5 - } // Regression for issue #3344 #[contract_library_method] fn foo(x: u8) -> u8 { diff --git a/noir/noir-repo/test_programs/execution_success/bigint/src/main.nr b/noir/noir-repo/test_programs/execution_success/bigint/src/main.nr index b93fec370e5..b6c23276c15 100644 --- a/noir/noir-repo/test_programs/execution_success/bigint/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/bigint/src/main.nr @@ -1,4 +1,5 @@ use dep::std::bigint; +use dep::std::{bigint::Secpk1Fq, println}; fn main(mut x: [u8; 5], y: [u8; 5]) { let a = bigint::Secpk1Fq::from_le_bytes([x[0], x[1], x[2], x[3], x[4]]); @@ -13,4 +14,15 @@ fn main(mut x: [u8; 5], y: [u8; 5]) { let d = a * b - b; let d1 = bigint::Secpk1Fq::from_le_bytes(597243850900842442924.to_le_bytes(10)); assert(d1 == d); + // big_int_example(x[0], x[1]); } + +// docs:start:big_int_example +fn big_int_example(x: u8, y: u8) { + let a = Secpk1Fq::from_le_bytes([x, y, 0, 45, 2]); + let b = Secpk1Fq::from_le_bytes([y, x, 9]); + let c = (a + b) * b / a; + let d = c.to_le_bytes(); + println(d[0]); +} +// docs:end:big_int_example diff --git a/noir/noir-repo/test_programs/execution_success/brillig_cow_assign/Nargo.toml b/noir/noir-repo/test_programs/execution_success/brillig_cow_assign/Nargo.toml new file mode 100644 index 00000000000..a878566a372 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/brillig_cow_assign/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "brillig_cow_assign" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/brillig_cow_assign/Prover.toml b/noir/noir-repo/test_programs/execution_success/brillig_cow_assign/Prover.toml new file mode 100644 index 00000000000..882c73b83f8 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/brillig_cow_assign/Prover.toml @@ -0,0 +1,2 @@ +items_to_update = 10 +index = 6 diff --git a/noir/noir-repo/test_programs/execution_success/brillig_cow_assign/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_cow_assign/src/main.nr new file mode 100644 index 00000000000..e5c3e2bd2f5 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/brillig_cow_assign/src/main.nr @@ -0,0 +1,23 @@ +global N = 10; + +unconstrained fn main() { + let mut arr = [0; N]; + let mut mid_change = arr; + + for i in 0..N { + if i == N / 2 { + mid_change = arr; + } + arr[i] = 27; + } + + // Expect: + // arr = [27, 27, 27, 27, 27, 27, 27, 27, 27, 27] + // mid_change = [27, 27, 27, 27, 27, 0, 0, 0, 0, 0] + + let modified_i = N / 2 + 1; + assert_eq(arr[modified_i], 27); + + // Fail here! + assert(mid_change[modified_i] != 27); +} diff --git a/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr b/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr index 4404ffe75f7..fd1a95ee5fb 100644 --- a/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr @@ -2,7 +2,9 @@ use dep::std::compat; use dep::std::ec::consts::te::baby_jubjub; use dep::std::ec::tecurve::affine::Point as TEPoint; use dep::std::hash; -use dep::std::eddsa::{eddsa_to_pub, eddsa_poseidon_verify}; +use dep::std::eddsa::{eddsa_to_pub, eddsa_poseidon_verify, eddsa_verify_with_hasher}; +use dep::std::hash::poseidon2::Poseidon2Hasher; +use dep::std::hash::pedersen::PedersenHasher; fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) { // Skip this test for non-bn254 backends @@ -48,5 +50,11 @@ fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) { assert(!eddsa_poseidon_verify(pub_key_a.x, pub_key_a.y, s_b, r8_b.x, r8_b.y, msg)); // User A's signature over the message can't be used with another message assert(!eddsa_poseidon_verify(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg + 1)); + // Using a different hash should fail + let mut hasher = Poseidon2Hasher::default(); + assert(!eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher)); + // Using a different hash should fail + let mut hasher = PedersenHasher::default(); + assert(!eddsa_verify_with_hasher(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg, &mut hasher)); } } diff --git a/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr b/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr index 597a5c0b7de..4d2cbd45993 100644 --- a/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr @@ -37,6 +37,8 @@ fn main(input: [Entry; HASHMAP_LEN]) { test_retain(); test_iterators(); test_mut_iterators(); + + doc_tests(); } // Insert, get, remove. @@ -154,9 +156,9 @@ fn test_iterators() { hashmap.insert(5, 7); hashmap.insert(11, 13); - let keys: [K; 3] = cut(hashmap.keys()).map(|k: Option| k.unwrap_unchecked()).sort_via(K_CMP); - let values: [V; 3] = cut(hashmap.values()).map(|v: Option| v.unwrap_unchecked()).sort_via(V_CMP); - let entries: [(K, V); 3] = cut(hashmap.entries()).map(|e: Option<(K, V)>| e.unwrap_unchecked()).sort_via(KV_CMP); + let keys: [K; 3] = cut(hashmap.keys()).sort_via(K_CMP); + let values: [V; 3] = cut(hashmap.values()).sort_via(V_CMP); + let entries: [(K, V); 3] = cut(hashmap.entries()).sort_via(KV_CMP); assert(keys == [2, 5, 11], "Got incorrect iteration of keys."); assert(values == [3, 7, 13], "Got incorrect iteration of values."); @@ -177,8 +179,8 @@ fn test_mut_iterators() { let f = |v: V| -> V{ v * 5}; hashmap.iter_values_mut(f); - let keys: [K; 3] = cut(hashmap.keys()).map(|k: Option| k.unwrap_unchecked()).sort_via(K_CMP); - let values: [V; 3] = cut(hashmap.values()).map(|v: Option| v.unwrap_unchecked()).sort_via(V_CMP); + let keys: [K; 3] = cut(hashmap.keys()).sort_via(K_CMP); + let values: [V; 3] = cut(hashmap.values()).sort_via(V_CMP); assert(keys == [6, 15, 33], f"Got incorrect iteration of keys: {keys}"); assert(values == [15, 35, 65], "Got incorrect iteration of values."); @@ -186,7 +188,175 @@ fn test_mut_iterators() { let f = |k: K, v: V| -> (K, V){(k * 2, v * 2)}; hashmap.iter_mut(f); - let entries: [(K, V); 3] = cut(hashmap.entries()).map(|e: Option<(K, V)>| e.unwrap_unchecked()).sort_via(KV_CMP); + let entries: [(K, V); 3] = cut(hashmap.entries()).sort_via(KV_CMP); assert(entries == [(12, 30), (30, 70), (66, 130)], "Got incorrect iteration of entries."); } + +// docs:start:type_alias +type MyMap = HashMap>; +// docs:end:type_alias + +/// Tests examples from the stdlib hashmap documentation +fn doc_tests() { + // docs:start:default_example + let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); + // docs:end:default_example + + // docs:start:with_hasher_example + let my_hasher: BuildHasherDefault = Default::default(); + let hashmap: HashMap> = HashMap::with_hasher(my_hasher); + assert(hashmap.is_empty()); + // docs:end:with_hasher_example + + // docs:start:insert_example + let mut map: HashMap> = HashMap::default(); + map.insert(12, 42); + assert(map.len() == 1); + // docs:end:insert_example + + get_example(map); + + // docs:start:remove_example + map.remove(12); + assert(map.is_empty()); + + // If a key was not present in the map, remove does nothing + map.remove(12); + assert(map.is_empty()); + // docs:end:remove_example + + // docs:start:is_empty_example + assert(map.is_empty()); + + map.insert(1, 2); + assert(!map.is_empty()); + + map.remove(1); + assert(map.is_empty()); + // docs:end:is_empty_example + + // docs:start:len_example + // This is equivalent to checking map.is_empty() + assert(map.len() == 0); + + map.insert(1, 2); + map.insert(3, 4); + map.insert(5, 6); + assert(map.len() == 3); + + // 3 was already present as a key in the hash map, so the length is unchanged + map.insert(3, 7); + assert(map.len() == 3); + + map.remove(1); + assert(map.len() == 2); + // docs:end:len_example + + // docs:start:capacity_example + let empty_map: HashMap> = HashMap::default(); + assert(empty_map.len() == 0); + assert(empty_map.capacity() == 42); + // docs:end:capacity_example + + // docs:start:clear_example + assert(!map.is_empty()); + map.clear(); + assert(map.is_empty()); + // docs:end:clear_example + + // docs:start:contains_key_example + if map.contains_key(7) { + let value = map.get(7); + assert(value.is_some()); + } else { + println("No value for key 7!"); + } + // docs:end:contains_key_example + + entries_examples(map); + iter_examples(map); + + // docs:start:retain_example + map.retain(|k, v| (k != 0) & (v != 0)); + // docs:end:retain_example + + // docs:start:eq_example + let mut map1: HashMap> = HashMap::default(); + let mut map2: HashMap> = HashMap::default(); + + map1.insert(1, 2); + map1.insert(3, 4); + + map2.insert(3, 4); + map2.insert(1, 2); + + assert(map1 == map2); + // docs:end:eq_example +} + +// docs:start:get_example +fn get_example(map: HashMap>) { + let x = map.get(12); + + if x.is_some() { + assert(x.unwrap() == 42); + } +} +// docs:end:get_example + +fn entries_examples(map: HashMap>) { + // docs:start:entries_example + let entries = map.entries(); + + // The length of a hashmap may not be compile-time known, so we + // need to loop over its capacity instead + for i in 0..map.capacity() { + if i < entries.len() { + let (key, value) = entries.get(i); + println(f"{key} -> {value}"); + } + } + // docs:end:entries_example + + // docs:start:keys_example + let keys = map.keys(); + + for i in 0..keys.max_len() { + if i < keys.len() { + let key = keys.get_unchecked(i); + let value = map.get(key).unwrap_unchecked(); + println(f"{key} -> {value}"); + } + } + // docs:end:keys_example + + // docs:start:values_example + let values = map.values(); + + for i in 0..values.max_len() { + if i < values.len() { + let value = values.get_unchecked(i); + println(f"Found value {value}"); + } + } + // docs:end:values_example +} + +fn iter_examples(mut map: HashMap>) { + // docs:start:iter_mut_example + // Add 1 to each key in the map, and double the value associated with that key. + map.iter_mut(|k, v| (k + 1, v * 2)); + // docs:end:iter_mut_example + + // docs:start:iter_keys_mut_example + // Double each key, leaving the value associated with that key untouched + map.iter_keys_mut(|k| k * 2); + // docs:end:iter_keys_mut_example + + // docs:start:iter_values_mut_example + // Halve each value + map.iter_values_mut(|v| v / 2); + // docs:end:iter_values_mut_example +} diff --git a/noir/noir-repo/test_programs/execution_success/hashmap/src/utils.nr b/noir/noir-repo/test_programs/execution_success/hashmap/src/utils.nr index 45c9ca9bbf7..ee73245a902 100644 --- a/noir/noir-repo/test_programs/execution_success/hashmap/src/utils.nr +++ b/noir/noir-repo/test_programs/execution_success/hashmap/src/utils.nr @@ -1,10 +1,10 @@ -// Compile-time: cuts the M first elements from the [T; N] array. -pub(crate) fn cut(input: [T; N]) -> [T; M] { - assert(M as u64 < N as u64, "M should be less than N."); +// Compile-time: cuts the M first elements from the BoundedVec. +pub(crate) fn cut(input: BoundedVec) -> [T; M] { + assert(M < N, "M should be less than N."); - let mut new = [dep::std::unsafe::zeroed(); M]; + let mut new = BoundedVec::new(); for i in 0..M { - new[i] = input[i]; + new.push(input.get(i)); } - new + new.storage() } diff --git a/noir/noir-repo/test_programs/execution_success/poseidon_bn254_hash/src/main.nr b/noir/noir-repo/test_programs/execution_success/poseidon_bn254_hash/src/main.nr index 939b99595c7..a1607956190 100644 --- a/noir/noir-repo/test_programs/execution_success/poseidon_bn254_hash/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/poseidon_bn254_hash/src/main.nr @@ -9,7 +9,7 @@ fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field let hash2 = poseidon::bn254::hash_4(x2); assert(hash2 == y2); - let hash3 = poseidon2::Poseidon2::hash(x3, x3.len() as u32); + let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); assert(hash3 == y3); } // docs:end:poseidon diff --git a/noir/noir-repo/test_programs/execution_success/regression_4449/Nargo.toml b/noir/noir-repo/test_programs/execution_success/regression_4449/Nargo.toml new file mode 100644 index 00000000000..925420a03a8 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_4449/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_4449" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/regression_4449/Prover.toml b/noir/noir-repo/test_programs/execution_success/regression_4449/Prover.toml new file mode 100644 index 00000000000..81af476bcc9 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_4449/Prover.toml @@ -0,0 +1,3 @@ + +x = 0xbd +result = [204, 59, 83, 197, 18, 1, 128, 43, 247, 28, 104, 225, 106, 13, 20, 187, 42, 26, 67, 150, 48, 75, 238, 168, 121, 247, 142, 160, 71, 222, 97, 188] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/regression_4449/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_4449/src/main.nr new file mode 100644 index 00000000000..454a93f5d1a --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_4449/src/main.nr @@ -0,0 +1,14 @@ +// Regression test for issue #4449 +use dep::std; + +fn main(x: u8, result: [u8; 32]) { + let x = x % 31; + let mut digest = [0; 32]; + for i in 0..70 { + let y = x + i; + let a = [y, x, 32, 0, y + 1, y - 1, y - 2, 5]; + digest = std::sha256::digest(a); + } + + assert(digest == result); +} diff --git a/noir/noir-repo/test_programs/execution_success/slices/src/main.nr b/noir/noir-repo/test_programs/execution_success/slices/src/main.nr index eca42a660c4..e44edf872a4 100644 --- a/noir/noir-repo/test_programs/execution_success/slices/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/slices/src/main.nr @@ -50,6 +50,10 @@ fn main(x: Field, y: pub Field) { // The parameters to this function must come from witness values (inputs to main) regression_merge_slices(x, y); regression_2370(); + + regression_4418(x); + regression_slice_call_result(x, y); + regression_4506(); } // Ensure that slices of struct/tuple values work. fn regression_2083() { @@ -297,3 +301,32 @@ fn regression_2370() { let mut slice = []; slice = [1, 2, 3]; } + +fn regression_4418(x: Field) { + let mut crash = x.to_be_bytes(32); + + if x != 0 { + crash[0] = 10; + } +} + +fn regression_slice_call_result(x: Field, y: Field) { + let mut slice = merge_slices_return(x, y); + if x != 0 { + slice = slice.push_back(5); + slice = slice.push_back(10); + } else { + slice = slice.push_back(5); + } + assert(slice.len() == 5); + assert(slice[0] == 0); + assert(slice[1] == 0); + assert(slice[2] == 10); + assert(slice[3] == 5); + assert(slice[4] == 10); +} + +fn regression_4506() { + let slice: [Field] = [1, 2, 3]; + assert(slice == slice); +} diff --git a/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs index f6337c2eb35..255b6131fd6 100644 --- a/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs @@ -62,18 +62,17 @@ pub(crate) fn run(args: ExecuteCommand) -> Result { pub(crate) fn execute_program_from_witness( inputs_map: &WitnessMap, - bytecode: &Vec, + bytecode: &[u8], foreign_call_resolver_url: Option<&str>, ) -> Result { let blackbox_solver = Bn254BlackBoxSolver::new(); - let circuit: Circuit = Circuit::deserialize_circuit(&bytecode) + let circuit: Circuit = Circuit::deserialize_circuit(bytecode) .map_err(|_| CliError::CircuitDeserializationError())?; - let result = execute_circuit( + execute_circuit( &circuit, inputs_map.clone(), &blackbox_solver, &mut DefaultForeignCallExecutor::new(true, foreign_call_resolver_url), ) - .map_err(|e| CliError::CircuitExecutionError(e)); - result + .map_err(CliError::CircuitExecutionError) } diff --git a/noir/noir-repo/tooling/bb_abstraction_leaks/build.rs b/noir/noir-repo/tooling/bb_abstraction_leaks/build.rs index f9effd5d991..0bd2b1c076a 100644 --- a/noir/noir-repo/tooling/bb_abstraction_leaks/build.rs +++ b/noir/noir-repo/tooling/bb_abstraction_leaks/build.rs @@ -10,7 +10,7 @@ use const_format::formatcp; const USERNAME: &str = "AztecProtocol"; const REPO: &str = "aztec-packages"; -const VERSION: &str = "0.24.0"; +const VERSION: &str = "0.26.3"; const TAG: &str = formatcp!("aztec-packages-v{}", VERSION); const API_URL: &str = diff --git a/noir/noir-repo/tooling/debugger/ignored-tests.txt b/noir/noir-repo/tooling/debugger/ignored-tests.txt index c472e828739..231d4d897a9 100644 --- a/noir/noir-repo/tooling/debugger/ignored-tests.txt +++ b/noir/noir-repo/tooling/debugger/ignored-tests.txt @@ -1,21 +1,13 @@ array_dynamic_blackbox_input -array_sort -assign_ex +bigint bit_shifts_comptime -brillig_cow -brillig_nested_arrays brillig_references brillig_to_bytes_integration debug_logs double_verify_nested_proof double_verify_proof modulus -nested_array_dynamic -nested_array_in_slice -nested_arrays_from_brillig references scalar_mul signed_comparison -simple_2d_array to_bytes_integration -bigint diff --git a/noir/noir-repo/tooling/debugger/src/context.rs b/noir/noir-repo/tooling/debugger/src/context.rs index 515edf0bb06..a3ee89263a4 100644 --- a/noir/noir-repo/tooling/debugger/src/context.rs +++ b/noir/noir-repo/tooling/debugger/src/context.rs @@ -8,11 +8,14 @@ use acvm::pwg::{ }; use acvm::{BlackBoxFunctionSolver, FieldElement}; -use nargo::artifacts::debug::DebugArtifact; +use codespan_reporting::files::{Files, SimpleFile}; +use fm::FileId; +use nargo::artifacts::debug::{DebugArtifact, StackFrame}; use nargo::errors::{ExecutionError, Location}; use nargo::NargoError; -use noirc_printable_type::{PrintableType, PrintableValue}; +use noirc_driver::DebugFile; +use std::collections::BTreeMap; use std::collections::{hash_set::Iter, HashSet}; #[derive(Debug)] @@ -29,6 +32,7 @@ pub(super) struct DebugContext<'a, B: BlackBoxFunctionSolver> { foreign_call_executor: Box, debug_artifact: &'a DebugArtifact, breakpoints: HashSet, + source_to_opcodes: BTreeMap>, } impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { @@ -39,12 +43,14 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { initial_witness: WitnessMap, foreign_call_executor: Box, ) -> Self { + let source_to_opcodes = build_source_to_opcode_debug_mappings(debug_artifact); Self { acvm: ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness), brillig_solver: None, foreign_call_executor, debug_artifact, breakpoints: HashSet::new(), + source_to_opcodes, } } @@ -100,10 +106,50 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { self.debug_artifact .file_map .get(&location.file) - .map(|file| file.path.starts_with("__debug/")) + .map(is_debug_file_in_debug_crate) .unwrap_or(false) } + /// Find an opcode location matching a source code location + // We apply some heuristics here, and there are four possibilities for the + // return value of this function: + // 1. the source location is not found -> None + // 2. an exact unique location is found (very rare) -> Some(opcode_location) + // 3. an exact but not unique location is found, ie. a source location may + // be mapped to multiple opcodes, and those may be disjoint, for example for + // functions called multiple times throughout the program + // -> return the first opcode in program order that matches the source location + // 4. exact location is not found, so an opcode for a nearby source location + // is returned (this again could actually be more than one opcodes) + // -> return the opcode for the next source line that is mapped + pub(super) fn find_opcode_for_source_location( + &self, + file_id: &FileId, + line: i64, + ) -> Option { + let line = line as usize; + let Some(line_to_opcodes) = self.source_to_opcodes.get(file_id) else { + return None; + }; + let found_index = match line_to_opcodes.binary_search_by(|x| x.0.cmp(&line)) { + Ok(index) => { + // move backwards to find the first opcode which matches the line + let mut index = index; + while index > 0 && line_to_opcodes[index - 1].0 == line { + index -= 1; + } + line_to_opcodes[index].1 + } + Err(index) => { + if index >= line_to_opcodes.len() { + return None; + } + line_to_opcodes[index].1 + } + }; + Some(found_index) + } + /// Returns the callstack in source code locations for the currently /// executing opcode. This can be `None` if the execution finished (and /// `get_current_opcode_location()` returns `None`) or if the opcode is not @@ -128,6 +174,9 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { &self, opcode_location: &OpcodeLocation, ) -> Vec { + // TODO: this assumes we're debugging a program (ie. the DebugArtifact + // will contain a single DebugInfo), but this assumption doesn't hold + // for contracts self.debug_artifact.debug_symbols[0] .opcode_location(opcode_location) .map(|source_locations| { @@ -467,10 +516,14 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { } } - pub(super) fn get_variables(&self) -> Vec<(&str, &PrintableValue, &PrintableType)> { + pub(super) fn get_variables(&self) -> Vec { return self.foreign_call_executor.get_variables(); } + pub(super) fn current_stack_frame(&self) -> Option { + return self.foreign_call_executor.current_stack_frame(); + } + fn breakpoint_reached(&self) -> bool { if let Some(location) = self.get_current_opcode_location() { self.breakpoints.contains(&location) @@ -526,6 +579,52 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { } } +fn is_debug_file_in_debug_crate(debug_file: &DebugFile) -> bool { + debug_file.path.starts_with("__debug/") +} + +/// Builds a map from FileId to an ordered vector of tuples with line +/// numbers and opcode locations corresponding to those line numbers +fn build_source_to_opcode_debug_mappings( + debug_artifact: &DebugArtifact, +) -> BTreeMap> { + if debug_artifact.debug_symbols.is_empty() { + return BTreeMap::new(); + } + let locations = &debug_artifact.debug_symbols[0].locations; + let simple_files: BTreeMap<_, _> = debug_artifact + .file_map + .iter() + .filter(|(_, debug_file)| !is_debug_file_in_debug_crate(debug_file)) + .map(|(file_id, debug_file)| { + ( + file_id, + SimpleFile::new(debug_file.path.to_str().unwrap(), debug_file.source.as_str()), + ) + }) + .collect(); + + let mut result: BTreeMap> = BTreeMap::new(); + locations.iter().for_each(|(opcode_location, source_locations)| { + source_locations.iter().for_each(|source_location| { + let span = source_location.span; + let file_id = source_location.file; + let Some(file) = simple_files.get(&file_id) else { + return; + }; + let Ok(line_index) = file.line_index((), span.start() as usize) else { + return; + }; + let line_number = line_index + 1; + + result.entry(file_id).or_default().push((line_number, *opcode_location)); + }); + }); + result.iter_mut().for_each(|(_, file_locations)| file_locations.sort_by_key(|x| (x.0, x.1))); + + result +} + #[cfg(test)] mod tests { use super::*; diff --git a/noir/noir-repo/tooling/debugger/src/dap.rs b/noir/noir-repo/tooling/debugger/src/dap.rs index 7e67a26b257..7c722ed0a61 100644 --- a/noir/noir-repo/tooling/debugger/src/dap.rs +++ b/noir/noir-repo/tooling/debugger/src/dap.rs @@ -5,7 +5,6 @@ use std::str::FromStr; use acvm::acir::circuit::{Circuit, OpcodeLocation}; use acvm::acir::native_types::WitnessMap; use acvm::BlackBoxFunctionSolver; -use codespan_reporting::files::{Files, SimpleFile}; use crate::context::DebugCommandResult; use crate::context::DebugContext; @@ -30,15 +29,16 @@ use nargo::artifacts::debug::DebugArtifact; use fm::FileId; use noirc_driver::CompiledProgram; +type BreakpointId = i64; + pub struct DapSession<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> { server: Server, context: DebugContext<'a, B>, debug_artifact: &'a DebugArtifact, running: bool, - source_to_opcodes: BTreeMap>, - next_breakpoint_id: i64, - instruction_breakpoints: Vec<(OpcodeLocation, i64)>, - source_breakpoints: BTreeMap>, + next_breakpoint_id: BreakpointId, + instruction_breakpoints: Vec<(OpcodeLocation, BreakpointId)>, + source_breakpoints: BTreeMap>, } enum ScopeReferences { @@ -57,8 +57,6 @@ impl From for ScopeReferences { } } -// BTreeMap - impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { pub fn new( server: Server, @@ -67,7 +65,6 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { debug_artifact: &'a DebugArtifact, initial_witness: WitnessMap, ) -> Self { - let source_to_opcodes = Self::build_source_to_opcode_debug_mappings(debug_artifact); let context = DebugContext::new( solver, circuit, @@ -79,7 +76,6 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { server, context, debug_artifact, - source_to_opcodes, running: false, next_breakpoint_id: 1, instruction_breakpoints: vec![], @@ -87,46 +83,6 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { } } - /// Builds a map from FileId to an ordered vector of tuples with line - /// numbers and opcode locations corresponding to those line numbers - fn build_source_to_opcode_debug_mappings( - debug_artifact: &'a DebugArtifact, - ) -> BTreeMap> { - if debug_artifact.debug_symbols.is_empty() { - return BTreeMap::new(); - } - let locations = &debug_artifact.debug_symbols[0].locations; - let simple_files: BTreeMap<_, _> = debug_artifact - .file_map - .iter() - .map(|(file_id, debug_file)| { - ( - file_id, - SimpleFile::new(debug_file.path.to_str().unwrap(), debug_file.source.as_str()), - ) - }) - .collect(); - - let mut result: BTreeMap> = BTreeMap::new(); - locations.iter().for_each(|(opcode_location, source_locations)| { - if source_locations.is_empty() { - return; - } - let source_location = source_locations[0]; - let span = source_location.span; - let file_id = source_location.file; - let Ok(line_index) = &simple_files[&file_id].line_index((), span.start() as usize) - else { - return; - }; - let line_number = line_index + 1; - - result.entry(file_id).or_default().push((line_number, *opcode_location)); - }); - result.iter_mut().for_each(|(_, file_locations)| file_locations.sort_by_key(|x| x.0)); - result - } - fn send_stopped_event(&mut self, reason: StoppedEventReason) -> Result<(), ServerError> { let description = format!("{:?}", &reason); self.server.send_event(Event::Stopped(StoppedEventBody { @@ -230,6 +186,8 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { } fn build_stack_trace(&self) -> Vec { + let stack_frames = self.context.get_variables(); + self.context .get_source_call_stack() .iter() @@ -239,9 +197,15 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { self.debug_artifact.location_line_number(*source_location).unwrap(); let column_number = self.debug_artifact.location_column_number(*source_location).unwrap(); + + let name = match stack_frames.get(index) { + Some(frame) => format!("{} {}", frame.function_name, index), + None => format!("frame #{index}"), + }; + StackFrame { id: index as i64, - name: format!("frame #{index}"), + name, source: Some(Source { path: self.debug_artifact.file_map[&source_location.file] .path @@ -422,7 +386,7 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { Ok(()) } - fn get_next_breakpoint_id(&mut self) -> i64 { + fn get_next_breakpoint_id(&mut self) -> BreakpointId { let id = self.next_breakpoint_id; self.next_breakpoint_id += 1; id @@ -493,36 +457,6 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { found.map(|iter| *iter.0) } - // TODO: there are four possibilities for the return value of this function: - // 1. the source location is not found -> None - // 2. an exact unique location is found -> Some(opcode_location) - // 3. an exact but not unique location is found (ie. a source location may - // be mapped to multiple opcodes, and those may be disjoint, for example for - // functions called multiple times throughout the program) - // 4. exact location is not found, so an opcode for a nearby source location - // is returned (this again could actually be more than one opcodes) - // Case 3 is not supported yet, and 4 is not correctly handled. - fn find_opcode_for_source_location( - &self, - file_id: &FileId, - line: i64, - ) -> Option { - let line = line as usize; - let Some(line_to_opcodes) = self.source_to_opcodes.get(file_id) else { - return None; - }; - let found_index = match line_to_opcodes.binary_search_by(|x| x.0.cmp(&line)) { - Ok(index) => line_to_opcodes[index].1, - Err(index) => { - if index >= line_to_opcodes.len() { - return None; - } - line_to_opcodes[index].1 - } - }; - Some(found_index) - } - fn map_source_breakpoints(&mut self, args: &SetBreakpointsArguments) -> Vec { let Some(ref source) = &args.source.path else { return vec![]; @@ -539,7 +473,8 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { .iter() .map(|breakpoint| { let line = breakpoint.line; - let Some(location) = self.find_opcode_for_source_location(&file_id, line) else { + let Some(location) = self.context.find_opcode_for_source_location(&file_id, line) + else { return Breakpoint { verified: false, message: Some(String::from( @@ -608,16 +543,20 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { } fn build_local_variables(&self) -> Vec { - let mut variables: Vec<_> = self - .context - .get_variables() + let Some(current_stack_frame) = self.context.current_stack_frame() else { + return vec![]; + }; + + let mut variables = current_stack_frame + .variables .iter() .map(|(name, value, _var_type)| Variable { name: String::from(*name), value: format!("{:?}", *value), ..Variable::default() }) - .collect(); + .collect::>(); + variables.sort_by(|a, b| a.name.partial_cmp(&b.name).unwrap()); variables } diff --git a/noir/noir-repo/tooling/debugger/src/foreign_calls.rs b/noir/noir-repo/tooling/debugger/src/foreign_calls.rs index 68c4d3947b0..25f126ff490 100644 --- a/noir/noir-repo/tooling/debugger/src/foreign_calls.rs +++ b/noir/noir-repo/tooling/debugger/src/foreign_calls.rs @@ -3,17 +3,19 @@ use acvm::{ pwg::ForeignCallWaitInfo, }; use nargo::{ - artifacts::debug::{DebugArtifact, DebugVars}, + artifacts::debug::{DebugArtifact, DebugVars, StackFrame}, ops::{DefaultForeignCallExecutor, ForeignCallExecutor, NargoForeignCallResult}, }; -use noirc_errors::debug_info::DebugVarId; -use noirc_printable_type::{ForeignCallError, PrintableType, PrintableValue}; +use noirc_errors::debug_info::{DebugFnId, DebugVarId}; +use noirc_printable_type::ForeignCallError; pub(crate) enum DebugForeignCall { VarAssign, VarDrop, MemberAssign(u32), DerefAssign, + FnEnter, + FnExit, } impl DebugForeignCall { @@ -28,13 +30,16 @@ impl DebugForeignCall { "__debug_var_assign" => Some(DebugForeignCall::VarAssign), "__debug_var_drop" => Some(DebugForeignCall::VarDrop), "__debug_deref_assign" => Some(DebugForeignCall::DerefAssign), + "__debug_fn_enter" => Some(DebugForeignCall::FnEnter), + "__debug_fn_exit" => Some(DebugForeignCall::FnExit), _ => None, } } } pub trait DebugForeignCallExecutor: ForeignCallExecutor { - fn get_variables(&self) -> Vec<(&str, &PrintableValue, &PrintableType)>; + fn get_variables(&self) -> Vec; + fn current_stack_frame(&self) -> Option; } pub struct DefaultDebugForeignCallExecutor { @@ -57,23 +62,33 @@ impl DefaultDebugForeignCallExecutor { } pub fn load_artifact(&mut self, artifact: &DebugArtifact) { - artifact.debug_symbols.iter().for_each(|info| { - self.debug_vars.insert_variables(&info.variables); - self.debug_vars.insert_types(&info.types); - }); + // TODO: handle loading from the correct DebugInfo when we support + // debugging contracts + let Some(info) = artifact.debug_symbols.get(0) else { + return; + }; + self.debug_vars.insert_debug_info(info); } } impl DebugForeignCallExecutor for DefaultDebugForeignCallExecutor { - fn get_variables(&self) -> Vec<(&str, &PrintableValue, &PrintableType)> { + fn get_variables(&self) -> Vec { self.debug_vars.get_variables() } + + fn current_stack_frame(&self) -> Option { + self.debug_vars.current_stack_frame() + } } fn debug_var_id(value: &Value) -> DebugVarId { DebugVarId(value.to_u128() as u32) } +fn debug_fn_id(value: &Value) -> DebugFnId { + DebugFnId(value.to_u128() as u32) +} + impl ForeignCallExecutor for DefaultDebugForeignCallExecutor { fn execute( &mut self, @@ -136,6 +151,19 @@ impl ForeignCallExecutor for DefaultDebugForeignCallExecutor { } Ok(ForeignCallResult::default().into()) } + Some(DebugForeignCall::FnEnter) => { + let fcp_fn_id = &foreign_call.inputs[0]; + let ForeignCallParam::Single(fn_id_value) = fcp_fn_id else { + panic!("unexpected foreign call parameter in fn enter: {fcp_fn_id:?}") + }; + let fn_id = debug_fn_id(fn_id_value); + self.debug_vars.push_fn(fn_id); + Ok(ForeignCallResult::default().into()) + } + Some(DebugForeignCall::FnExit) => { + self.debug_vars.pop_fn(); + Ok(ForeignCallResult::default().into()) + } None => self.executor.execute(foreign_call), } } diff --git a/noir/noir-repo/tooling/debugger/src/repl.rs b/noir/noir-repo/tooling/debugger/src/repl.rs index 8441dbde9be..41dbf604f99 100644 --- a/noir/noir-repo/tooling/debugger/src/repl.rs +++ b/noir/noir-repo/tooling/debugger/src/repl.rs @@ -337,11 +337,13 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { } pub fn show_vars(&self) { - let vars = self.context.get_variables(); - for (var_name, value, var_type) in vars.iter() { - let printable_value = - PrintableValueDisplay::Plain((*value).clone(), (*var_type).clone()); - println!("{var_name}:{var_type:?} = {}", printable_value); + for frame in self.context.get_variables() { + println!("{}({})", frame.function_name, frame.function_params.join(", ")); + for (var_name, value, var_type) in frame.variables.iter() { + let printable_value = + PrintableValueDisplay::Plain((*value).clone(), (*var_type).clone()); + println!(" {var_name}:{var_type:?} = {}", printable_value); + } } } @@ -530,7 +532,7 @@ pub fn run( .add( "vars", command! { - "show variable values available at this point in execution", + "show variables for each function scope available at this point in execution", () => || { ref_context.borrow_mut().show_vars(); Ok(CommandStatus::Done) diff --git a/noir/noir-repo/tooling/debugger/src/source_code_printer.rs b/noir/noir-repo/tooling/debugger/src/source_code_printer.rs index b5ffdb12d01..e298eb8aadd 100644 --- a/noir/noir-repo/tooling/debugger/src/source_code_printer.rs +++ b/noir/noir-repo/tooling/debugger/src/source_code_printer.rs @@ -30,7 +30,7 @@ struct LocationPrintContext { // Given a DebugArtifact and an OpcodeLocation, prints all the source code // locations the OpcodeLocation maps to, with some surrounding context and // visual aids to highlight the location itself. -pub(crate) fn print_source_code_location(debug_artifact: &DebugArtifact, locations: &[Location]) { +pub(super) fn print_source_code_location(debug_artifact: &DebugArtifact, locations: &[Location]) { let locations = locations.iter(); for loc in locations { @@ -269,8 +269,12 @@ mod tests { let mut opcode_locations = BTreeMap::>::new(); opcode_locations.insert(OpcodeLocation::Acir(42), vec![loc]); - let debug_symbols = - vec![DebugInfo::new(opcode_locations, BTreeMap::default(), BTreeMap::default())]; + let debug_symbols = vec![DebugInfo::new( + opcode_locations, + BTreeMap::default(), + BTreeMap::default(), + BTreeMap::default(), + )]; let debug_artifact = DebugArtifact::new(debug_symbols, &fm); let location_rendered: Vec<_> = render_location(&debug_artifact, &loc).collect(); diff --git a/noir/noir-repo/tooling/debugger/tests/debug.rs b/noir/noir-repo/tooling/debugger/tests/debug.rs index 4cb678192b8..143ee7987f8 100644 --- a/noir/noir-repo/tooling/debugger/tests/debug.rs +++ b/noir/noir-repo/tooling/debugger/tests/debug.rs @@ -12,7 +12,7 @@ mod tests { let nargo_bin = cargo_bin("nargo").into_os_string().into_string().expect("Cannot parse nargo path"); - let mut dbg_session = spawn_bash(Some(10000)).expect("Could not start bash session"); + let mut dbg_session = spawn_bash(Some(15000)).expect("Could not start bash session"); // Set backend to `/dev/null` to force an error if nargo tries to speak to a backend. dbg_session diff --git a/noir/noir-repo/tooling/lsp/src/requests/test_run.rs b/noir/noir-repo/tooling/lsp/src/requests/test_run.rs index 0b88d814265..1844a3d9bf0 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/test_run.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/test_run.rs @@ -84,7 +84,7 @@ fn on_test_run_request_inner( let test_result = run_test( &state.solver, &mut context, - test_function, + &test_function, false, None, &CompileOptions::default(), diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs b/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs index d928b09fcb9..020ce49662f 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs +++ b/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs @@ -1,6 +1,6 @@ use acvm::acir::circuit::Circuit; use noirc_abi::{Abi, ContractEvent}; -use noirc_driver::{CompiledContract, ContractFunction, ContractFunctionType}; +use noirc_driver::{CompiledContract, ContractFunction}; use serde::{Deserialize, Serialize}; use noirc_driver::DebugFile; @@ -43,9 +43,9 @@ impl From for ContractArtifact { pub struct ContractFunctionArtifact { pub name: String, - pub function_type: ContractFunctionType, + pub is_unconstrained: bool, - pub is_internal: bool, + pub custom_attributes: Vec, pub abi: Abi, @@ -66,8 +66,8 @@ impl From for ContractFunctionArtifact { fn from(func: ContractFunction) -> Self { ContractFunctionArtifact { name: func.name, - function_type: func.function_type, - is_internal: func.is_internal, + is_unconstrained: func.is_unconstrained, + custom_attributes: func.custom_attributes, abi: func.abi, bytecode: func.bytecode, debug_symbols: func.debug, diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/debug.rs b/noir/noir-repo/tooling/nargo/src/artifacts/debug.rs index a249ecb03ad..fbdf59805c9 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/debug.rs +++ b/noir/noir-repo/tooling/nargo/src/artifacts/debug.rs @@ -8,7 +8,7 @@ use std::{ ops::Range, }; -pub use super::debug_vars::DebugVars; +pub use super::debug_vars::{DebugVars, StackFrame}; use fm::{FileId, FileManager, PathString}; /// A Debug Artifact stores, for a given program, the debug info for every function @@ -231,8 +231,12 @@ mod tests { let mut opcode_locations = BTreeMap::>::new(); opcode_locations.insert(OpcodeLocation::Acir(42), vec![loc]); - let debug_symbols = - vec![DebugInfo::new(opcode_locations, BTreeMap::default(), BTreeMap::default())]; + let debug_symbols = vec![DebugInfo::new( + opcode_locations, + BTreeMap::default(), + BTreeMap::default(), + BTreeMap::default(), + )]; let debug_artifact = DebugArtifact::new(debug_symbols, &fm); let location_in_line = debug_artifact.location_in_line(loc).expect("Expected a range"); diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/debug_vars.rs b/noir/noir-repo/tooling/nargo/src/artifacts/debug_vars.rs index 20f2637f7d6..66568bec833 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/debug_vars.rs +++ b/noir/noir-repo/tooling/nargo/src/artifacts/debug_vars.rs @@ -1,54 +1,85 @@ use acvm::brillig_vm::brillig::Value; use noirc_errors::debug_info::{ - DebugTypeId, DebugTypes, DebugVarId, DebugVariable, DebugVariables, + DebugFnId, DebugFunction, DebugInfo, DebugTypeId, DebugVarId, DebugVariable, }; use noirc_printable_type::{decode_value, PrintableType, PrintableValue}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; #[derive(Debug, Default, Clone)] pub struct DebugVars { variables: HashMap, + functions: HashMap, types: HashMap, - active: HashSet, - values: HashMap, + frames: Vec<(DebugFnId, HashMap)>, +} + +pub struct StackFrame<'a> { + pub function_name: &'a str, + pub function_params: Vec<&'a str>, + pub variables: Vec<(&'a str, &'a PrintableValue, &'a PrintableType)>, } impl DebugVars { - pub fn get_variables(&self) -> Vec<(&str, &PrintableValue, &PrintableType)> { - self.active - .iter() - .filter_map(|var_id| { - self.variables.get(var_id).and_then(|debug_var| { - let Some(value) = self.values.get(var_id) else { - return None; - }; - let Some(ptype) = self.types.get(&debug_var.debug_type_id) else { - return None; - }; - Some((debug_var.name.as_str(), value, ptype)) - }) - }) - .collect() + pub fn insert_debug_info(&mut self, info: &DebugInfo) { + self.variables.extend(info.variables.clone()); + self.types.extend(info.types.clone()); + self.functions.extend(info.functions.clone()); + } + + pub fn get_variables(&self) -> Vec { + self.frames.iter().map(|(fn_id, frame)| self.build_stack_frame(fn_id, frame)).collect() } - pub fn insert_variables(&mut self, vars: &DebugVariables) { - self.variables.extend(vars.clone()); + pub fn current_stack_frame(&self) -> Option { + self.frames.last().map(|(fn_id, frame)| self.build_stack_frame(fn_id, frame)) } - pub fn insert_types(&mut self, types: &DebugTypes) { - self.types.extend(types.clone()); + fn lookup_var(&self, var_id: DebugVarId) -> Option<(&str, &PrintableType)> { + self.variables.get(&var_id).and_then(|debug_var| { + let Some(ptype) = self.types.get(&debug_var.debug_type_id) else { + return None; + }; + Some((debug_var.name.as_str(), ptype)) + }) + } + + fn build_stack_frame<'a>( + &'a self, + fn_id: &DebugFnId, + frame: &'a HashMap, + ) -> StackFrame { + let debug_fn = &self.functions.get(fn_id).expect("failed to find function metadata"); + + let params: Vec<&str> = + debug_fn.arg_names.iter().map(|arg_name| arg_name.as_str()).collect(); + let vars: Vec<(&str, &PrintableValue, &PrintableType)> = frame + .iter() + .filter_map(|(var_id, var_value)| { + self.lookup_var(*var_id).map(|(name, typ)| (name, var_value, typ)) + }) + .collect(); + + StackFrame { + function_name: debug_fn.name.as_str(), + function_params: params, + variables: vars, + } } pub fn assign_var(&mut self, var_id: DebugVarId, values: &[Value]) { - self.active.insert(var_id); let type_id = &self.variables.get(&var_id).unwrap().debug_type_id; let ptype = self.types.get(type_id).unwrap(); - self.values.insert(var_id, decode_value(&mut values.iter().map(|v| v.to_field()), ptype)); + + self.frames + .last_mut() + .expect("unexpected empty stack frames") + .1 + .insert(var_id, decode_value(&mut values.iter().map(|v| v.to_field()), ptype)); } pub fn assign_field(&mut self, var_id: DebugVarId, indexes: Vec, values: &[Value]) { - let mut cursor: &mut PrintableValue = self - .values + let current_frame = &mut self.frames.last_mut().expect("unexpected empty stack frames").1; + let mut cursor: &mut PrintableValue = current_frame .get_mut(&var_id) .unwrap_or_else(|| panic!("value unavailable for var_id {var_id:?}")); let cursor_type_id = &self @@ -102,7 +133,6 @@ impl DebugVars { }; } *cursor = decode_value(&mut values.iter().map(|v| v.to_field()), cursor_type); - self.active.insert(var_id); } pub fn assign_deref(&mut self, _var_id: DebugVarId, _values: &[Value]) { @@ -114,6 +144,14 @@ impl DebugVars { } pub fn drop_var(&mut self, var_id: DebugVarId) { - self.active.remove(&var_id); + self.frames.last_mut().expect("unexpected empty stack frames").1.remove(&var_id); + } + + pub fn push_fn(&mut self, fn_id: DebugFnId) { + self.frames.push((fn_id, HashMap::default())); + } + + pub fn pop_fn(&mut self) { + self.frames.pop(); } } diff --git a/noir/noir-repo/tooling/nargo/src/ops/test.rs b/noir/noir-repo/tooling/nargo/src/ops/test.rs index 92c09ec889e..8ddcb5cf8d2 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/test.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/test.rs @@ -14,10 +14,16 @@ pub enum TestStatus { CompileError(FileDiagnostic), } +impl TestStatus { + pub fn failed(&self) -> bool { + !matches!(self, TestStatus::Pass) + } +} + pub fn run_test( blackbox_solver: &B, context: &mut Context, - test_function: TestFunction, + test_function: &TestFunction, show_output: bool, foreign_call_resolver_url: Option<&str>, config: &CompileOptions, @@ -45,7 +51,7 @@ pub fn run_test( /// that a constraint was never satisfiable. /// An example of this is the program `assert(false)` /// In that case, we check if the test function should fail, and if so, we return `TestStatus::Pass`. -fn test_status_program_compile_fail(err: CompileError, test_function: TestFunction) -> TestStatus { +fn test_status_program_compile_fail(err: CompileError, test_function: &TestFunction) -> TestStatus { // The test has failed compilation, but it should never fail. Report error. if !test_function.should_fail() { return TestStatus::CompileError(err.into()); @@ -70,7 +76,7 @@ fn test_status_program_compile_fail(err: CompileError, test_function: TestFuncti /// We now check whether execution passed/failed and whether it should have /// passed/failed to determine the test status. fn test_status_program_compile_pass( - test_function: TestFunction, + test_function: &TestFunction, debug: DebugInfo, circuit_execution: Result, ) -> TestStatus { @@ -109,7 +115,7 @@ fn test_status_program_compile_pass( } fn check_expected_failure_message( - test_function: TestFunction, + test_function: &TestFunction, failed_assertion: Option, error_diagnostic: Option, ) -> TestStatus { diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs index 68660d62d23..2828aaf01eb 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs @@ -5,17 +5,18 @@ use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; use fm::FileManager; use nargo::{ - insert_all_files_for_workspace_into_file_manager, - ops::{run_test, TestStatus}, - package::Package, - parse_all, prepare_package, + insert_all_files_for_workspace_into_file_manager, ops::TestStatus, package::Package, parse_all, + prepare_package, }; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{file_manager_with_stdlib, CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_driver::{ + check_crate, file_manager_with_stdlib, CompileOptions, NOIR_ARTIFACT_VERSION_STRING, +}; use noirc_frontend::{ graph::CrateName, hir::{FunctionNameMatch, ParsedFiles}, }; +use rayon::prelude::{IntoParallelIterator, ParallelBridge, ParallelIterator}; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; use crate::{backends::Backend, cli::check_cmd::check_crate_and_report_errors, errors::CliError}; @@ -82,15 +83,13 @@ pub(crate) fn run( None => FunctionNameMatch::Anything, }; - let blackbox_solver = Bn254BlackBoxSolver::new(); - let test_reports: Vec> = workspace .into_iter() + .par_bridge() .map(|package| { - run_tests( + run_tests::( &workspace_file_manager, &parsed_files, - &blackbox_solver, package, pattern, args.show_output, @@ -116,24 +115,95 @@ pub(crate) fn run( }; } - if test_report.iter().any(|(_, status)| matches!(status, TestStatus::Fail { .. })) { + if test_report.iter().any(|(_, status)| status.failed()) { Err(CliError::Generic(String::new())) } else { Ok(()) } } -#[allow(clippy::too_many_arguments)] -fn run_tests( +fn run_tests( file_manager: &FileManager, parsed_files: &ParsedFiles, - blackbox_solver: &S, package: &Package, fn_name: FunctionNameMatch, show_output: bool, foreign_call_resolver_url: Option<&str>, compile_options: &CompileOptions, ) -> Result, CliError> { + let test_functions = + get_tests_in_package(file_manager, parsed_files, package, fn_name, compile_options)?; + + let count_all = test_functions.len(); + + let plural = if count_all == 1 { "" } else { "s" }; + println!("[{}] Running {count_all} test function{plural}", package.name); + + let test_report: Vec<(String, TestStatus)> = test_functions + .into_par_iter() + .map(|test_name| { + let status = run_test::( + file_manager, + parsed_files, + package, + &test_name, + show_output, + foreign_call_resolver_url, + compile_options, + ); + + (test_name, status) + }) + .collect(); + + display_test_report(file_manager, package, compile_options, &test_report)?; + Ok(test_report) +} + +fn run_test( + file_manager: &FileManager, + parsed_files: &ParsedFiles, + package: &Package, + fn_name: &str, + show_output: bool, + foreign_call_resolver_url: Option<&str>, + compile_options: &CompileOptions, +) -> TestStatus { + // This is really hacky but we can't share `Context` or `S` across threads. + // We then need to construct a separate copy for each test. + + let (mut context, crate_id) = prepare_package(file_manager, parsed_files, package); + check_crate( + &mut context, + crate_id, + compile_options.deny_warnings, + compile_options.disable_macros, + ) + .expect("Any errors should have occurred when collecting test functions"); + + let test_functions = context + .get_all_test_functions_in_crate_matching(&crate_id, FunctionNameMatch::Exact(fn_name)); + let (_, test_function) = test_functions.first().expect("Test function should exist"); + + let blackbox_solver = S::default(); + + nargo::ops::run_test( + &blackbox_solver, + &mut context, + test_function, + show_output, + foreign_call_resolver_url, + compile_options, + ) +} + +fn get_tests_in_package( + file_manager: &FileManager, + parsed_files: &ParsedFiles, + package: &Package, + fn_name: FunctionNameMatch, + compile_options: &CompileOptions, +) -> Result, CliError> { let (mut context, crate_id) = prepare_package(file_manager, parsed_files, package); check_crate_and_report_errors( &mut context, @@ -143,30 +213,27 @@ fn run_tests( compile_options.silence_warnings, )?; - let test_functions = context.get_all_test_functions_in_crate_matching(&crate_id, fn_name); - let count_all = test_functions.len(); - - let plural = if count_all == 1 { "" } else { "s" }; - println!("[{}] Running {count_all} test function{plural}", package.name); + Ok(context + .get_all_test_functions_in_crate_matching(&crate_id, fn_name) + .into_iter() + .map(|(test_name, _)| test_name) + .collect()) +} +fn display_test_report( + file_manager: &FileManager, + package: &Package, + compile_options: &CompileOptions, + test_report: &[(String, TestStatus)], +) -> Result<(), CliError> { let writer = StandardStream::stderr(ColorChoice::Always); let mut writer = writer.lock(); - let mut test_report: Vec<(String, TestStatus)> = Vec::new(); - for (test_name, test_function) in test_functions { + for (test_name, test_status) in test_report { write!(writer, "[{}] Testing {test_name}... ", package.name) .expect("Failed to write to stderr"); writer.flush().expect("Failed to flush writer"); - let test_status = run_test( - blackbox_solver, - &mut context, - test_function, - show_output, - foreign_call_resolver_url, - compile_options, - ); - match &test_status { TestStatus::Pass { .. } => { writer @@ -181,7 +248,7 @@ fn run_tests( writeln!(writer, "FAIL\n{message}\n").expect("Failed to write to stderr"); if let Some(diag) = error_diagnostic { noirc_errors::reporter::report_all( - context.file_manager.as_file_map(), + file_manager.as_file_map(), &[diag.clone()], compile_options.deny_warnings, compile_options.silence_warnings, @@ -190,23 +257,21 @@ fn run_tests( } TestStatus::CompileError(err) => { noirc_errors::reporter::report_all( - context.file_manager.as_file_map(), + file_manager.as_file_map(), &[err.clone()], compile_options.deny_warnings, compile_options.silence_warnings, ); } } - - test_report.push((test_name, test_status)); - writer.reset().expect("Failed to reset writer"); } write!(writer, "[{}] ", package.name).expect("Failed to write to stderr"); - let count_failed = - test_report.iter().filter(|(_, status)| !matches!(status, TestStatus::Pass)).count(); + let count_all = test_report.len(); + let count_failed = test_report.iter().filter(|(_, status)| status.failed()).count(); + let plural = if count_all == 1 { "" } else { "s" }; if count_failed == 0 { writer.set_color(ColorSpec::new().set_fg(Some(Color::Green))).expect("Failed to set color"); write!(writer, "{count_all} test{plural} passed").expect("Failed to write to stderr"); @@ -231,5 +296,5 @@ fn run_tests( writer.reset().expect("Failed to reset writer"); } - Ok(test_report) + Ok(()) } diff --git a/noir/noir-repo/tooling/noir_codegen/package.json b/noir/noir-repo/tooling/noir_codegen/package.json index 6bb9d06f718..68ee7184928 100644 --- a/noir/noir-repo/tooling/noir_codegen/package.json +++ b/noir/noir-repo/tooling/noir_codegen/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.24.0", + "version": "0.25.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/noir/noir-repo/tooling/noir_js/package.json b/noir/noir-repo/tooling/noir_js/package.json index 6f1899fae52..0a40d300ea4 100644 --- a/noir/noir-repo/tooling/noir_js/package.json +++ b/noir/noir-repo/tooling/noir_js/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.24.0", + "version": "0.25.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json index 28c3609fd14..d94999f324b 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.24.0", + "version": "0.25.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", @@ -42,7 +42,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "0.24.0", + "@aztec/bb.js": "0.26.3", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, diff --git a/noir/noir-repo/tooling/noir_js_types/package.json b/noir/noir-repo/tooling/noir_js_types/package.json index a3b5c85897a..d853813303d 100644 --- a/noir/noir-repo/tooling/noir_js_types/package.json +++ b/noir/noir-repo/tooling/noir_js_types/package.json @@ -4,7 +4,7 @@ "The Noir Team " ], "packageManager": "yarn@3.5.1", - "version": "0.24.0", + "version": "0.25.0", "license": "(MIT OR Apache-2.0)", "homepage": "https://noir-lang.org/", "repository": { diff --git a/noir/noir-repo/tooling/noirc_abi_wasm/package.json b/noir/noir-repo/tooling/noirc_abi_wasm/package.json index 05fcc270402..8fb9eb314a5 100644 --- a/noir/noir-repo/tooling/noirc_abi_wasm/package.json +++ b/noir/noir-repo/tooling/noirc_abi_wasm/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.24.0", + "version": "0.25.0", "license": "(MIT OR Apache-2.0)", "homepage": "https://noir-lang.org/", "repository": { diff --git a/noir/noir-repo/yarn.lock b/noir/noir-repo/yarn.lock index f5f3a29f08a..49485193532 100644 --- a/noir/noir-repo/yarn.lock +++ b/noir/noir-repo/yarn.lock @@ -221,9 +221,9 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@npm:0.24.0": - version: 0.24.0 - resolution: "@aztec/bb.js@npm:0.24.0" +"@aztec/bb.js@npm:0.26.3": + version: 0.26.3 + resolution: "@aztec/bb.js@npm:0.26.3" dependencies: comlink: ^4.4.1 commander: ^10.0.1 @@ -231,7 +231,7 @@ __metadata: tslib: ^2.4.0 bin: bb.js: dest/node/main.js - checksum: a086dabf30084cfa526e512148b9c02f0a0770dcc19b7dca4af9a3e98612b716acc7eaac6b52c0f12d985932e866d1cb9e534ded6ac9d747f3dd021afe25de27 + checksum: 74c2b7ef5405f56472cf7c41d1c13261df07b1d5019e3ede9b63d218378e0fb73ccf5c52f1cc524505efad5799b347b497349d7c9b6fe82286014b1574f12309 languageName: node linkType: hard @@ -4396,7 +4396,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": 0.24.0 + "@aztec/bb.js": 0.26.3 "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3 diff --git a/noir/scripts/test_native.sh b/noir/scripts/test_native.sh index e106c5b719b..e8c3f27b4b7 100755 --- a/noir/scripts/test_native.sh +++ b/noir/scripts/test_native.sh @@ -9,7 +9,7 @@ export GIT_DIRTY=false export GIT_COMMIT=${COMMIT_HASH:-$(git rev-parse --verify HEAD)} cargo fmt --all --check -cargo clippy --workspace --locked --release +RUSTFLAGS=-Dwarnings cargo clippy --workspace --locked --release ./.github/scripts/cargo-binstall-install.sh cargo-binstall cargo-nextest --version 0.9.67 -y --secure diff --git a/yarn-project/archiver/README.md b/yarn-project/archiver/README.md index d2787773807..a240d07d596 100644 --- a/yarn-project/archiver/README.md +++ b/yarn-project/archiver/README.md @@ -4,8 +4,7 @@ Archiver is a service which is used to fetch data on-chain data and present them The on-chain data specifically are the following events: 1. `L2BlockProcessed` event emitted on Rollup contract, -2. `ContractDeployment` event emitted on ContractDeploymentEmitter contract, -3. `MessageAdded` event emitted on Inbox contract, +2. `MessageAdded` event emitted on Inbox contract, The interfaces defining how the data can be consumed from the archiver are `L2BlockSource`, `L2LogsSource` and `ContractDataSource`. @@ -14,4 +13,4 @@ The interfaces defining how the data can be consumed from the archiver are `L2Bl To install dependencies and build the package run `yarn install` followed by `yarn build`. To run test execute `yarn test`. -To start the service export `ETHEREUM_HOST` (defaults to `http://127.0.0.1:8545/`), `ARCHIVER_POLLING_INTERVAL` (defaults to `1000 ms`), `ROLLUP_CONTRACT_ADDRESS`, `INBOX_CONTRACT_ADDRESS`, `CONTRACT_DEPLOYMENT_EMITTER_ADDRESS` environmental variables and start the service with `yarn start`. +To start the service export `ETHEREUM_HOST` (defaults to `http://127.0.0.1:8545/`), `ARCHIVER_POLLING_INTERVAL` (defaults to `1000 ms`), `ROLLUP_CONTRACT_ADDRESS`, `INBOX_CONTRACT_ADDRESS` environmental variables and start the service with `yarn start`. diff --git a/yarn-project/archiver/src/archiver/archiver.test.ts b/yarn-project/archiver/src/archiver/archiver.test.ts index 7fd15cf32cf..a7a89c78bf5 100644 --- a/yarn-project/archiver/src/archiver/archiver.test.ts +++ b/yarn-project/archiver/src/archiver/archiver.test.ts @@ -1,15 +1,9 @@ -import { Body, ExtendedContractData, L2Block, L2BlockL2Logs, LogType } from '@aztec/circuit-types'; +import { Body, L2Block, L2BlockL2Logs, LogType } from '@aztec/circuit-types'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { sleep } from '@aztec/foundation/sleep'; -import { - AvailabilityOracleAbi, - ContractDeploymentEmitterAbi, - InboxAbi, - NewInboxAbi, - RollupAbi, -} from '@aztec/l1-artifacts'; +import { AvailabilityOracleAbi, InboxAbi, NewInboxAbi, RollupAbi } from '@aztec/l1-artifacts'; import { MockProxy, mock } from 'jest-mock-extended'; import { Chain, HttpTransport, Log, PublicClient, Transaction, encodeFunctionData, toHex } from 'viem'; @@ -25,7 +19,6 @@ describe('Archiver', () => { const newInboxAddress = EthAddress.ZERO; const registryAddress = EthAddress.ZERO; const availabilityOracleAddress = EthAddress.ZERO; - const contractDeploymentEmitterAddress = EthAddress.fromString('0x0000000000000000000000000000000000000001'); const blockNumbers = [1, 2, 3]; let publicClient: MockProxy>; let archiverStore: ArchiverDataStore; @@ -43,7 +36,6 @@ describe('Archiver', () => { inboxAddress, newInboxAddress, registryAddress, - contractDeploymentEmitterAddress, archiverStore, 1000, ); @@ -94,7 +86,6 @@ describe('Archiver', () => { .mockResolvedValueOnce([makeLeafInsertedEvent(98n, 1n, 0n), makeLeafInsertedEvent(99n, 1n, 1n)]) .mockResolvedValueOnce([makeTxsPublishedEvent(101n, blocks[0].body.getTxsEffectsHash())]) .mockResolvedValueOnce([makeL2BlockProcessedEvent(101n, 1n)]) - .mockResolvedValueOnce([makeContractDeploymentEvent(103n, blocks[0])]) // the first loop of the archiver ends here at block 2500 .mockResolvedValueOnce(l1ToL2MessageAddedEvents.slice(2, 4).flat()) .mockResolvedValueOnce(makeL1ToL2MessageCancelledEvents(2503n, l1ToL2MessagesToCancel)) .mockResolvedValueOnce([ @@ -108,7 +99,6 @@ describe('Archiver', () => { makeTxsPublishedEvent(2520n, blocks[2].body.getTxsEffectsHash()), ]) .mockResolvedValueOnce([makeL2BlockProcessedEvent(2510n, 2n), makeL2BlockProcessedEvent(2520n, 3n)]) - .mockResolvedValueOnce([makeContractDeploymentEvent(2540n, blocks[1])]) .mockResolvedValue([]); publicClient.getTransaction.mockResolvedValueOnce(publishTxs[0]); publicClient.getTransaction.mockResolvedValueOnce(rollupTxs[0]); @@ -182,7 +172,6 @@ describe('Archiver', () => { inboxAddress, newInboxAddress, registryAddress, - contractDeploymentEmitterAddress, archiverStore, 1000, ); @@ -268,7 +257,6 @@ describe('Archiver', () => { inboxAddress, newInboxAddress, registryAddress, - contractDeploymentEmitterAddress, archiverStore, 1000, ); @@ -345,31 +333,6 @@ function makeTxsPublishedEvent(l1BlockNum: bigint, txsEffectsHash: Buffer) { } as Log; } -/** - * Makes a fake ContractDeployment event for testing purposes. - * @param l1BlockNum - L1 block number. - * @param l2Block - The l2Block this event is associated with. - * @returns An ContractDeployment event. - */ -function makeContractDeploymentEvent(l1BlockNum: bigint, l2Block: L2Block) { - const extendedContractData = ExtendedContractData.random(); - const acir = extendedContractData.bytecode?.toString('hex'); - return { - blockNumber: l1BlockNum, - args: { - l2BlockNum: BigInt(l2Block.number), - aztecAddress: extendedContractData.contractData.contractAddress.toString(), - portalAddress: extendedContractData.contractData.portalContractAddress.toString(), - l2BlockHash: `0x${l2Block.body.getTxsEffectsHash().toString('hex')}`, - contractClassId: extendedContractData.contractClassId.toString(), - saltedInitializationHash: extendedContractData.saltedInitializationHash.toString(), - publicKeyHash: extendedContractData.publicKeyHash.toString(), - acir: '0x' + acir, - }, - transactionHash: `0x${l2Block.number}`, - } as Log; -} - /** * Makes fake L1ToL2 MessageAdded events for testing purposes. * @param l1BlockNum - L1 block number. diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index bda21f4a5bd..258c68db0e9 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -43,7 +43,6 @@ import { retrieveBlockBodiesFromAvailabilityOracle, retrieveBlockMetadataFromRollup, retrieveNewCancelledL1ToL2Messages, - retrieveNewContractData, retrieveNewL1ToL2Messages, retrieveNewPendingL1ToL2Messages, } from './data_retrieval.js'; @@ -76,7 +75,6 @@ export class Archiver implements ArchiveSource { * @param inboxAddress - Ethereum address of the inbox contract. * @param newInboxAddress - Ethereum address of the new inbox contract. * @param registryAddress - Ethereum address of the registry contract. - * @param contractDeploymentEmitterAddress - Ethereum address of the contractDeploymentEmitter contract. * @param pollingIntervalMs - The interval for polling for L1 logs (in milliseconds). * @param store - An archiver data store for storage & retrieval of blocks, encrypted logs & contract data. * @param log - A logger. @@ -88,7 +86,6 @@ export class Archiver implements ArchiveSource { private readonly inboxAddress: EthAddress, private readonly newInboxAddress: EthAddress, private readonly registryAddress: EthAddress, - private readonly contractDeploymentEmitterAddress: EthAddress, private readonly store: ArchiverDataStore, private readonly pollingIntervalMs = 10_000, private readonly log: DebugLogger = createDebugLogger('aztec:archiver'), @@ -131,7 +128,6 @@ export class Archiver implements ArchiveSource { config.l1Contracts.inboxAddress, newInboxAddress, config.l1Contracts.registryAddress, - config.l1Contracts.contractDeploymentEmitterAddress, archiverStore, config.archiverPollingIntervalMS, ); @@ -323,14 +319,6 @@ export class Archiver implements ArchiveSource { retrievedBlocks.retrievedData.forEach((block: L2Block) => { blockNumberToBodyHash[block.number] = block.header.contentCommitment.txsEffectsHash; }); - const retrievedContracts = await retrieveNewContractData( - this.publicClient, - this.contractDeploymentEmitterAddress, - blockUntilSynced, - lastL1Blocks.addedBlock + 1n, - currentL1BlockNumber, - blockNumberToBodyHash, - ); this.log(`Retrieved ${retrievedBlocks.retrievedData.length} block(s) from chain`); @@ -355,18 +343,6 @@ export class Archiver implements ArchiveSource { }), ); - // store contracts for which we have retrieved L2 blocks - const lastKnownL2BlockNum = retrievedBlocks.retrievedData[retrievedBlocks.retrievedData.length - 1].number; - await Promise.all( - retrievedContracts.retrievedData.map(async ([contracts, l2BlockNum]) => { - this.log(`Retrieved extended contract data for l2 block number: ${l2BlockNum}`); - if (l2BlockNum <= lastKnownL2BlockNum) { - await this.store.addExtendedContractData(contracts, l2BlockNum); - await this.storeContractDataAsClassesAndInstances(contracts, l2BlockNum); - } - }), - ); - // from retrieved L2Blocks, confirm L1 to L2 messages that have been published // from each l2block fetch all entryKeys in a flattened array: this.log(`Confirming l1 to l2 messages in store`); @@ -410,6 +386,7 @@ export class Archiver implements ArchiveSource { * Temporary solution until we source this data from the contract class registerer and instance deployer. * @param contracts - The extended contract data to be stored. * @param l2BlockNum - The L2 block number to which the contract data corresponds. + * TODO(palla/purge-old-contract-deploy): Delete this method */ async storeContractDataAsClassesAndInstances(contracts: ExtendedContractData[], l2BlockNum: number) { const classesAndInstances = contracts.map(extendedContractDataToContractClassAndInstance); @@ -489,6 +466,7 @@ export class Archiver implements ArchiveSource { /** * Temporary method for creating a fake extended contract data out of classes and instances registered in the node. * Used as a fallback if the extended contract data is not found. + * TODO(palla/purge-old-contract-deploy): Use proper classes */ private async makeExtendedContractDataFor(address: AztecAddress): Promise { const instance = await this.store.getContractInstance(address); @@ -505,23 +483,14 @@ export class Archiver implements ArchiveSource { return ExtendedContractData.fromClassAndInstance(contractClass, instance); } - /** - * Lookup all contract data in an L2 block. - * @param blockNum - The block number to get all contract data from. - * @returns All new contract data in the block (if found). - */ - public getExtendedContractDataInBlock(blockNum: number): Promise { - return this.store.getExtendedContractDataInBlock(blockNum); - } - /** * Lookup the contract data for this contract. * Contains contract address & the ethereum portal address. * @param contractAddress - The contract data address. * @returns ContractData with the portal address (if we didn't throw an error). */ - public async getContractData(contractAddress: AztecAddress): Promise { - return (await this.store.getContractData(contractAddress)) ?? this.makeContractDataFor(contractAddress); + public getContractData(contractAddress: AztecAddress): Promise { + return this.makeContractDataFor(contractAddress); } /** @@ -537,16 +506,6 @@ export class Archiver implements ArchiveSource { return new ContractData(address, instance.portalContractAddress); } - /** - * Lookup the L2 contract data inside a block. - * Contains contract address & the ethereum portal address. - * @param l2BlockNum - The L2 block number to get the contract data from. - * @returns ContractData with the portal address (if we didn't throw an error). - */ - public getContractDataInBlock(l2BlockNum: number): Promise { - return this.store.getContractDataInBlock(l2BlockNum); - } - /** * Gets the public function data for a contract. * @param contractAddress - The contract address containing the function to fetch. diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 1070de6a986..f39399bd663 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -1,6 +1,5 @@ import { Body, - ContractData, ExtendedContractData, GetUnencryptedLogsResponse, L1ToL2Message, @@ -180,29 +179,6 @@ export interface ArchiverDataStore { */ getExtendedContractData(contractAddress: AztecAddress): Promise; - /** - * Lookup all extended contract data in an L2 block. - * @param blockNum - The block number to get all contract data from. - * @returns All extended contract data in the block (if found). - */ - getExtendedContractDataInBlock(blockNum: number): Promise; - - /** - * Get basic info for an L2 contract. - * Contains contract address & the ethereum portal address. - * @param contractAddress - The contract data address. - * @returns ContractData with the portal address (if we didn't throw an error). - */ - getContractData(contractAddress: AztecAddress): Promise; - - /** - * Get basic info for an all L2 contracts deployed in a block. - * Contains contract address & the ethereum portal address. - * @param l2BlockNum - Number of the L2 block where contracts were deployed. - * @returns ContractData with the portal address (if we didn't throw an error). - */ - getContractDataInBlock(l2BlockNum: number): Promise; - /** * Gets the number of the latest L2 block processed. * @returns The number of the latest L2 block processed. diff --git a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts index ef3e28a0f7f..52a94986982 100644 --- a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts +++ b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts @@ -1,5 +1,4 @@ import { - ExtendedContractData, L1ToL2Message, L2Block, L2BlockContext, @@ -417,119 +416,6 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch }); }); - describe('getContractData', () => { - let block: L2Block; - beforeEach(async () => { - block = L2Block.random(1); - await store.addBlocks([block]); - await store.addBlockBodies([block.body]); - }); - - it('returns previously stored contract data', async () => { - await expect(store.getContractData(block.body.txEffects[0].contractData[0].contractAddress)).resolves.toEqual( - block.body.txEffects[0].contractData[0], - ); - }); - - it('returns undefined if contract data is not found', async () => { - await expect(store.getContractData(AztecAddress.random())).resolves.toBeUndefined(); - }); - }); - - describe('getContractDataInBlock', () => { - let block: L2Block; - beforeEach(async () => { - block = L2Block.random(1); - await store.addBlocks([block]); - await store.addBlockBodies([block.body]); - }); - - it('returns the contract data for a known block', async () => { - await expect(store.getContractDataInBlock(block.number)).resolves.toEqual( - block.body.txEffects.flatMap(txEffect => txEffect.contractData), - ); - }); - - it('returns an empty array if contract data is not found', async () => { - await expect(store.getContractDataInBlock(block.number + 1)).resolves.toEqual([]); - }); - }); - - describe('addExtendedContractData', () => { - it('stores extended contract data', async () => { - const block = L2Block.random(1); - await store.addBlocks([block]); - await store.addBlockBodies([block.body]); - await expect(store.addExtendedContractData([ExtendedContractData.random()], block.number)).resolves.toEqual( - true, - ); - }); - - it('stores extended contract data for an unknown block', async () => { - await expect(store.addExtendedContractData([ExtendedContractData.random()], 1)).resolves.toEqual(true); - }); - - it('"pushes" extended contract data and does not overwrite', async () => { - const block = L2Block.random(1); - await store.addBlocks([block]); - await store.addBlockBodies([block.body]); - - // Assuming one contract per tx, and the first two txs - const firstContract = ExtendedContractData.random(block.body.txEffects[0].contractData[0]); - await store.addExtendedContractData([firstContract], block.number); - - const secondContract = ExtendedContractData.random(block.body.txEffects[1].contractData[0]); - await store.addExtendedContractData([secondContract], block.number); - - await expect(store.getExtendedContractDataInBlock(block.number)).resolves.toEqual([ - firstContract, - secondContract, - ]); - }); - }); - - describe('getExtendedContractData', () => { - let block: L2Block; - let extendedContractData: ExtendedContractData; - beforeEach(async () => { - block = L2Block.random(1); - extendedContractData = ExtendedContractData.random(block.body.txEffects[0].contractData[0]); - await store.addBlocks([block]); - await store.addBlockBodies([block.body]); - await store.addExtendedContractData([extendedContractData], block.number); - }); - - it('returns previously stored extended contract data', async () => { - await expect(store.getExtendedContractData(extendedContractData.contractData.contractAddress)).resolves.toEqual( - extendedContractData, - ); - }); - - it('returns undefined if extended contract data is not found', async () => { - await expect(store.getExtendedContractData(AztecAddress.random())).resolves.toBeUndefined(); - }); - }); - - describe('getExtendedContractDataInBlock', () => { - let block: L2Block; - let extendedContractData: ExtendedContractData; - beforeEach(async () => { - block = L2Block.random(1); - extendedContractData = ExtendedContractData.random(block.body.txEffects[0].contractData[0]); - await store.addBlocks([block]); - await store.addBlockBodies([block.body]); - await store.addExtendedContractData([extendedContractData], block.number); - }); - - it('returns previously stored extended contract data', async () => { - await expect(store.getExtendedContractDataInBlock(block.number)).resolves.toEqual([extendedContractData]); - }); - - it('returns an empty array if extended contract data is not found for the block', async () => { - await expect(store.getExtendedContractDataInBlock(block.number + 1)).resolves.toEqual([]); - }); - }); - describe('getUnencryptedLogs', () => { const txsPerBlock = 4; const numPublicFunctionCalls = 3; diff --git a/yarn-project/archiver/src/archiver/config.ts b/yarn-project/archiver/src/archiver/config.ts index 9c83ab13072..daddf75df06 100644 --- a/yarn-project/archiver/src/archiver/config.ts +++ b/yarn-project/archiver/src/archiver/config.ts @@ -58,7 +58,6 @@ export function getConfigEnvVars(): ArchiverConfig { ARCHIVER_VIEM_POLLING_INTERVAL_MS, AVAILABILITY_ORACLE_CONTRACT_ADDRESS, ROLLUP_CONTRACT_ADDRESS, - CONTRACT_DEPLOYMENT_EMITTER_ADDRESS, API_KEY, INBOX_CONTRACT_ADDRESS, OUTBOX_CONTRACT_ADDRESS, @@ -74,9 +73,6 @@ export function getConfigEnvVars(): ArchiverConfig { registryAddress: REGISTRY_CONTRACT_ADDRESS ? EthAddress.fromString(REGISTRY_CONTRACT_ADDRESS) : EthAddress.ZERO, inboxAddress: INBOX_CONTRACT_ADDRESS ? EthAddress.fromString(INBOX_CONTRACT_ADDRESS) : EthAddress.ZERO, outboxAddress: OUTBOX_CONTRACT_ADDRESS ? EthAddress.fromString(OUTBOX_CONTRACT_ADDRESS) : EthAddress.ZERO, - contractDeploymentEmitterAddress: CONTRACT_DEPLOYMENT_EMITTER_ADDRESS - ? EthAddress.fromString(CONTRACT_DEPLOYMENT_EMITTER_ADDRESS) - : EthAddress.ZERO, }; return { rpcUrl: ETHEREUM_HOST || 'http://127.0.0.1:8545/', diff --git a/yarn-project/archiver/src/archiver/data_retrieval.ts b/yarn-project/archiver/src/archiver/data_retrieval.ts index ec9378c7d02..8c90b82e147 100644 --- a/yarn-project/archiver/src/archiver/data_retrieval.ts +++ b/yarn-project/archiver/src/archiver/data_retrieval.ts @@ -1,18 +1,16 @@ -import { Body, ExtendedContractData, L1ToL2Message, NewInboxLeaf } from '@aztec/circuit-types'; +import { Body, L1ToL2Message, NewInboxLeaf } from '@aztec/circuit-types'; import { AppendOnlyTreeSnapshot, Fr, Header } from '@aztec/circuits.js'; import { EthAddress } from '@aztec/foundation/eth-address'; import { PublicClient } from 'viem'; import { - getContractDeploymentLogs, getL1ToL2MessageCancelledLogs, getL2BlockProcessedLogs, getLeafInsertedLogs, getPendingL1ToL2MessageLogs, getTxsPublishedLogs, processCancelledL1ToL2MessagesLogs, - processContractDeploymentLogs, processL2BlockProcessedLogs, processLeafInsertedLogs, processPendingL1ToL2MessageAddedLogs, @@ -117,45 +115,6 @@ export async function retrieveBlockBodiesFromAvailabilityOracle( return { nextEthBlockNumber: searchStartBlock, retrievedData: retrievedBlockBodies }; } -/** - * Fetches new contract data. - * @param publicClient - The viem public client to use for transaction retrieval. - * @param contractDeploymentEmitterAddress - The address of the contract deployment emitter contract. - * @param blockUntilSynced - If true, blocks until the archiver has fully synced. - * @param searchStartBlock - The block number to use for starting the search. - * @param searchEndBlock - The highest block number that we should search up to. - * @param blockNumberToBodyHash - A mapping from block number to relevant body hash. - * @returns An array of ExtendedContractData and their equivalent L2 Block number along with the next eth block to search from.. - */ -export async function retrieveNewContractData( - publicClient: PublicClient, - contractDeploymentEmitterAddress: EthAddress, - blockUntilSynced: boolean, - searchStartBlock: bigint, - searchEndBlock: bigint, - blockNumberToBodyHash: { [key: number]: Buffer | undefined }, -): Promise> { - let retrievedNewContracts: [ExtendedContractData[], number][] = []; - do { - if (searchStartBlock > searchEndBlock) { - break; - } - const contractDataLogs = await getContractDeploymentLogs( - publicClient, - contractDeploymentEmitterAddress, - searchStartBlock, - searchEndBlock, - ); - if (contractDataLogs.length === 0) { - break; - } - const newContracts = processContractDeploymentLogs(blockNumberToBodyHash, contractDataLogs); - retrievedNewContracts = retrievedNewContracts.concat(newContracts); - searchStartBlock = (contractDataLogs.findLast(cd => !!cd)?.blockNumber || searchStartBlock) + 1n; - } while (blockUntilSynced && searchStartBlock <= searchEndBlock); - return { nextEthBlockNumber: searchStartBlock, retrievedData: retrievedNewContracts }; -} - /** * Fetch new pending L1 to L2 messages. * @param publicClient - The viem public client to use for transaction retrieval. diff --git a/yarn-project/archiver/src/archiver/eth_log_handlers.ts b/yarn-project/archiver/src/archiver/eth_log_handlers.ts index 515c8641c0b..2d2e2e4a325 100644 --- a/yarn-project/archiver/src/archiver/eth_log_handlers.ts +++ b/yarn-project/archiver/src/archiver/eth_log_handlers.ts @@ -1,25 +1,10 @@ -import { - Body, - ContractData, - EncodedContractFunction, - ExtendedContractData, - L1Actor, - L1ToL2Message, - L2Actor, - NewInboxLeaf, -} from '@aztec/circuit-types'; +import { Body, L1Actor, L1ToL2Message, L2Actor, NewInboxLeaf } from '@aztec/circuit-types'; import { AppendOnlyTreeSnapshot, Header } from '@aztec/circuits.js'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; -import { BufferReader, numToUInt32BE } from '@aztec/foundation/serialize'; -import { - AvailabilityOracleAbi, - ContractDeploymentEmitterAbi, - InboxAbi, - NewInboxAbi, - RollupAbi, -} from '@aztec/l1-artifacts'; +import { numToUInt32BE } from '@aztec/foundation/serialize'; +import { AvailabilityOracleAbi, InboxAbi, NewInboxAbi, RollupAbi } from '@aztec/l1-artifacts'; import { Hex, Log, PublicClient, decodeFunctionData, getAbiItem, getAddress, hexToBytes } from 'viem'; @@ -249,71 +234,6 @@ export function getTxsPublishedLogs( }); } -/** - * Gets relevant `ContractDeployment` logs from chain. - * @param publicClient - The viem public client to use for transaction retrieval. - * @param contractDeploymentEmitterAddress - The address of the L2 contract deployment emitter contract. - * @param fromBlock - First block to get logs from (inclusive). - * @param toBlock - Last block to get logs from (inclusive). - * @returns An array of `ContractDeployment` logs. - */ -export function getContractDeploymentLogs( - publicClient: PublicClient, - contractDeploymentEmitterAddress: EthAddress, - fromBlock: bigint, - toBlock: bigint, -): Promise[]> { - return publicClient.getLogs({ - address: getAddress(contractDeploymentEmitterAddress.toString()), - event: getAbiItem({ - abi: ContractDeploymentEmitterAbi, - name: 'ContractDeployment', - }), - fromBlock, - toBlock: toBlock + 1n, // the toBlock argument in getLogs is exclusive - }); -} - -/** - * Processes newly received ContractDeployment logs. - * @param blockNumberToBodyHash - A mapping from block number to relevant body hash. - * @param logs - ContractDeployment logs. - * @returns The set of retrieved extended contract data items. - */ -export function processContractDeploymentLogs( - blockNumberToBodyHash: { [key: number]: Buffer | undefined }, - logs: Log[], -): [ExtendedContractData[], number][] { - const extendedContractData: [ExtendedContractData[], number][] = []; - for (let i = 0; i < logs.length; i++) { - const log = logs[i]; - const l2BlockNum = Number(log.args.l2BlockNum); - const blockHash = Buffer.from(hexToBytes(log.args.l2BlockHash)); - const expectedBlockHash = blockNumberToBodyHash[l2BlockNum]; - if (expectedBlockHash === undefined || !blockHash.equals(expectedBlockHash)) { - continue; - } - const publicFnsReader = BufferReader.asReader(Buffer.from(log.args.acir.slice(2), 'hex')); - const contractClassId = Fr.fromBuffer(Buffer.from(hexToBytes(log.args.contractClassId))); - const saltedInitializationHash = Fr.fromBuffer(Buffer.from(hexToBytes(log.args.saltedInitializationHash))); - const publicKeyHash = Fr.fromBuffer(Buffer.from(hexToBytes(log.args.publicKeyHash))); - - const contractData = new ExtendedContractData( - new ContractData(AztecAddress.fromString(log.args.aztecAddress), EthAddress.fromString(log.args.portalAddress)), - publicFnsReader.readVector(EncodedContractFunction), - contractClassId, - saltedInitializationHash, - publicKeyHash, - ); - if (extendedContractData[i]) { - extendedContractData[i][0].push(contractData); - } else { - extendedContractData[i] = [[contractData], l2BlockNum]; - } - } - return extendedContractData; -} - /** * Get relevant `MessageAdded` logs emitted by Inbox on chain. * @param publicClient - The viem public client to use for transaction retrieval. diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts index c581bd965ed..8d26356acab 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts @@ -55,16 +55,6 @@ export class BlockStore { block.getTxs().forEach((tx, i) => { void this.#txIndex.set(tx.txHash.toString(), [block.number, i]); }); - - block.body.txEffects - .flatMap(txEffect => txEffect.contractData) - .forEach((contractData, i) => { - if (contractData.contractAddress.isZero()) { - return; - } - - void this.#contractIndex.set(contractData.contractAddress.toString(), [block.number, i]); - }); } return true; diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/contract_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/contract_store.ts index f5653857a33..8278d75bb13 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/contract_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/contract_store.ts @@ -1,4 +1,4 @@ -import { ContractData, ExtendedContractData } from '@aztec/circuit-types'; +import { ExtendedContractData } from '@aztec/circuit-types'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { createDebugLogger } from '@aztec/foundation/log'; import { AztecKVStore, AztecMap } from '@aztec/kv-store'; @@ -52,47 +52,4 @@ export class ContractStore { return undefined; } - - /** - * Lookup all extended contract data in an L2 block. - * @param blockNumber - The block number to get all contract data from. - * @returns All extended contract data in the block (if found). - */ - getExtendedContractDataInBlock(blockNumber: number): Array { - return (this.#extendedContractData.get(blockNumber) ?? []).map(contract => - ExtendedContractData.fromBuffer(contract), - ); - } - - /** - * Get basic info for an L2 contract. - * Contains contract address & the ethereum portal address. - * @param contractAddress - The contract data address. - * @returns ContractData with the portal address (if we didn't throw an error). - */ - getContractData(contractAddress: AztecAddress): ContractData | undefined { - const [blockNumber, index] = this.#blockStore.getContractLocation(contractAddress) ?? []; - if (typeof blockNumber !== 'number' || typeof index !== 'number') { - return undefined; - } - - const block = this.#blockStore.getBlock(blockNumber); - - if (block?.body.txEffects[index].contractData.length !== 1) { - throw new Error(`Contract data at block: ${blockNumber}, tx: ${index} does not have length of 1`); - } - - return block?.body.txEffects[index].contractData[0]; - } - - /** - * Get basic info for an all L2 contracts deployed in a block. - * Contains contract address & the ethereum portal address. - * @param blockNumber - Number of the L2 block where contracts were deployed. - * @returns ContractData with the portal address (if we didn't throw an error). - */ - getContractDataInBlock(blockNumber: number): ContractData[] { - const block = this.#blockStore.getBlock(blockNumber); - return block?.body.txEffects.flatMap(txEffect => txEffect.contractData) ?? []; - } } diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts index 83191b36789..477c0692926 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts @@ -1,6 +1,5 @@ import { Body, - ContractData, ExtendedContractData, GetUnencryptedLogsResponse, L1ToL2Message, @@ -272,35 +271,6 @@ export class KVArchiverDataStore implements ArchiverDataStore { return Promise.resolve(this.#contractStore.getExtendedContractData(contractAddress)); } - /** - * Lookup all extended contract data in an L2 block. - * @param blockNumber - The block number to get all contract data from. - * @returns All extended contract data in the block (if found). - */ - getExtendedContractDataInBlock(blockNumber: number): Promise { - return Promise.resolve(Array.from(this.#contractStore.getExtendedContractDataInBlock(blockNumber))); - } - - /** - * Get basic info for an L2 contract. - * Contains contract address & the ethereum portal address. - * @param contractAddress - The contract data address. - * @returns ContractData with the portal address (if we didn't throw an error). - */ - getContractData(contractAddress: AztecAddress): Promise { - return Promise.resolve(this.#contractStore.getContractData(contractAddress)); - } - - /** - * Get basic info for an all L2 contracts deployed in a block. - * Contains contract address & the ethereum portal address. - * @param blockNumber - Number of the L2 block where contracts were deployed. - * @returns ContractData with the portal address (if we didn't throw an error). - */ - getContractDataInBlock(blockNumber: number): Promise { - return Promise.resolve(Array.from(this.#contractStore.getContractDataInBlock(blockNumber))); - } - /** * Gets the number of the latest L2 block processed. * @returns The number of the latest L2 block processed. diff --git a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts index d299a7d9959..444db95ff7e 100644 --- a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts @@ -1,6 +1,5 @@ import { Body, - ContractData, ExtendedContractData, ExtendedUnencryptedL2Log, GetUnencryptedLogsResponse, @@ -459,6 +458,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { /** * Get the extended contract data for this contract. + * TODO(palla/purge-old-contract-deploy): Delete me? * @param contractAddress - The contract data address. * @returns The extended contract data or undefined if not found. */ @@ -467,52 +467,6 @@ export class MemoryArchiverStore implements ArchiverDataStore { return Promise.resolve(result); } - /** - * Lookup all contract data in an L2 block. - * @param blockNum - The block number to get all contract data from. - * @returns All extended contract data in the block (if found). - */ - public getExtendedContractDataInBlock(blockNum: number): Promise { - if (blockNum > this.l2BlockContexts.length) { - return Promise.resolve([]); - } - return Promise.resolve(this.extendedContractDataByBlock[blockNum] || []); - } - - /** - * Get basic info for an L2 contract. - * Contains contract address & the ethereum portal address. - * @param contractAddress - The contract data address. - * @returns ContractData with the portal address (if we didn't throw an error). - */ - public getContractData(contractAddress: AztecAddress): Promise { - if (contractAddress.isZero()) { - return Promise.resolve(undefined); - } - for (const blockContext of this.l2BlockContexts) { - for (const contractData of blockContext.block.body.txEffects.flatMap(txEffect => txEffect.contractData)) { - if (contractData.contractAddress.equals(contractAddress)) { - return Promise.resolve(contractData); - } - } - } - return Promise.resolve(undefined); - } - - /** - * Get basic info for an all L2 contracts deployed in a block. - * Contains contract address & the ethereum portal address. - * @param l2BlockNum - Number of the L2 block where contracts were deployed. - * @returns ContractData with the portal address (if we didn't throw an error). - */ - public getContractDataInBlock(l2BlockNum: number): Promise { - if (l2BlockNum > this.l2BlockContexts.length) { - return Promise.resolve([]); - } - const block: L2Block | undefined = this.l2BlockContexts[l2BlockNum - INITIAL_L2_BLOCK_NUM]?.block; - return Promise.resolve(block?.body.txEffects.flatMap(txEffect => txEffect.contractData)); - } - /** * Gets the number of the latest L2 block processed. * @returns The number of the latest L2 block processed. diff --git a/yarn-project/archiver/src/index.ts b/yarn-project/archiver/src/index.ts index f6e3c1003e4..a2d04eccd4e 100644 --- a/yarn-project/archiver/src/index.ts +++ b/yarn-project/archiver/src/index.ts @@ -47,7 +47,6 @@ async function main() { l1Contracts.inboxAddress, newInboxAddress, l1Contracts.registryAddress, - l1Contracts.contractDeploymentEmitterAddress, archiverStore, ); diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index c8ee8cfd348..956bc5582bf 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -26,7 +26,6 @@ import { } from '@aztec/circuit-types'; import { ARCHIVE_HEIGHT, - CONTRACT_TREE_HEIGHT, EthAddress, Fr, Header, @@ -93,7 +92,6 @@ export class AztecNodeService implements AztecNode { `Registry: ${config.l1Contracts.registryAddress.toString()}\n` + `Inbox: ${config.l1Contracts.inboxAddress.toString()}\n` + `Outbox: ${config.l1Contracts.outboxAddress.toString()}\n` + - `Contract Emitter: ${config.l1Contracts.contractDeploymentEmitterAddress.toString()}\n` + `Availability Oracle: ${config.l1Contracts.availabilityOracleAddress.toString()}`; this.log(message); } @@ -359,20 +357,6 @@ export class AztecNodeService implements AztecNode { return committedDb.findLeafIndex(treeId, leafValue.toBuffer()); } - /** - * Returns a sibling path for the given index in the contract tree. - * @param blockNumber - The block number at which to get the data. - * @param leafIndex - The index of the leaf for which the sibling path is required. - * @returns The sibling path for the leaf index. - */ - public async getContractSiblingPath( - blockNumber: number | 'latest', - leafIndex: bigint, - ): Promise> { - const committedDb = await this.#getWorldState(blockNumber); - return committedDb.getSiblingPath(MerkleTreeId.CONTRACT_TREE, leafIndex); - } - /** * Returns a sibling path for the given index in the nullifier tree. * @param blockNumber - The block number at which to get the data. diff --git a/yarn-project/aztec-node/terraform/main.tf b/yarn-project/aztec-node/terraform/main.tf index ce2e3b42bff..5bf9187d744 100644 --- a/yarn-project/aztec-node/terraform/main.tf +++ b/yarn-project/aztec-node/terraform/main.tf @@ -215,10 +215,7 @@ resource "aws_ecs_task_definition" "aztec-node" { "name": "SEQ_PUBLISHER_PRIVATE_KEY", "value": "${local.publisher_private_keys[count.index]}" }, - { - "name": "CONTRACT_DEPLOYMENT_EMITTER_ADDRESS", - "value": "${data.terraform_remote_state.l1_contracts.outputs.contract_deployment_emitter_address}" - }, + { "name": "ROLLUP_CONTRACT_ADDRESS", "value": "${data.terraform_remote_state.l1_contracts.outputs.rollup_contract_address}" diff --git a/yarn-project/aztec.js/src/contract/contract.test.ts b/yarn-project/aztec.js/src/contract/contract.test.ts index d2b27f15070..474cf57ede5 100644 --- a/yarn-project/aztec.js/src/contract/contract.test.ts +++ b/yarn-project/aztec.js/src/contract/contract.test.ts @@ -28,7 +28,6 @@ describe('Contract Class', () => { registryAddress: EthAddress.random(), inboxAddress: EthAddress.random(), outboxAddress: EthAddress.random(), - contractDeploymentEmitterAddress: EthAddress.random(), }; const mockNodeInfo: NodeInfo = { nodeVersion: 'vx.x.x', diff --git a/yarn-project/aztec.js/src/contract/sent_tx.ts b/yarn-project/aztec.js/src/contract/sent_tx.ts index 64379ce0c42..c0d49fa61c2 100644 --- a/yarn-project/aztec.js/src/contract/sent_tx.ts +++ b/yarn-project/aztec.js/src/contract/sent_tx.ts @@ -75,8 +75,6 @@ export class SentTx { nullifiers: tx.nullifiers.filter(n => !n.isZero()), publicDataWrites: tx.publicDataWrites.filter(p => !p.isEmpty()), l2ToL1Msgs: tx.l2ToL1Msgs.filter(l => !l.isZero()), - contractsLeaves: tx.contractLeaves.filter(c => !c.isZero()), - contractData: tx.contractData.filter(c => !c.isEmpty()), visibleNotes, }; } diff --git a/yarn-project/aztec/CHANGELOG.md b/yarn-project/aztec/CHANGELOG.md index 9f62a9ce34f..42dac751310 100644 --- a/yarn-project/aztec/CHANGELOG.md +++ b/yarn-project/aztec/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [0.27.1](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.27.0...aztec-package-v0.27.1) (2024-03-12) + + +### Miscellaneous + +* **aztec-package:** Synchronize aztec-packages versions + +## [0.27.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.26.6...aztec-package-v0.27.0) (2024-03-12) + + +### Features + +* Add api for inclusion proof of outgoing message in block [#4562](https://github.com/AztecProtocol/aztec-packages/issues/4562) ([#4899](https://github.com/AztecProtocol/aztec-packages/issues/4899)) ([26d2643](https://github.com/AztecProtocol/aztec-packages/commit/26d26437022567e2d54052f21b1c937259f26c94)) + + +### Miscellaneous + +* Pin foundry ([#5151](https://github.com/AztecProtocol/aztec-packages/issues/5151)) ([69bd7dd](https://github.com/AztecProtocol/aztec-packages/commit/69bd7dd45af6b197b23c25dc883a1a5485955203)) +* Remove old contract deployment flow ([#4970](https://github.com/AztecProtocol/aztec-packages/issues/4970)) ([6d15947](https://github.com/AztecProtocol/aztec-packages/commit/6d1594736e96cd744ea691a239fcd3a46bdade60)) + ## [0.26.6](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.26.5...aztec-package-v0.26.6) (2024-03-08) diff --git a/yarn-project/aztec/docker-compose.yml b/yarn-project/aztec/docker-compose.yml index 84397ba70b7..813431296df 100644 --- a/yarn-project/aztec/docker-compose.yml +++ b/yarn-project/aztec/docker-compose.yml @@ -1,7 +1,7 @@ version: '3' services: ethereum: - image: ghcr.io/foundry-rs/foundry@sha256:29ba6e34379e79c342ec02d437beb7929c9e254261e8032b17e187be71a2609f + image: ghcr.io/foundry-rs/foundry:nightly-de33b6af53005037b463318d2628b5cfcaf39916 entrypoint: > sh -c ' if [ -n "$FORK_BLOCK_NUMBER" ] && [ -n "$FORK_URL" ]; then diff --git a/yarn-project/aztec/package.json b/yarn-project/aztec/package.json index bc5e0f419b4..543a928d579 100644 --- a/yarn-project/aztec/package.json +++ b/yarn-project/aztec/package.json @@ -1,6 +1,6 @@ { "name": "@aztec/aztec", - "version": "0.26.6", + "version": "0.27.1", "type": "module", "exports": { ".": "./dest/index.js" diff --git a/yarn-project/aztec/src/cli/texts.ts b/yarn-project/aztec/src/cli/texts.ts index 6d203edb071..4c37b30ff9a 100644 --- a/yarn-project/aztec/src/cli/texts.ts +++ b/yarn-project/aztec/src/cli/texts.ts @@ -4,8 +4,7 @@ const contractAddresses = 'registryAddress:REGISTRY_CONTRACT_ADDRESS - string - The deployed L1 registry contract address.\n' + 'inboxAddress:INBOX_CONTRACT_ADDRESS - string - The deployed L1 inbox contract address.\n' + 'outboxAddress:OUTBOX_CONTRACT_ADDRESS - string - The deployed L1 outbox contract address.\n' + - 'contractDeploymentEmitterAddress:CONTRACT_DEPLOYMENT_EMITTER_ADDRESS - string - The deployed L1 contract deployment emitter contract address.\n'; -('availabilityOracleAddress:AVAILABILITY_ORACLE_CONTRACT_ADDRESS - string - The deployed L1 availability oracle contract address.\n'); + 'availabilityOracleAddress:AVAILABILITY_ORACLE_CONTRACT_ADDRESS - string - The deployed L1 availability oracle contract address.\n'; const p2pOptions = 'p2pBlockCheckIntervalMS:P2P_BLOCK_CHECK_INTERVAL_MS - number - The frequency in which to check for blocks. Default: 100\n' + 'p2pL2QueueSize:P2P_L2_QUEUE_SIZE - number - Size of queue of L2 blocks to store. Default: 1000\n' + diff --git a/yarn-project/aztec/src/sandbox.ts b/yarn-project/aztec/src/sandbox.ts index 4c4b378ba67..161100eefce 100644 --- a/yarn-project/aztec/src/sandbox.ts +++ b/yarn-project/aztec/src/sandbox.ts @@ -13,8 +13,6 @@ import { retryUntil } from '@aztec/foundation/retry'; import { AvailabilityOracleAbi, AvailabilityOracleBytecode, - ContractDeploymentEmitterAbi, - ContractDeploymentEmitterBytecode, InboxAbi, InboxBytecode, OutboxAbi, @@ -80,10 +78,6 @@ export async function deployContractsToL1( contractDeployLogger = logger, ) { const l1Artifacts: L1ContractArtifactsForDeployment = { - contractDeploymentEmitter: { - contractAbi: ContractDeploymentEmitterAbi, - contractBytecode: ContractDeploymentEmitterBytecode, - }, registry: { contractAbi: RegistryAbi, contractBytecode: RegistryBytecode, diff --git a/yarn-project/circuit-types/src/contract_data.ts b/yarn-project/circuit-types/src/contract_data.ts index 6803d0c1dd2..fe1db7c04ae 100644 --- a/yarn-project/circuit-types/src/contract_data.ts +++ b/yarn-project/circuit-types/src/contract_data.ts @@ -29,20 +29,6 @@ export interface ContractDataSource { */ getContractData(contractAddress: AztecAddress): Promise; - /** - * Gets extended contract data for all contracts deployed in L2 block. - * @param blockNumber - The block number. - * @returns Extended contract data of contracts deployed in L2 block. - */ - getExtendedContractDataInBlock(blockNumber: number): Promise; - - /** - * Lookup contract data in an L2 block. - * @param blockNumber - The block number. - * @returns Portal contract address info of contracts deployed in L2 block. - */ - getContractDataInBlock(blockNumber: number): Promise; - /** * Returns a contract's encoded public function, given its function selector. * @param address - The contract aztec address. @@ -141,6 +127,7 @@ export class EncodedContractFunction { /** * A contract data blob, containing L1 and L2 addresses, public functions' bytecode, partial address and public key. + * TODO(palla/purge-old-contract-deploy): Delete this class? */ export class ExtendedContractData { /** The contract's encoded ACIR code. This should become Brillig code once implemented. */ @@ -270,6 +257,7 @@ export class ExtendedContractData { /** * A contract data blob, containing L1 and L2 addresses. + * TODO(palla/purge-old-contract-deploy): Delete me */ export class ContractData { constructor( diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index 72bc6a5d8a8..0aee895dee8 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -1,6 +1,5 @@ import { ARCHIVE_HEIGHT, - CONTRACT_TREE_HEIGHT, Header, L1_TO_L2_MSG_TREE_HEIGHT, NOTE_HASH_TREE_HEIGHT, @@ -41,17 +40,6 @@ export interface AztecNode { */ findLeafIndex(blockNumber: BlockNumber, treeId: MerkleTreeId, leafValue: Fr): Promise; - /** - * Returns a sibling path for the given index in the contract tree. - * @param blockNumber - The block number at which to get the data. - * @param leafIndex - The index of the leaf for which the sibling path is required. - * @returns The sibling path for the leaf index. - */ - getContractSiblingPath( - blockNumber: BlockNumber, - leafIndex: bigint, - ): Promise>; - /** * Returns a sibling path for the given index in the nullifier tree. * @param blockNumber - The block number at which to get the data. diff --git a/yarn-project/circuit-types/src/l2_block.ts b/yarn-project/circuit-types/src/l2_block.ts index a17333ab097..0d947ac4d69 100644 --- a/yarn-project/circuit-types/src/l2_block.ts +++ b/yarn-project/circuit-types/src/l2_block.ts @@ -170,13 +170,11 @@ export class L2Block { this.header.globalVariables, AppendOnlyTreeSnapshot.zero(), // this.startNoteHashTreeSnapshot / commitments, AppendOnlyTreeSnapshot.zero(), // this.startNullifierTreeSnapshot, - AppendOnlyTreeSnapshot.zero(), // this.startContractTreeSnapshot, AppendOnlyTreeSnapshot.zero(), // this.startPublicDataTreeSnapshot, AppendOnlyTreeSnapshot.zero(), // this.startL1ToL2MessageTreeSnapshot, this.header.lastArchive, this.header.state.partial.noteHashTree, this.header.state.partial.nullifierTree, - this.header.state.partial.contractTree, this.header.state.partial.publicDataTree, this.header.state.l1ToL2MessageTree, this.archive, @@ -197,7 +195,6 @@ export class L2Block { new Fr(Number(this.header.globalVariables.blockNumber.toBigInt()) - 1), AppendOnlyTreeSnapshot.zero(), // this.startNoteHashTreeSnapshot, AppendOnlyTreeSnapshot.zero(), // this.startNullifierTreeSnapshot, - AppendOnlyTreeSnapshot.zero(), // this.startContractTreeSnapshot, AppendOnlyTreeSnapshot.zero(), // this.startPublicDataTreeSnapshot, AppendOnlyTreeSnapshot.zero(), // this.startL1ToL2MessageTreeSnapshot, this.header.lastArchive, @@ -215,7 +212,6 @@ export class L2Block { this.header.globalVariables.blockNumber, this.header.state.partial.noteHashTree, this.header.state.partial.nullifierTree, - this.header.state.partial.contractTree, this.header.state.partial.publicDataTree, this.header.state.l1ToL2MessageTree, this.archive, diff --git a/yarn-project/circuit-types/src/l2_block_code_to_purge.ts b/yarn-project/circuit-types/src/l2_block_code_to_purge.ts index 25eec75d249..6f66eead4f9 100644 --- a/yarn-project/circuit-types/src/l2_block_code_to_purge.ts +++ b/yarn-project/circuit-types/src/l2_block_code_to_purge.ts @@ -68,7 +68,6 @@ function makePartialStateReference(seed = 0): PartialStateReference { makeAppendOnlyTreeSnapshot(seed), makeAppendOnlyTreeSnapshot(seed + 1), makeAppendOnlyTreeSnapshot(seed + 2), - makeAppendOnlyTreeSnapshot(seed + 3), ); } diff --git a/yarn-project/circuit-types/src/merkle_tree_id.ts b/yarn-project/circuit-types/src/merkle_tree_id.ts index 0279f60b89f..25ab0897284 100644 --- a/yarn-project/circuit-types/src/merkle_tree_id.ts +++ b/yarn-project/circuit-types/src/merkle_tree_id.ts @@ -1,14 +1,21 @@ +import { + ARCHIVE_TREE_ID, + L1_TO_L2_MESSAGE_TREE_ID, + NOTE_HASH_TREE_ID, + NULLIFIER_TREE_ID, + PUBLIC_DATA_TREE_ID, +} from '@aztec/circuits.js'; + /** * Defines the possible Merkle tree IDs. - * NOTE: If you change this, update get_membership_witness.nr as well. + * @remarks The MerkleTrees class expects these to start from zero and be in incremental order. */ export enum MerkleTreeId { - CONTRACT_TREE = 0, - NULLIFIER_TREE = 1, - NOTE_HASH_TREE = 2, - PUBLIC_DATA_TREE = 3, - L1_TO_L2_MESSAGE_TREE = 4, - ARCHIVE = 5, + NULLIFIER_TREE = NULLIFIER_TREE_ID, + NOTE_HASH_TREE = NOTE_HASH_TREE_ID, + PUBLIC_DATA_TREE = PUBLIC_DATA_TREE_ID, + L1_TO_L2_MESSAGE_TREE = L1_TO_L2_MESSAGE_TREE_ID, + ARCHIVE = ARCHIVE_TREE_ID, } export const merkleTreeIds = () => { diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index 36ae115c485..743a0809168 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -2,7 +2,6 @@ import { AztecAddress, CallRequest, Fr, - MAX_NEW_CONTRACTS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, Proof, @@ -14,7 +13,6 @@ import { randomBytes } from '@aztec/foundation/crypto'; import { Tuple } from '@aztec/foundation/serialize'; import { ContractInstanceWithAddress, SerializableContractInstance } from '@aztec/types/contracts'; -import { ExtendedContractData } from './contract_data.js'; import { DeployedContract } from './interfaces/index.js'; import { FunctionL2Logs, Note, TxL2Logs } from './logs/index.js'; import { makePrivateKernelTailCircuitPublicInputs, makePublicCallRequest } from './mocks_to_purge.js'; @@ -38,10 +36,6 @@ export const mockTx = (seed = 1, logs = true) => { logs ? TxL2Logs.random(8, 3) : TxL2Logs.empty(), // 8 priv function invocations creating 3 encrypted logs each logs ? TxL2Logs.random(11, 2) : TxL2Logs.empty(), // 8 priv + 3 pub function invocations creating 2 unencrypted logs each times(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, makePublicCallRequest), - times(MAX_NEW_CONTRACTS_PER_TX, () => ExtendedContractData.random()) as Tuple< - ExtendedContractData, - typeof MAX_NEW_CONTRACTS_PER_TX - >, ); tx.data.endNonRevertibleData.publicCallStack = [ diff --git a/yarn-project/circuit-types/src/mocks_to_purge.ts b/yarn-project/circuit-types/src/mocks_to_purge.ts index f83e3d11115..7556e69603c 100644 --- a/yarn-project/circuit-types/src/mocks_to_purge.ts +++ b/yarn-project/circuit-types/src/mocks_to_purge.ts @@ -6,14 +6,12 @@ import { CallRequest, CallerContext, CombinedConstantData, - ContractDeploymentData, EthAddress, Fq, Fr, FunctionData, FunctionSelector, G1AffineElement, - MAX_NEW_CONTRACTS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX, MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX, @@ -22,7 +20,6 @@ import { MAX_REVERTIBLE_NOTE_HASHES_PER_TX, MAX_REVERTIBLE_NULLIFIERS_PER_TX, MAX_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, - NewContractData, Point, PrivateAccumulatedNonRevertibleData, PrivateAccumulatedRevertibleData, @@ -149,19 +146,9 @@ export function makeFinalAccumulatedData(seed = 1, full = false): PrivateAccumul tupleGenerator(2, fr, seed + 0x800), // unencrypted logs hash fr(seed + 0x900), // encrypted_log_preimages_length fr(seed + 0xa00), // unencrypted_log_preimages_length - tupleGenerator(MAX_NEW_CONTRACTS_PER_TX, makeNewContractData, seed + 0xb00), ); } -/** - * Creates arbitrary contract data. - * @param seed - The seed to use for generating the contract data. - * @returns A contract data. - */ -export function makeNewContractData(seed = 1): NewContractData { - return new NewContractData(makeAztecAddress(seed), makeEthAddress(seed + 1), fr(seed + 2)); -} - /** * Makes arbitrary eth address. * @param seed - The seed to use for generating the eth address. @@ -185,25 +172,9 @@ export function makeConstantData(seed = 1): CombinedConstantData { * @param seed - The seed to use for generating the tx context. * @returns A tx context. */ -export function makeTxContext(seed: number): TxContext { +export function makeTxContext(_seed: number): TxContext { // @todo @LHerskind should probably take value for chainId as it will be verified later. - // @todo @LHerskind should probably take value for version as it will be verified later. - return new TxContext(false, false, true, makeContractDeploymentData(seed), Fr.ZERO, Fr.ZERO); -} - -/** - * Makes arbitrary contract deployment data. - * @param seed - The seed to use for generating the contract deployment data. - * @returns A contract deployment data. - */ -export function makeContractDeploymentData(seed = 1) { - return new ContractDeploymentData( - makePoint(seed), - fr(seed + 1), - fr(seed + 2), - fr(seed + 3), - makeEthAddress(seed + 4), - ); + return new TxContext(false, false, Fr.ZERO, Fr.ZERO); } /** @@ -229,7 +200,6 @@ export function makePublicCallRequest(seed = 1): PublicCallRequest { functionSelector: makeSelector(seed + 3), isStaticCall: false, isDelegateCall: false, - isContractDeployment: false, startSideEffectCounter: 0, }); return new PublicCallRequest( @@ -255,7 +225,6 @@ export function makeCallContext(seed = 0, storageContractAddress = makeAztecAddr makeSelector(seed + 3), false, false, - false, 0, ); } diff --git a/yarn-project/circuit-types/src/stats/metrics.ts b/yarn-project/circuit-types/src/stats/metrics.ts index 347732a591b..a27e8c6f0b4 100644 --- a/yarn-project/circuit-types/src/stats/metrics.ts +++ b/yarn-project/circuit-types/src/stats/metrics.ts @@ -5,7 +5,7 @@ export type MetricGroupBy = | 'block-size' | 'chain-length' | 'circuit-name' - | 'contract-count' + | 'classes-registered' | 'leaf-count' | 'data-writes'; @@ -129,7 +129,7 @@ export const Metrics = [ }, { name: 'tx_size_in_bytes', - groupBy: 'contract-count', + groupBy: 'classes-registered', description: 'Size of txs received in the mempool.', events: ['tx-added-to-pool'], }, diff --git a/yarn-project/circuit-types/src/stats/stats.ts b/yarn-project/circuit-types/src/stats/stats.ts index 8ad9f63bcaf..102fb6c6a78 100644 --- a/yarn-project/circuit-types/src/stats/stats.ts +++ b/yarn-project/circuit-types/src/stats/stats.ts @@ -138,14 +138,12 @@ export type TxStats = { encryptedLogSize: number; /** Serialized size of unencrypted logs. */ unencryptedLogSize: number; - /** Serialized size of new contract data. */ - newContractDataSize: number; - /** Number of new contracts deployed in this tx. */ - newContractCount: number; - /** comm */ + /** New commitments count */ newCommitmentCount: number; - /** a */ + /** New nullifier count */ newNullifierCount: number; + /** How many classes were registered through the canonical class registerer. */ + classRegisteredCount: number; }; /** diff --git a/yarn-project/circuit-types/src/tx/tx.ts b/yarn-project/circuit-types/src/tx/tx.ts index e36bf56e085..1b7aeb0768e 100644 --- a/yarn-project/circuit-types/src/tx/tx.ts +++ b/yarn-project/circuit-types/src/tx/tx.ts @@ -1,5 +1,5 @@ import { - MAX_NEW_CONTRACTS_PER_TX, + ContractClassRegisteredEvent, PrivateKernelTailCircuitPublicInputs, Proof, PublicCallRequest, @@ -7,9 +7,8 @@ import { SideEffectLinkedToNoteHash, } from '@aztec/circuits.js'; import { arrayNonEmptyLength } from '@aztec/foundation/collection'; -import { BufferReader, Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { ExtendedContractData } from '../contract_data.js'; import { GetUnencryptedLogsResponse } from '../logs/get_unencrypted_logs_response.js'; import { L2LogsSource } from '../logs/l2_logs_source.js'; import { TxL2Logs } from '../logs/tx_l2_logs.js'; @@ -42,12 +41,6 @@ export class Tx { * Preimages of the public call stack entries from the private kernel circuit output. */ public readonly enqueuedPublicFunctionCalls: PublicCallRequest[], - /** - * Contracts deployed in this tx. - * Note: Portal address is always set to zero in the tx's new contracts. - * TODO(#3417): Check if portal addresses are still always set to zero - */ - public readonly newContracts: Tuple, ) { if (this.unencryptedLogs.functionLogs.length < this.encryptedLogs.functionLogs.length) { // This check is present because each private function invocation creates encrypted FunctionL2Logs object and @@ -82,7 +75,6 @@ export class Tx { reader.readObject(TxL2Logs), reader.readObject(TxL2Logs), reader.readArray(reader.readNumber(), PublicCallRequest), - reader.readArray(reader.readNumber(), ExtendedContractData) as [ExtendedContractData], ); } @@ -98,8 +90,6 @@ export class Tx { this.unencryptedLogs, this.enqueuedPublicFunctionCalls.length, this.enqueuedPublicFunctionCalls, - this.newContracts.length, - this.newContracts, ]); } @@ -114,7 +104,6 @@ export class Tx { unencryptedLogs: this.unencryptedLogs.toBuffer().toString('hex'), proof: this.proof.toBuffer().toString('hex'), enqueuedPublicFunctions: this.enqueuedPublicFunctionCalls.map(f => f.toBuffer().toString('hex')) ?? [], - newContracts: this.newContracts.map(c => c.toBuffer().toString('hex')), }; } @@ -140,15 +129,7 @@ export class Tx { const enqueuedPublicFunctions = obj.enqueuedPublicFunctions ? obj.enqueuedPublicFunctions.map((x: string) => PublicCallRequest.fromBuffer(Buffer.from(x, 'hex'))) : []; - const newContracts = obj.newContracts.map((x: string) => ExtendedContractData.fromBuffer(Buffer.from(x, 'hex'))); - return new Tx( - publicInputs, - Proof.fromBuffer(proof), - encryptedLogs, - unencryptedLogs, - enqueuedPublicFunctions, - newContracts, - ); + return new Tx(publicInputs, Proof.fromBuffer(proof), encryptedLogs, unencryptedLogs, enqueuedPublicFunctions); } /** @@ -172,8 +153,6 @@ export class Tx { unencryptedLogCount: this.unencryptedLogs.getTotalLogCount(), encryptedLogSize: this.encryptedLogs.getSerializedLength(), unencryptedLogSize: this.unencryptedLogs.getSerializedLength(), - newContractCount: arrayNonEmptyLength(this.newContracts, ExtendedContractData.isEmpty), - newContractDataSize: this.newContracts.map(c => c.toBuffer().length).reduce((a, b) => a + b, 0), newCommitmentCount: arrayNonEmptyLength(this.data!.endNonRevertibleData.newNoteHashes, SideEffect.isEmpty) + @@ -185,6 +164,9 @@ export class Tx { proofSize: this.proof.buffer.length, size: this.toBuffer().length, + classRegisteredCount: this.unencryptedLogs + .unrollLogs() + .filter(log => ContractClassRegisteredEvent.isContractClassRegisteredEvent(log)).length, }; } @@ -220,11 +202,7 @@ export class Tx { const enqueuedPublicFunctions = tx.enqueuedPublicFunctionCalls.map(x => { return PublicCallRequest.fromBuffer(x.toBuffer()); }); - const newContracts = tx.newContracts.map(c => ExtendedContractData.fromBuffer(c.toBuffer())) as Tuple< - ExtendedContractData, - typeof MAX_NEW_CONTRACTS_PER_TX - >; - return new Tx(publicInputs, proof, encryptedLogs, unencryptedLogs, enqueuedPublicFunctions, newContracts); + return new Tx(publicInputs, proof, encryptedLogs, unencryptedLogs, enqueuedPublicFunctions); } } diff --git a/yarn-project/circuit-types/src/tx/tx_receipt.ts b/yarn-project/circuit-types/src/tx/tx_receipt.ts index b29d1b13810..4a64176de9e 100644 --- a/yarn-project/circuit-types/src/tx/tx_receipt.ts +++ b/yarn-project/circuit-types/src/tx/tx_receipt.ts @@ -1,6 +1,5 @@ import { Fr } from '@aztec/foundation/fields'; -import { ContractData } from '../contract_data.js'; import { ExtendedNote } from '../notes/extended_note.js'; import { PublicDataWrite } from '../public_data_write.js'; import { TxHash } from './tx_hash.js'; @@ -96,14 +95,6 @@ interface DebugInfo { * New L2 to L1 messages created by the transaction. */ l2ToL1Msgs: Fr[]; - /** - * New contracts leaves created by the transaction to be inserted into the contract tree. - */ - contractsLeaves: Fr[]; - /** - * New contract data created by the transaction. - */ - contractData: ContractData[]; /** * Notes created in this tx which belong to accounts which are registered in the PXE which was used to submit the * tx. You will not receive notes of accounts which are not registered in the PXE here even though they were diff --git a/yarn-project/circuit-types/src/tx_effect.ts b/yarn-project/circuit-types/src/tx_effect.ts index 6ffb6a54525..79a8bd2104e 100644 --- a/yarn-project/circuit-types/src/tx_effect.ts +++ b/yarn-project/circuit-types/src/tx_effect.ts @@ -1,7 +1,6 @@ -import { ContractData, LogType, PublicDataWrite, TxHash, TxL2Logs } from '@aztec/circuit-types'; +import { LogType, PublicDataWrite, TxHash, TxL2Logs } from '@aztec/circuit-types'; import { Fr, - MAX_NEW_CONTRACTS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, @@ -32,14 +31,6 @@ export class TxEffect { * The public data writes to be inserted into the public data tree. */ public publicDataWrites: Tuple, - /** - * The leaves of the new contract data that will be inserted into the contracts tree. - */ - public contractLeaves: Tuple, - /** - * The contract data of the new contracts. - */ - public contractData: Tuple, /** * The logs of the txEffect */ @@ -52,17 +43,12 @@ export class TxEffect { const nonZeroNullifiers = this.nullifiers.filter(h => !h.isZero()); const nonZeroL2ToL1Msgs = this.l2ToL1Msgs.filter(h => !h.isZero()); const nonZeroPublicDataWrites = this.publicDataWrites.filter(h => !h.isEmpty()); - const nonZeroContractLeaves = this.contractLeaves.filter(h => !h.isZero()); - const nonZeroContractData = this.contractData.filter(h => !h.isEmpty()); return Buffer.concat([ serializeArrayOfBufferableToVector(nonZeroNoteHashes, 1), serializeArrayOfBufferableToVector(nonZeroNullifiers, 1), serializeArrayOfBufferableToVector(nonZeroL2ToL1Msgs, 1), serializeArrayOfBufferableToVector(nonZeroPublicDataWrites, 1), - serializeArrayOfBufferableToVector(nonZeroContractLeaves, 1), - // We don't prefix the contract data with the length because we already have that info before contract leaves - ...nonZeroContractData.map(x => x.toBuffer()), this.encryptedLogs.toBuffer(), this.unencryptedLogs.toBuffer(), ]); @@ -81,18 +67,11 @@ export class TxEffect { const nonZeroL2ToL1Msgs = reader.readVectorUint8Prefix(Fr); const nonZeroPublicDataWrites = reader.readVectorUint8Prefix(PublicDataWrite); - const nonZeroContractLeaves = reader.readVectorUint8Prefix(Fr); - - const numContracts = nonZeroContractLeaves.length; - const nonZeroContractData = reader.readArray(numContracts, ContractData); - return new TxEffect( padArrayEnd(nonZeroNoteHashes, Fr.ZERO, MAX_NEW_NOTE_HASHES_PER_TX), padArrayEnd(nonZeroNullifiers, Fr.ZERO, MAX_NEW_NULLIFIERS_PER_TX), padArrayEnd(nonZeroL2ToL1Msgs, Fr.ZERO, MAX_NEW_L2_TO_L1_MSGS_PER_TX), padArrayEnd(nonZeroPublicDataWrites, PublicDataWrite.empty(), MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX), - padArrayEnd(nonZeroContractLeaves, Fr.ZERO, MAX_NEW_CONTRACTS_PER_TX), - padArrayEnd(nonZeroContractData, ContractData.empty(), MAX_NEW_CONTRACTS_PER_TX), TxL2Logs.fromBuffer(reader), TxL2Logs.fromBuffer(reader), ); @@ -118,18 +97,11 @@ export class TxEffect { const encryptedLogsHashKernel0 = this.encryptedLogs.hash(); const unencryptedLogsHashKernel0 = this.unencryptedLogs.hash(); - if (MAX_NEW_CONTRACTS_PER_TX !== 1) { - throw new Error('Only one contract per transaction is supported for now.'); - } - const inputValue = Buffer.concat([ noteHashesBuffer, nullifiersBuffer, newL2ToL1MsgsBuffer, publicDataUpdateRequestsBuffer, - this.contractLeaves[0].toBuffer(), - this.contractData[0].contractAddress.toBuffer(), - this.contractData[0].portalContractAddress.toBuffer32(), encryptedLogsHashKernel0, unencryptedLogsHashKernel0, ]); @@ -148,8 +120,6 @@ export class TxEffect { makeTuple(MAX_NEW_NULLIFIERS_PER_TX, Fr.random), makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr.random), makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite.random), - makeTuple(MAX_NEW_CONTRACTS_PER_TX, Fr.random), - makeTuple(MAX_NEW_CONTRACTS_PER_TX, ContractData.random), TxL2Logs.random(numPrivateCallsPerTx, numEncryptedLogsPerCall, LogType.ENCRYPTED), TxL2Logs.random(numPublicCallsPerTx, numUnencryptedLogsPerCall, LogType.UNENCRYPTED), ); @@ -170,8 +140,6 @@ export class TxEffect { nullifiers: [${this.nullifiers.map(h => h.toString()).join(', ')}], l2ToL1Msgs: [${this.l2ToL1Msgs.map(h => h.toString()).join(', ')}], publicDataWrites: [${this.publicDataWrites.map(h => h.toString()).join(', ')}], - contractLeaves: [${this.contractLeaves.map(h => h.toString()).join(', ')}], - contractData: [${this.contractData.map(h => h.toString()).join(', ')}], encryptedLogs: ${JSON.stringify(this.encryptedLogs.toJSON())}, unencryptedLogs: ${JSON.stringify(this.unencryptedLogs.toJSON())} }`; diff --git a/yarn-project/circuits.js/.gitignore b/yarn-project/circuits.js/.gitignore new file mode 100644 index 00000000000..6fc41e1039e --- /dev/null +++ b/yarn-project/circuits.js/.gitignore @@ -0,0 +1 @@ +fixtures/*.json diff --git a/yarn-project/circuits.js/fixtures/Benchmarking.test.json b/yarn-project/circuits.js/fixtures/Benchmarking.test.json deleted file mode 100644 index 5927c4d1224..00000000000 --- a/yarn-project/circuits.js/fixtures/Benchmarking.test.json +++ /dev/null @@ -1,3511 +0,0 @@ -{ - "noir_version": "0.23.0+602f23f4fb698cf6e37071936a2a46593a998d08", - "name": "Benchmarking", - "functions": [ - { - "name": "increment_balance", - "function_type": "Open", - "is_internal": false, - "abi": { - "parameters": [ - { - "name": "inputs", - "type": { - "kind": "struct", - "path": "aztec::abi::PublicContextInputs", - "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::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "storage_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "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_delegate_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_contract_deployment", - "type": { - "kind": "boolean" - } - }, - { - "name": "start_side_effect_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "block_header", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::block_header::BlockHeader", - "fields": [ - { - "name": "note_hash_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "nullifier_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "l1_to_l2_message_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "archive_root", - "type": { - "kind": "field" - } - }, - { - "name": "public_data_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "global_variables_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "public_global_variables", - "type": { - "kind": "struct", - "path": "aztec::abi::PublicGlobalVariables", - "fields": [ - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - }, - { - "name": "block_number", - "type": { - "kind": "field" - } - }, - { - "name": "timestamp", - "type": { - "kind": "field" - } - } - ] - } - } - ] - }, - "visibility": "private" - }, - { - "name": "owner", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - }, - "visibility": "private" - }, - { - "name": "value", - "type": { - "kind": "field" - }, - "visibility": "private" - } - ], - "param_witnesses": { - "inputs": [ - { - "start": 0, - "end": 19 - } - ], - "owner": [ - { - "start": 19, - "end": 20 - } - ], - "value": [ - { - "start": 20, - "end": 21 - } - ] - }, - "return_type": { - "abi_type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::public_circuit_public_inputs::PublicCircuitPublicInputs", - "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::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "storage_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "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_delegate_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_contract_deployment", - "type": { - "kind": "boolean" - } - }, - { - "name": "start_side_effect_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "args_hash", - "type": { - "kind": "field" - } - }, - { - "name": "return_values", - "type": { - "kind": "array", - "length": 4, - "type": { - "kind": "field" - } - } - }, - { - "name": "contract_storage_update_requests", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::contrakt::storage_update_request::StorageUpdateRequest", - "fields": [ - { - "name": "storage_slot", - "type": { - "kind": "field" - } - }, - { - "name": "old_value", - "type": { - "kind": "field" - } - }, - { - "name": "new_value", - "type": { - "kind": "field" - } - } - ] - } - } - }, - { - "name": "contract_storage_reads", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::contrakt::storage_read::StorageRead", - "fields": [ - { - "name": "storage_slot", - "type": { - "kind": "field" - } - }, - { - "name": "current_value", - "type": { - "kind": "field" - } - } - ] - } - } - }, - { - "name": "public_call_stack_hashes", - "type": { - "kind": "array", - "length": 4, - "type": { - "kind": "field" - } - } - }, - { - "name": "new_note_hashes", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::SideEffect", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "new_nullifiers", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::SideEffectLinkedToNoteHash", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "note_hash", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "new_l2_to_l1_msgs", - "type": { - "kind": "array", - "length": 2, - "type": { - "kind": "field" - } - } - }, - { - "name": "unencrypted_logs_hash", - "type": { - "kind": "array", - "length": 2, - "type": { - "kind": "field" - } - } - }, - { - "name": "unencrypted_log_preimages_length", - "type": { - "kind": "field" - } - }, - { - "name": "block_header", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::block_header::BlockHeader", - "fields": [ - { - "name": "note_hash_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "nullifier_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "l1_to_l2_message_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "archive_root", - "type": { - "kind": "field" - } - }, - { - "name": "public_data_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "global_variables_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "prover_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - } - ] - }, - "visibility": "public" - }, - "return_witnesses": [ - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210 - ] - }, - "bytecode": "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", - "debug_symbols": "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0JtO9KYTvelEb7rQmy70pgu96UJvutCbLvSmC73pQm+60Jsu9KYbvelGb7rRm270phu96UZvutGbbvSmG73pRm960Jse9KYHvelBb3rQmx70pge96UFvetCbHvSmF73pRW960Zte9KYXvelFb3rRm170phe96QVvuq4LfcDQBxx9INAHDvpAog8U+kCjDwz6AHrTht60oTdt6E0betOG3rShN23oTRt604betKE37ehNO3rTjt60ozft6E07etOO3rSjN+3oTTt604HedKA3HehNB3rTgd50oDcd6E0HetOB3nSgN33Qmz7oTR/0pg960we96YPeNJqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRFZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRNZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRDZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqRLZqR2YWGZI8nDH7C4ScCfuLATyT8RMFPNPzEwE/Ad27wnRt85wbfucF3bvCdG3znBt+5wXdu8J0bfOcO37nDd+7wnTt85w7fucN37vCdO3znDt+5w3ce8J0HfOcB33nAdx7wnQd85wHfecB3HvCdB3znB77zA9/5ge/8wHd+4Ds/8J0f+M4PfOcHvvMD33nCd57wnSd85wnfecJ3nvCdJ3znCd95wnee8J0XfOcF33nBd17wnRd85wXfecF3XvCdF3znBd95w3fe8J03fOcN33nDd97wnTd85w3fecN33vCdD3znA9/5wHc+8J0PfOcD3/nAdz7wnQ985wPf+cJ3vvCdL3znC9/5wne+8J0vfOcL3/nCdw7ncAbncAbncAbncAbncI8/vsJPJPxEwU80/MTAT8B3DudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwBudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwDudwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwAedwB87hDpzDHTiHO3AOd+Ac7sA53IFzuAPncAfO4Q6cwx04hztwDnfgHO7AOdyBc7gD53AHzuEOnMMdOIc7cA534BzuwDncgXO4A+dwB87hDpzDHTiHO3AOd+Ac7sA53IFzuAPncAfO4Q6cwx04hztwDnfgHO7AOdyBc7gD53AHzuEOnMMdOIc7cA534BzuwDncgXO4A+dwB87hDpzDHTiHO3AOd+Ac7sA53IFzuAPncAfO4Q6cwx04hztwDnfgHO7AOdyBc7gD53AHzuEOnMMdOIc7cA534Bzu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tOyJ9sM03H010Wsp7IdOZD9sorji5UQuN1HITXTkJkryRBH1fOczLycquYn6x030bePnm4lGbqKlT/T8o0LUy4mczezw+GQik5vI5SZiMzv6+ZecsS//NOJHbqKUm6jkJmq1ieLP82j2+Q3PXvk38zzPMMIZTjgjCGccwhl/flP3wzLZvF6eUYQzmnDGEM7Y+884F+EMI5zhhDOCcMYhnEHY80PY80PY80PY80PY8yTseRL2PAl7noQ9T8KeJ2HPk7DnSdjzJOx5Eva8CHtehD0vwp4XYc+LsOdF2PMi7HkR9rwIe16EPW/Cnjdhz5uw503Y8ybseRP2vAl73oQ9b8KeN2HPh7DnQ9jzIez5EPZ8CHs+hD0fwp4PYc+HsOdD2PMl7PkS9nwJe76EPV/Cni9hz5ew50vY8yXs+d6/53FdhDOMcIYTzgjCGYdwRhLOKMIZTThjCGcQ9twIe26EPTfCnhthz42w50bYcyPsuRH23Ah7boQ9d8KeO2HPnbDnTthzJ+y5E/bcCXvuhD13wp47Yc+DsOdB2PMg7HkQ9jwIe07owwWhDxeEPlwQ+nBB6MMFoQ8XhD5cEPpwQejDBaEPF4Q+XBD6cEHowwWhDxeEPlwQ+nBB6MMFoQ8XhD5cEPpwQejDBaEPF4Q+XBD6cEHowwWhDxeEPlwQ+nBB6MMFoQ8XhD5cEPpwQejDBaEPF4Q+XBD6cEHowwWhDxeEPlwQ+nBB6MMFoQ8XhD5cEPpwQejDBaEPF4Q+XBD6cEHowwWhDxeEPlwQ+nBB6MMFoQ8XhD5cEPpwQejDBaEPF4Q+XBD6cEHowwWhDxeEPlwQ+nBB6MMdQh/ufI8+XMzzjF///xdnOOGMIJxxCGck4YwinNGEM4Zwxt5/xvfow316BmHPjbDnRthzI+y5EfbcCHtuhD03wp4bYc+dsOdO2HMn7LkT9twJe+6EPXfCnjthz52w507Y8yDseRD2PAh7/rpH9vyv9V2//+428/z25vGPX3986omPt697377vffu59+331rd/XRf7fm9v97693/v2ce/bn3vf/k9t7X78B39tz8u3r3vfvu99+7n37ffWt8/r3re3e9/e7337uPftz71vf+/W5r1bm/dubf65rbX4+vb56u331rev6963t3vf3u99+7j37c+9b5/3vn3d+/Z979vfu7V179b2vVvb925t37u1fe/W9r1b2/dubd+7tX3v1va9W9v3bu3cu7Vz79bOvVs7927t3Lu1c+/Wzr1bO/du7dy7tXPv1u69W7v3bu3eu7V/56fAXs8fhOLffMuU9fFUvfVUv/XUvPXUvvFU/p0fFfrZUy//bVj1xzeebV//3X8k4Pm6KfEHnnv5b6Tq+YNM+no55b7z1OuGwqdP2VtP+VtPvfyNIT++6y/7uiRlH0/lW0+9vul9rqPb1x+Ilft86vXf/n521uu/z/30KX/rqXjrKfDf/F//+v8A" - }, - { - "name": "compute_note_hash_and_nullifier", - "function_type": "Unconstrained", - "is_internal": false, - "abi": { - "parameters": [ - { - "name": "contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - }, - "visibility": "private" - }, - { - "name": "nonce", - "type": { - "kind": "field" - }, - "visibility": "private" - }, - { - "name": "storage_slot", - "type": { - "kind": "field" - }, - "visibility": "private" - }, - { - "name": "serialized_note", - "type": { - "kind": "array", - "length": 3, - "type": { - "kind": "field" - } - }, - "visibility": "private" - } - ], - "param_witnesses": { - "contract_address": [ - { - "start": 0, - "end": 1 - } - ], - "nonce": [ - { - "start": 1, - "end": 2 - } - ], - "serialized_note": [ - { - "start": 3, - "end": 6 - } - ], - "storage_slot": [ - { - "start": 2, - "end": 3 - } - ] - }, - "return_type": { - "abi_type": { - "kind": "array", - "length": 4, - "type": { - "kind": "field" - } - }, - "visibility": "public" - }, - "return_witnesses": [6, 7, 8, 9] - }, - "bytecode": "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", - "debug_symbols": "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G44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lG44lm44lm44lm44lm44lmxcmbadjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjyaZjycqxZOVYsnIsWTmWrC5M2pZjycqxZOVYsnIsWTmWrBxLVo4lK8eSlWPJyrFk5ViycixZOZasHEtWjiUrx5KVY8nKsWTlWLJyLFk5lqwcS1aOJSvHkpVjycqxZOVYsnIsWTmWrBxLVo4lK8eSlWPJyrFk5ViycixZOZasHEtWjiUrx5KVY8nKsWTlWLJyLFk5lqwcS1aOJSvHkpVjycqxZOVYsnIsWTmWrBxLVo4lK8eSlWPJyrFk5ViycixZOZasHEtWjiUrx5KVY8nKsWTlWLJyLFk5lqwcS1aOJSvHkpVjycqxZOVYsnIsWTmWrBxLVo4lK8eSlWPJyrFk5ViycixZOZasHEtWjiUrx5KVY8nKsWTlWLJyLFk5lqwcS1aOJVuOJVuOJVuOJVuOJVsXJm2XY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mWY8mW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" - }, - { - "name": "broadcast", - "function_type": "Open", - "is_internal": false, - "abi": { - "parameters": [ - { - "name": "inputs", - "type": { - "kind": "struct", - "path": "aztec::abi::PublicContextInputs", - "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::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "storage_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "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_delegate_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_contract_deployment", - "type": { - "kind": "boolean" - } - }, - { - "name": "start_side_effect_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "block_header", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::block_header::BlockHeader", - "fields": [ - { - "name": "note_hash_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "nullifier_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "l1_to_l2_message_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "archive_root", - "type": { - "kind": "field" - } - }, - { - "name": "public_data_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "global_variables_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "public_global_variables", - "type": { - "kind": "struct", - "path": "aztec::abi::PublicGlobalVariables", - "fields": [ - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - }, - { - "name": "block_number", - "type": { - "kind": "field" - } - }, - { - "name": "timestamp", - "type": { - "kind": "field" - } - } - ] - } - } - ] - }, - "visibility": "private" - }, - { - "name": "owner", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - }, - "visibility": "private" - } - ], - "param_witnesses": { - "inputs": [ - { - "start": 0, - "end": 19 - } - ], - "owner": [ - { - "start": 19, - "end": 20 - } - ] - }, - "return_type": { - "abi_type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::public_circuit_public_inputs::PublicCircuitPublicInputs", - "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::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "storage_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "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_delegate_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_contract_deployment", - "type": { - "kind": "boolean" - } - }, - { - "name": "start_side_effect_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "args_hash", - "type": { - "kind": "field" - } - }, - { - "name": "return_values", - "type": { - "kind": "array", - "length": 4, - "type": { - "kind": "field" - } - } - }, - { - "name": "contract_storage_update_requests", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::contrakt::storage_update_request::StorageUpdateRequest", - "fields": [ - { - "name": "storage_slot", - "type": { - "kind": "field" - } - }, - { - "name": "old_value", - "type": { - "kind": "field" - } - }, - { - "name": "new_value", - "type": { - "kind": "field" - } - } - ] - } - } - }, - { - "name": "contract_storage_reads", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::contrakt::storage_read::StorageRead", - "fields": [ - { - "name": "storage_slot", - "type": { - "kind": "field" - } - }, - { - "name": "current_value", - "type": { - "kind": "field" - } - } - ] - } - } - }, - { - "name": "public_call_stack_hashes", - "type": { - "kind": "array", - "length": 4, - "type": { - "kind": "field" - } - } - }, - { - "name": "new_note_hashes", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::SideEffect", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "new_nullifiers", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::SideEffectLinkedToNoteHash", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "note_hash", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "new_l2_to_l1_msgs", - "type": { - "kind": "array", - "length": 2, - "type": { - "kind": "field" - } - } - }, - { - "name": "unencrypted_logs_hash", - "type": { - "kind": "array", - "length": 2, - "type": { - "kind": "field" - } - } - }, - { - "name": "unencrypted_log_preimages_length", - "type": { - "kind": "field" - } - }, - { - "name": "block_header", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::block_header::BlockHeader", - "fields": [ - { - "name": "note_hash_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "nullifier_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "l1_to_l2_message_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "archive_root", - "type": { - "kind": "field" - } - }, - { - "name": "public_data_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "global_variables_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "prover_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - } - ] - }, - "visibility": "public" - }, - "return_witnesses": [ - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209 - ] - }, - "bytecode": "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", - "debug_symbols": "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" - }, - { - "name": "constructor", - "function_type": "Secret", - "is_internal": false, - "abi": { - "parameters": [ - { - "name": "inputs", - "type": { - "kind": "struct", - "path": "aztec::abi::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::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "storage_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "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_delegate_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_contract_deployment", - "type": { - "kind": "boolean" - } - }, - { - "name": "start_side_effect_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "block_header", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::block_header::BlockHeader", - "fields": [ - { - "name": "note_hash_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "nullifier_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "l1_to_l2_message_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "archive_root", - "type": { - "kind": "field" - } - }, - { - "name": "public_data_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "global_variables_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_deployment_data", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::contrakt::deployment_data::ContractDeploymentData", - "fields": [ - { - "name": "deployer_public_key", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::grumpkin_point::GrumpkinPoint", - "fields": [ - { - "name": "x", - "type": { - "kind": "field" - } - }, - { - "name": "y", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "constructor_vk_hash", - "type": { - "kind": "field" - } - }, - { - "name": "function_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_address_salt", - "type": { - "kind": "field" - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - } - ] - } - }, - { - "name": "private_global_variables", - "type": { - "kind": "struct", - "path": "aztec::abi::PrivateGlobalVariables", - "fields": [ - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - } - ] - } - } - ] - }, - "visibility": "private" - } - ], - "param_witnesses": { - "inputs": [ - { - "start": 0, - "end": 23 - } - ] - }, - "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::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "storage_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "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_delegate_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_contract_deployment", - "type": { - "kind": "boolean" - } - }, - { - "name": "start_side_effect_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "args_hash", - "type": { - "kind": "field" - } - }, - { - "name": "return_values", - "type": { - "kind": "array", - "length": 4, - "type": { - "kind": "field" - } - } - }, - { - "name": "read_requests", - "type": { - "kind": "array", - "length": 32, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::SideEffect", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "new_note_hashes", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::SideEffect", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "new_nullifiers", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::SideEffectLinkedToNoteHash", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "note_hash", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "private_call_stack_hashes", - "type": { - "kind": "array", - "length": 4, - "type": { - "kind": "field" - } - } - }, - { - "name": "public_call_stack_hashes", - "type": { - "kind": "array", - "length": 4, - "type": { - "kind": "field" - } - } - }, - { - "name": "new_l2_to_l1_msgs", - "type": { - "kind": "array", - "length": 2, - "type": { - "kind": "field" - } - } - }, - { - "name": "end_side_effect_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "encrypted_logs_hash", - "type": { - "kind": "array", - "length": 2, - "type": { - "kind": "field" - } - } - }, - { - "name": "unencrypted_logs_hash", - "type": { - "kind": "array", - "length": 2, - "type": { - "kind": "field" - } - } - }, - { - "name": "encrypted_log_preimages_length", - "type": { - "kind": "field" - } - }, - { - "name": "unencrypted_log_preimages_length", - "type": { - "kind": "field" - } - }, - { - "name": "block_header", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::block_header::BlockHeader", - "fields": [ - { - "name": "note_hash_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "nullifier_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "l1_to_l2_message_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "archive_root", - "type": { - "kind": "field" - } - }, - { - "name": "public_data_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "global_variables_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_deployment_data", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::contrakt::deployment_data::ContractDeploymentData", - "fields": [ - { - "name": "deployer_public_key", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::grumpkin_point::GrumpkinPoint", - "fields": [ - { - "name": "x", - "type": { - "kind": "field" - } - }, - { - "name": "y", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "constructor_vk_hash", - "type": { - "kind": "field" - } - }, - { - "name": "function_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_address_salt", - "type": { - "kind": "field" - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - } - ] - } - }, - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - } - ] - }, - "visibility": "public" - }, - "return_witnesses": [ - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212 - ] - }, - "bytecode": "H4sIAAAAAAAA/+Xd5XNUVxzG8U2yu6l7CU5wh9XsXdzdqtQLWzb1lir1UupOlXopdaeutLTUvcAfxPMMm5m8gFeczHDme2eeyUxe3NnP3rtXz/n9dqdSqR2pvUuT0qy0KO3d/udlRuNv7sCWfFrrSO9jvcVcR6lUrxTq+WJ+da5QrSXlXKlc60jySb6clNcUkmKxnpSSSrVWreSq+VKxnu8sV4udjRWnw33GXE+4M1pHpgfcmYPcndU6sj3gzgZ0d+33rd32+9R+9v8D/dxtgbdX19IceLuFNPeOxNwU0NwnEnNzQHPfSMwtAc39IjGnA5r7R2LOBDQPiMScDWgeGIm5NaB5UCTmtoDmdqB5MNA8BGgeCjQPA5qHA80jgOaRQPMooHk00DwGaB4LNI8DmscDzROA5olAcw5ozgPNBaC5CDSXgOYy0NwBNFeA5gRorgLNk4DmyUDzFKB5KtA8DWieDjTPAJpnAs2zgObZQPMcoHku0DwPaJ4PNC8AmhcCzYuA5sVA8xKgeSnQvAxoXg40rwCaTwKaTwaaTwGaTwWaTwOaTweaVwLNZwDNZwLNZwHNZwPN5wDN5wLN5wHN5wPNq4Dm1UBzDWi+AGheAzTXgeZOoPlCoPkioPlioPkSoPlSoPkyoPlyoPkKoPlKoHkt0HwV0Hw10HwN0Hwt0Hwd0Hw90LwOaL4BaL4RaL4JaL4ZaL4FaL4VaL4NaL4daF4PNN8BNG8Amu8Emu8Cmu8Gmu8Bmu8Fmu8Dmu8Hmh8Amh8Emh8Cmh8Gmh8Bmh8FmjcCzY8BzY8DzU8AzU8CzU8BzU8DzZuA5meA5meB5ueA5ueB5heA5heB5peA5peB5s1A8ytA8xag+VWg+TWg+XWg+Q2g+U2g+S2g+W2g+R2g+V2g+T2g+X2g+QOg+UOgeSvQ/BHQ/DHQ/AnQ/CnQ/BnQ/DnQ/AXQ/CXQ/BXQ/DXQ/A3Q/C3QvA1o/i4Sc2tA8/fA7bwdaP4BaP4RaN4BNP8ENP8cifmQgOZfIjEfGtD8ayTmwwKaf4vEfHhA8++RmI8IaP4jEvORAc1/RmI+KqD5r0jMRwc0/x2J+ZiA5n8iMR8b0PxvJObjApr/i8R8fEDz/5GYTwho3hmJ+cSA5l2RmHsFNO8OaG7rZm5quFuUtJJRsoqfX/q+0PdJvm/wdbSvK32d5esOn4d9XvJx2sct/469X3s79+q2/m2Nv72VPkpfpZ/SXxmgDFQGKe3KYGWIMlQZpgxXRigjlVHKaGWMMlYZp4xXJigT/Z0oeaXg71opKWWlQ6koiVJVJimTlSnKVGWaMr3x3c5UZimzlTnKXGWeMl9ZoCxUFimLlSXKUmWZslxZobj/vPuxuz+5+3W7f7X7Oa9U3O/X/W/dD9b9Ud0v1P0z3U/S/RVXKe6/V1Pcn839yty/y/2s3N/J/Y7c/8f9cNwfxv1S3D/E/TTcX2Kt4v4Drsfv+vSu1+765a7nvU5xvWfXP3Y9YNfHdb1Y1091PVHX11yvuP7iBsX1+VyvzvXbXM/M9b1c78r1n1wPyfWBXC/H9WNcT8X1RTYqrj/hegyuT+D5+p6/7vncmxTP9/X8V88H9fxIzxf0/DnPJ/P8qs2K599sUTw/w/MVPH7f49k9vtvjnT3+1+NhPT7U4yU9ftDj6Ty+bKvi8Ucej+PxKR6v4fELfp/v99t+3+v3n34f6Pdjfl/kfdPvE/x8fbvi569+Hunnc35e5ec3fp7h+3vf7/r+z/dDvj/w9bKvH3095esLn299/vHx2Mcn/167lj1HMZVAULsAAA==", - "debug_symbols": "q1bKyU9OLMnMzytWsqqurQUA" - }, - { - "name": "recreate_note", - "function_type": "Secret", - "is_internal": false, - "abi": { - "parameters": [ - { - "name": "inputs", - "type": { - "kind": "struct", - "path": "aztec::abi::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::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "storage_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "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_delegate_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_contract_deployment", - "type": { - "kind": "boolean" - } - }, - { - "name": "start_side_effect_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "block_header", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::block_header::BlockHeader", - "fields": [ - { - "name": "note_hash_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "nullifier_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "l1_to_l2_message_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "archive_root", - "type": { - "kind": "field" - } - }, - { - "name": "public_data_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "global_variables_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_deployment_data", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::contrakt::deployment_data::ContractDeploymentData", - "fields": [ - { - "name": "deployer_public_key", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::grumpkin_point::GrumpkinPoint", - "fields": [ - { - "name": "x", - "type": { - "kind": "field" - } - }, - { - "name": "y", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "constructor_vk_hash", - "type": { - "kind": "field" - } - }, - { - "name": "function_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_address_salt", - "type": { - "kind": "field" - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - } - ] - } - }, - { - "name": "private_global_variables", - "type": { - "kind": "struct", - "path": "aztec::abi::PrivateGlobalVariables", - "fields": [ - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - } - ] - } - } - ] - }, - "visibility": "private" - }, - { - "name": "owner", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - }, - "visibility": "private" - }, - { - "name": "index", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - }, - "visibility": "private" - } - ], - "param_witnesses": { - "index": [ - { - "start": 24, - "end": 25 - } - ], - "inputs": [ - { - "start": 0, - "end": 23 - } - ], - "owner": [ - { - "start": 23, - "end": 24 - } - ] - }, - "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::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "storage_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "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_delegate_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_contract_deployment", - "type": { - "kind": "boolean" - } - }, - { - "name": "start_side_effect_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "args_hash", - "type": { - "kind": "field" - } - }, - { - "name": "return_values", - "type": { - "kind": "array", - "length": 4, - "type": { - "kind": "field" - } - } - }, - { - "name": "read_requests", - "type": { - "kind": "array", - "length": 32, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::SideEffect", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "new_note_hashes", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::SideEffect", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "new_nullifiers", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::SideEffectLinkedToNoteHash", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "note_hash", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "private_call_stack_hashes", - "type": { - "kind": "array", - "length": 4, - "type": { - "kind": "field" - } - } - }, - { - "name": "public_call_stack_hashes", - "type": { - "kind": "array", - "length": 4, - "type": { - "kind": "field" - } - } - }, - { - "name": "new_l2_to_l1_msgs", - "type": { - "kind": "array", - "length": 2, - "type": { - "kind": "field" - } - } - }, - { - "name": "end_side_effect_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "encrypted_logs_hash", - "type": { - "kind": "array", - "length": 2, - "type": { - "kind": "field" - } - } - }, - { - "name": "unencrypted_logs_hash", - "type": { - "kind": "array", - "length": 2, - "type": { - "kind": "field" - } - } - }, - { - "name": "encrypted_log_preimages_length", - "type": { - "kind": "field" - } - }, - { - "name": "unencrypted_log_preimages_length", - "type": { - "kind": "field" - } - }, - { - "name": "block_header", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::block_header::BlockHeader", - "fields": [ - { - "name": "note_hash_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "nullifier_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "l1_to_l2_message_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "archive_root", - "type": { - "kind": "field" - } - }, - { - "name": "public_data_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "global_variables_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_deployment_data", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::contrakt::deployment_data::ContractDeploymentData", - "fields": [ - { - "name": "deployer_public_key", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::grumpkin_point::GrumpkinPoint", - "fields": [ - { - "name": "x", - "type": { - "kind": "field" - } - }, - { - "name": "y", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "constructor_vk_hash", - "type": { - "kind": "field" - } - }, - { - "name": "function_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_address_salt", - "type": { - "kind": "field" - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - } - ] - } - }, - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - } - ] - }, - "visibility": "public" - }, - "return_witnesses": [ - 6072, 6073, 6074, 6075, 6076, 6077, 6078, 6079, 6080, 6081, 6082, 6083, 6084, 6085, 6086, 6087, 6088, 6089, - 6090, 6091, 6092, 6093, 6094, 6095, 6096, 6097, 6098, 6099, 6100, 6101, 6102, 6103, 6104, 6105, 6106, 6107, - 6108, 6109, 6110, 6111, 6112, 6113, 6114, 6115, 6116, 6117, 6118, 6119, 6120, 6121, 6122, 6123, 6124, 6125, - 6126, 6127, 6128, 6129, 6130, 6131, 6132, 6133, 6134, 6135, 6136, 6137, 6138, 6139, 6140, 6141, 6142, 6143, - 6144, 6145, 6146, 6147, 6148, 6149, 6150, 6151, 6152, 6153, 6154, 6155, 6156, 6157, 6158, 6159, 6160, 6161, - 6162, 6163, 6164, 6165, 6166, 6167, 6168, 6169, 6170, 6171, 6172, 6173, 6174, 6175, 6176, 6177, 6178, 6179, - 6180, 6181, 6182, 6183, 6184, 6185, 6186, 6187, 6188, 6189, 6190, 6191, 6192, 6193, 6194, 6195, 6196, 6197, - 6198, 6199, 6200, 6201, 6202, 6203, 6204, 6205, 6206, 6207, 6208, 6209, 6210, 6211, 6212, 6213, 6214, 6215, - 6216, 6217, 6218, 6219, 6220, 6221, 6222, 6223, 6224, 6225, 6226, 6227, 6228, 6229, 6230, 6231, 6232, 6233, - 6234, 6235, 6236, 6237, 6238, 6239, 6240, 6241, 6242, 6243, 6244, 6245, 6246, 6247, 6248, 6249, 6250, 6251, - 6252, 6253, 6254, 6255, 6256, 6257, 6258, 6259, 6260 - ] - }, - "bytecode": "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", - "debug_symbols": "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WVuPsdboUo9crKByrFbQYluoWm793Cq3fm6VWz+3yq2fW+XWz61y6+dWufMesZZb7xHry/eIpf0n1b8XVFYrqK5WkK1WUFutIF+toFitoL7Y3FlX27vU1fYuttrexW5t0NmtNzp2642O3XqjY7fe6NitNzp2642O3XqjY7nYENNW27u01fYubbW9S1tt79JW27u01fYubbW9S+urFbTa3qWttnfx1fYuvtq5i996O+K33o74rbcjfuvtiN96O+K33o74rbcjfutzl1ht7xKr7V1itb1LrLZ3idX2LrHa3iVW27vEanuXGKsVtNrepa+2d+mr7V36Yq/d1H7r7Ui/9Xak33o70m+9Hem33o70W29H+q23I+PWrwqN1fYuY7W9y1ht7/IrcCe/tqDV9i5jtb3LWG3vMlbbu4zVTshztb3LasiAuhoyoK6GDKgvRwb80tEgb70dyVtvR25NLqi3JhfUW5ML7NbkArs1ucCOxfYudiy2d7GjrVbQYnsXOxbbu9ix2N7FjsX2LnYstnexstgJua32rr6VxfYuVhbbu9jL36h/WtCdtyN265fk7dYvydutX5K3W78kb/XW25F66+1IvfMPo221d/VttXf1bbV39W21d/WtrrZ3qavtXepqexdbbe9ii52Qm622d7HV9i4vf0n+aUGLoZrt1q+y261fZbdbv8puduvtSLv1dqTdejvSbr0daXf+YbSt9q6+rfauvq32rr6t9q6+tdX2Lm21vYuvtnfx1fYuvtoJua+2d3n5G/VPC1pt7+KLxczYrV9lt1u/ym63fpXd4tbbkbj1diRuvR2JW29HXv/6/S+tfrW9y2rv6ttq7+rbau/qW6y2d+mr7V36anuXvtrepa92Qv7y1++fTeZ9tb1LX23v0hej2dutX2W3W7/Kbrd+ld3Grbcj49bbkXHr7cjr36j/pdXf+ofRq72rb6u9q2+rvatvq72rb7na3iVX27vkanuXXG3v8vp39Z8VtNreJVfbu+Rqe5dcjGZvt36Vvd36VfZ261fZ23Hn7Ug77rwdaUe7dfV33o60484/jG6rvavfVntXv632rn5b7V39Vhbbu7Sy2N6llcX2Lu316ffPClrshLyVxfYurSy2d2llsb1LK4vR7NutX2Vvt36Vvd36VfZWb70def1777+0+ltvR+qttyP1zj+Mbqu9q99We1e/rfau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SddWSddWSddWSddWSddWSddWSddWSddWSddWSddWydBWydBWydBWydBWydBWydBWydBWydBWydBWydBWSWqrJLVVktoqSW2VpLZKUlslqa2S1FZJaqsktVVSjkP8uyL+XRX/zsS/a+Lfufh3If5dF/9uiH8nrpcirpcirpcirpcirpcirpcirpcirpcirpcirpcirpcqrpcqrpcqrpcqrpcqrpcqrpcqrpcqrpcqrpcqrhcT14uJ68XE9WLiejFxvZi4XkxcLyauFxPXi4nrpYnrpYnrpYnrpYnrpYnrpYnrpYnrRfRqi2jWFtGtLaJdW0S/toiGbREd2yJatkX0bIto2hbRtS2ibVtE37aIxm0RndsiWrdF9G6LaN4W0b0ton1bRP+2iAZuER3cIlq4RfRwi2jiFtHFLaKNW0Qft4hGbhGd3CJauUX0coto5hbRzS2inVtEP7eIhm4RHd0iWrpF9HSLaOoW0dUtoq1bRF+3iMZuEZ3dIlq7RfR2i2juFtHdLaK9W0R/t4r+bhX93Sr6u1X0d6vo71bR362iv1tFf7eK/m4V/d0q+rtV9Her6O9W0d+tor9bRX+3/if+7kfIyfn/+nd/18W/G+LfpfZ3/4m/+/zvivh3Vfw7E//u+/XS8/pdox+f31b6+DsX/y7Ev+vi3w3x71L7u//E333+d0X8uyr+nYl/J64XE9eLievFxPVi4noxcb00cb00cb00cb00cb00cb00cb00cb00cb00cb00cb24uF5cXC8urhcX14uL68XF9eLienFxvbi4XlxcLyGulxDXS4jrJcT1EuJ6CXG9hLheQlwvIa6XENdLF9dLF9dLF9dLF9dLF9dLF9dLF9dLF9dLF9dLF9fLENfLENfLENfLENfLENfLENfLENfLENfLENfLENdLiuslxfWS4npJcb2kuF5SXC8prpcU10uK6yW19WLHIf5dEf+uin9n4t818e9c/LsQ/66LfzfEvxPXSxHXSxHXSxHXSxHXSxHXSxHXSxHXSxHXSxHXSxHXSxXXSxXXSxXXSxXXi+jvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvmujvNtHfbaK/20R/t4n+bhP93Sb6u030d5vo7zbR322iv9tEf7eJ/m4T/d0m+rtN9Heb6O820d9tor/bRH+3if5uE/3dJvq7TfR3m+jvNtHfbaK/20R/t4n+bhP93Sb6u030d5vo7zbR322iv9tEf7eJ/m4T/d0m+rtN9Heb6O820d9tor/bRH+3if5uE/3dJvq7TfR3m+jvNtHfbaK/20R/t4n+bhP93Sb6u030d5vo7zbR322iv9tEf7eJ/m4T/d0m+rtN9Heb6O820d9tor/bRH+3if5uE/3dJvq7TfR3m+jvNtHfbaK/20R/t4n+bhP93Sb6u030d5vo7zbR322iv9tEf7eJ/m4T/d0m+rtN9Heb6O820d9tor/bRH+3if5uE/3dJvq7TfR3m+jvNtHfbaK/20R/t4n+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+rov+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+boj+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HnJTPeSmeshN9ZCb6iE31UNuqofcVA+5qR5yUz3kpnrITfWQm+ohN9VDbqqH3FQPuakeclM95KZ6yE31kJvqITfVQ26qh9xUD7mpHnJTPeSmeshN9ZCb6iE31UNuqofcVA+5qR5yUz3kpnrITfWQm+ohN9VDbqqH3FQPuakeclM95KZ6yE31kJvqITfVQ26qh9xUD7mpHnJTPeSmeshN9ZCb6iE31UNuqofcVA+5qR5yUz3kpnrITfWQm+ohN9VDbqqH3FQPuakeclM95KZ6yE31kJvqITfVQ26qh9xUD7mpHnJTPeSmeshN9ZCb6iE31UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UN21UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UMO1UPuqofcVQ+5qx5yVz3krnrIXfWQu+ohd9VD7qqH3FUPuaseclc95K56yF31kLvqIXfVQ+6qh9xVD7mr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VENONeRUQ0415FRDTjXkVENONeRUQ0415FRDTjXkVENONeRUQ0415FRDTjXkVENONeRUQ0415FRDTjXkVENONeRUQ0415FRDTjXkVENONeRUQ0415FRDTjXkVENONeRUQ0415FRDTjXkVENONeRUQ0415FRDTjXkVENONeRUQ0415FRDTjXkVENONeRUQ0415FRDTjXkVENONeRUQ0415FRDTjXkVENONeRUQ0415FRDTjXkVENONeRUQ0415FRDTjXkVEMuNeRSQy415FJDLjXkUkMuNeRSQy415FJDLjXkUkMuNeRSQy415FJDLjXkUkMuNeRSQy415FJDLjXkUkMuNeRSQy415FJDLjXkUkMuNeRSQy415FJDLjXkUkMuNeRSQy415FJDLjXkUkMuNeRSQy415FJDLjXkUkMuNeRSQy415FJDLjXkUkMuNeRSQy415FJDLjXkUkMuNeRSQy415FJDLjXkUkMuNeRSQy415FJDLjXkUkMuNeRSQy415FJDLjXkUkMuNeRSQy415FJDLjXkUkMuNeRSQy415FJDLjXkUkMuNeRSQy415FJDLjXkUkMuNeRSQy415FJD3mrIWw15qyFvNeSthrzVkLca8lZD3mrIWw15qyFvNeSthrzVkLca8lZD3mrIWw15qyFvNeSthrzVkLca8lZD3mrIWw15qyFvNeSthrzVkLca8lZD3mrIWw15qyFvNeSthrzVkLca8lZD3mrIWw15qyFvNeSthrzVkLca8lZD3mrIWw15qyFvNeSthrzVkLca8lZD3mrIWw15qyFvNeSthrzVkLca8lZD3mrIWw15qyFvNeSthrzVkLca8lZD3mrIWw15qyFvNeSthrzVkLca8lZD3mrIWw15qyFvNeSthrzVkLca8lZD3mrIWw15qyFvNeSthrzVkLca8lZD3mrIWw15qyFvNeRWQ2415FZDbjXkVkNuNeRWQ2415FZDbjXkVkNuNeRWQ2415FZDbjXkVkNuNeRWQ2415FZDbjXkVkNuNeRWQ2415FZDbjXkVkNuNeRWQ2415FZDbjXkVkNuNeRWQ2415FZDbjXkVkNuNeRWQ2415FZDbjXkVkNuNeRWQ2415FZDbjXkVkNuNeRWQ2415FZDbjXkVkNuNeRWQ2415FZDbjXkVkNuNeRWQ2415FZDbjXkVkNuNeRWQ2415FZDbjXk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" - }, - { - "name": "create_note", - "function_type": "Secret", - "is_internal": false, - "abi": { - "parameters": [ - { - "name": "inputs", - "type": { - "kind": "struct", - "path": "aztec::abi::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::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "storage_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "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_delegate_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_contract_deployment", - "type": { - "kind": "boolean" - } - }, - { - "name": "start_side_effect_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "block_header", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::block_header::BlockHeader", - "fields": [ - { - "name": "note_hash_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "nullifier_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "l1_to_l2_message_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "archive_root", - "type": { - "kind": "field" - } - }, - { - "name": "public_data_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "global_variables_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_deployment_data", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::contrakt::deployment_data::ContractDeploymentData", - "fields": [ - { - "name": "deployer_public_key", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::grumpkin_point::GrumpkinPoint", - "fields": [ - { - "name": "x", - "type": { - "kind": "field" - } - }, - { - "name": "y", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "constructor_vk_hash", - "type": { - "kind": "field" - } - }, - { - "name": "function_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_address_salt", - "type": { - "kind": "field" - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - } - ] - } - }, - { - "name": "private_global_variables", - "type": { - "kind": "struct", - "path": "aztec::abi::PrivateGlobalVariables", - "fields": [ - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - } - ] - } - } - ] - }, - "visibility": "private" - }, - { - "name": "owner", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - }, - "visibility": "private" - }, - { - "name": "value", - "type": { - "kind": "field" - }, - "visibility": "private" - } - ], - "param_witnesses": { - "inputs": [ - { - "start": 0, - "end": 23 - } - ], - "owner": [ - { - "start": 23, - "end": 24 - } - ], - "value": [ - { - "start": 24, - "end": 25 - } - ] - }, - "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::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "storage_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::AztecAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "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_delegate_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_static_call", - "type": { - "kind": "boolean" - } - }, - { - "name": "is_contract_deployment", - "type": { - "kind": "boolean" - } - }, - { - "name": "start_side_effect_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - }, - { - "name": "args_hash", - "type": { - "kind": "field" - } - }, - { - "name": "return_values", - "type": { - "kind": "array", - "length": 4, - "type": { - "kind": "field" - } - } - }, - { - "name": "read_requests", - "type": { - "kind": "array", - "length": 32, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::SideEffect", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "new_note_hashes", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::SideEffect", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "new_nullifiers", - "type": { - "kind": "array", - "length": 16, - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::side_effect::SideEffectLinkedToNoteHash", - "fields": [ - { - "name": "value", - "type": { - "kind": "field" - } - }, - { - "name": "note_hash", - "type": { - "kind": "field" - } - }, - { - "name": "counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - } - ] - } - } - }, - { - "name": "private_call_stack_hashes", - "type": { - "kind": "array", - "length": 4, - "type": { - "kind": "field" - } - } - }, - { - "name": "public_call_stack_hashes", - "type": { - "kind": "array", - "length": 4, - "type": { - "kind": "field" - } - } - }, - { - "name": "new_l2_to_l1_msgs", - "type": { - "kind": "array", - "length": 2, - "type": { - "kind": "field" - } - } - }, - { - "name": "end_side_effect_counter", - "type": { - "kind": "integer", - "sign": "unsigned", - "width": 32 - } - }, - { - "name": "encrypted_logs_hash", - "type": { - "kind": "array", - "length": 2, - "type": { - "kind": "field" - } - } - }, - { - "name": "unencrypted_logs_hash", - "type": { - "kind": "array", - "length": 2, - "type": { - "kind": "field" - } - } - }, - { - "name": "encrypted_log_preimages_length", - "type": { - "kind": "field" - } - }, - { - "name": "unencrypted_log_preimages_length", - "type": { - "kind": "field" - } - }, - { - "name": "block_header", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::abis::block_header::BlockHeader", - "fields": [ - { - "name": "note_hash_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "nullifier_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "l1_to_l2_message_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "archive_root", - "type": { - "kind": "field" - } - }, - { - "name": "public_data_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "global_variables_hash", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "contract_deployment_data", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::contrakt::deployment_data::ContractDeploymentData", - "fields": [ - { - "name": "deployer_public_key", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::grumpkin_point::GrumpkinPoint", - "fields": [ - { - "name": "x", - "type": { - "kind": "field" - } - }, - { - "name": "y", - "type": { - "kind": "field" - } - } - ] - } - }, - { - "name": "constructor_vk_hash", - "type": { - "kind": "field" - } - }, - { - "name": "function_tree_root", - "type": { - "kind": "field" - } - }, - { - "name": "contract_address_salt", - "type": { - "kind": "field" - } - }, - { - "name": "portal_contract_address", - "type": { - "kind": "struct", - "path": "aztec::protocol_types::address::EthAddress", - "fields": [ - { - "name": "inner", - "type": { - "kind": "field" - } - } - ] - } - } - ] - } - }, - { - "name": "chain_id", - "type": { - "kind": "field" - } - }, - { - "name": "version", - "type": { - "kind": "field" - } - } - ] - }, - "visibility": "public" - }, - "return_witnesses": [ - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234 - ] - }, - "bytecode": "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", - "debug_symbols": "7ZjdbhoxEIXfxdcIzdjj+eFVqlygNpUiRaQq3CHevQtdex1q4XRXVLsNVwjpjP35eOyZ9dG9vn3dHl7ednu3ObroNl+Obv9juzv/2x+2Pw9uAyv3vPvW/Z5W7vvL67PbBDut/pB5gNgrPXjJYgo1cSBKYgLMYkSsqBFM0tiIcJ6+0D+tHC+UW/4ZN4kmcQw6lVtr3CiS0FEs3KY3n7QmfmC3MTQ2KxqEyTgIJMMU1AAKaEkcuJE0pnlgKAeWCzkultwvljwslpzq5JzJFbQxPiUW0+HYIUtFK5QuMIlUaO3CEiezdNZpdhHtHc15Br77DHL3GXT6DKA+z+ChsWddsmU1FTtM1Q32nDa4uINVK1LO1zXTcDjMV6QdQei1AUneJU4FmGI2kAxb6mYpsP/F8JiIBaBhuE9nOhSj2qg2w8Oc/VNJ/lmRhZ1/Z3JcCrlek/s5k1vM5GaNnFVJrTobFOPCZZnhcyyT5rxMBLGhXunthQbmZEpgi4272XNMHJ5FG+oI2ItjHI4yx4uF8WHhBywUzCUiSmnhzbYSQyjGhVFFgh/785H9yV8UWpTwPsXlYeFUC2fdWy/Dwll3y4uwMMy6Yb6rhZrfNzW2PvMCp4pCxVuC9M8a62rBtwF9WObv1wcP6/ozTrRU6BiLzyZKQTQmqEpHGnMDM1RI6XvAdfV+D9lgQr4+i7TWETE2Iqb+XtoKwr8NCp11VRsoHw4yvUqGc5COCaoaEfMmcfFp3GXr0+n0Cw==" - } - ], - "events": [], - "file_map": { - "18": { - "source": "use crate::grumpkin_scalar::GrumpkinScalar;\nuse crate::scalar_mul::fixed_base_embedded_curve;\n\npub fn grumpkin_fixed_base(scalar: GrumpkinScalar) -> [Field; 2] {\n // TODO: this should use both the low and high limbs to do the scalar multiplication\n fixed_base_embedded_curve(scalar.low, scalar.high)\n}\n", - "path": "std/grumpkin_scalar_mul.nr" - }, - "28": { - "source": "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::unsafe::zeroed() }\n }\n\n /// Constructs a Some wrapper around the given value\n pub fn some(_value: T) -> Self {\n Self { _is_some: true, _value }\n }\n\n /// True if this Option is None\n pub fn is_none(self) -> bool {\n !self._is_some\n }\n\n /// True if this Option is Some\n pub fn is_some(self) -> bool {\n self._is_some\n }\n\n /// Asserts `self.is_some()` and returns the wrapped value.\n pub fn unwrap(self) -> T {\n assert(self._is_some);\n self._value\n }\n\n /// Returns the inner value without asserting `self.is_some()`\n /// Note that if `self` is `None`, there is no guarantee what value will be returned,\n /// only that it will be of type `T`.\n pub fn unwrap_unchecked(self) -> T {\n self._value\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value.\n pub fn unwrap_or(self, default: T) -> T {\n if self._is_some {\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 /// 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", - "path": "std/option.nr" - }, - "39": { - "source": "// A contract used for running benchmarks.\n// We should try to change this contract as little as possible, since any modification\n// would alter the metrics we're capturing in the benchmarks, and we want to keep the\n// subject being tested as unmodified as possible so we can detect metric changes that\n// arise from code changes.\n\ncontract Benchmarking {\n use dep::value_note::{\n utils::{increment, decrement},\n value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods},\n };\n\n use dep::aztec::{\n protocol_types::{\n abis::function_selector::FunctionSelector,\n address::AztecAddress,\n },\n context::{Context},\n note::{utils as note_utils, note_getter_options::NoteGetterOptions, note_header::NoteHeader},\n log::emit_unencrypted_log,\n state_vars::{map::Map, public_state::PublicState, set::Set},\n types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN},\n };\n\n struct Storage {\n notes: Map>,\n balances: Map>,\n }\n\n impl Storage {\n fn init(context: Context) -> pub Self {\n Storage {\n notes: Map::new(context, 1, |context, slot| { Set::new(context, slot, ValueNoteMethods) }),\n balances: Map::new(context, 2, |context, slot| { PublicState::new(context, slot, FieldSerializationMethods) }),\n }\n }\n }\n\n #[aztec(private)]\n fn constructor() {}\n\n // Creates a new value note for the target owner. Use this method to seed an initial set of notes.\n #[aztec(private)]\n fn create_note(owner: AztecAddress, value: Field) {\n increment(storage.notes.at(owner), value, owner);\n }\n\n // Deletes a note at a specific index in the set and creates a new one with the same value.\n // We explicitly pass in the note index so we can ensure we consume different notes when sending\n // multiple txs that will land on the same block.\n // See https://discourse.aztec.network/t/utxo-concurrency-issues-for-private-state/635\n // by @rahul-kothari for a full explanation on why this is needed.\n #[aztec(private)]\n fn recreate_note(owner: AztecAddress, index: u32) {\n let owner_notes = storage.notes.at(owner);\n let getter_options = NoteGetterOptions::new().set_limit(1).set_offset(index);\n let notes = owner_notes.get_notes(getter_options);\n let note = notes[0].unwrap_unchecked();\n owner_notes.remove(note);\n increment(owner_notes, note.value, owner);\n }\n\n // Reads and writes to public storage and enqueues a call to another public function.\n #[aztec(public)]\n fn increment_balance(owner: AztecAddress, value: Field) {\n let current = storage.balances.at(owner).read();\n storage.balances.at(owner).write(current + value);\n let _callStackItem1 = context.call_public_function(\n context.this_address(),\n FunctionSelector::from_signature(\"broadcast((Field))\"),\n [owner.to_field()]\n );\n }\n\n // Emits a public log.\n #[aztec(public)]\n fn broadcast(owner: AztecAddress) {\n emit_unencrypted_log(&mut context, storage.balances.at(owner).read());\n }\n\n unconstrained fn compute_note_hash_and_nullifier(\n contract_address: AztecAddress,\n nonce: Field,\n storage_slot: Field,\n serialized_note: [Field; VALUE_NOTE_LEN]\n ) -> pub [Field; 4] {\n let note_header = NoteHeader::new(contract_address, nonce, storage_slot);\n note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, serialized_note)\n }\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/noir-contracts/contracts/benchmarking_contract/src/main.nr" - }, - "40": { - "source": "use crate::{\n abi::{\n PrivateContextInputs,\n PublicContextInputs,\n },\n key::nullifier_key::validate_nullifier_key_against_address,\n messaging::process_l1_to_l2_message,\n oracle::{\n arguments,\n call_private_function::call_private_function_internal,\n public_call::call_public_function_internal,\n enqueue_public_function_call::enqueue_public_function_call_internal,\n context::get_portal_address,\n get_block_header::get_block_header,\n nullifier_key::get_nullifier_key_pair,\n },\n types::vec::BoundedVec,\n utils::Reader,\n};\nuse dep::protocol_types::{\n abis::{\n block_header::BlockHeader,\n call_context::CallContext,\n function_data::FunctionData,\n function_selector::FunctionSelector,\n private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_circuit_public_inputs::PublicCircuitPublicInputs,\n call_stack_item::PrivateCallStackItem,\n call_stack_item::PublicCallStackItem,\n side_effect::{SideEffect, SideEffectLinkedToNoteHash},\n },\n address::{\n AztecAddress,\n EthAddress,\n },\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL,\n MAX_NEW_L2_TO_L1_MSGS_PER_CALL,\n MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n NUM_FIELDS_PER_SHA256,\n RETURN_VALUES_LENGTH,\n },\n contrakt::{\n deployment_data::ContractDeploymentData,\n storage_read::StorageRead,\n storage_update_request::StorageUpdateRequest,\n },\n hash::hash_args,\n grumpkin_point::GrumpkinPoint,\n};\nuse dep::std::{\n grumpkin_scalar::GrumpkinScalar,\n option::Option,\n};\n\n// TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165)\n// use dep::std::collections::vec::Vec;\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n args_hash : Field,\n return_values : BoundedVec,\n\n read_requests: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_stack_hashes : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n block_header: BlockHeader,\n\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165)\n // encrypted_logs_preimages: Vec,\n // unencrypted_logs_preimages: Vec,\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs: inputs,\n side_effect_counter: inputs.call_context.start_side_effect_counter,\n\n args_hash: args_hash,\n return_values: BoundedVec::new();\n call_public_function_internal(\n contract_address, \n function_selector, \n args_hash,\n )\n }\n\n pub fn call_public_function_no_args(\n _self: Self,\n contract_address: AztecAddress, \n function_selector: FunctionSelector,\n ) -> [Field; RETURN_VALUES_LENGTH] {\n call_public_function_internal(\n contract_address, \n function_selector, \n 0,\n )\n }\n\n}\n\nstruct Context {\n private: Option<&mut PrivateContext>,\n public: Option<&mut PublicContext>,\n}\n\nimpl Context {\n pub fn private(context: &mut PrivateContext) -> Context {\n Context {\n private: Option::some(context),\n public: Option::none()\n }\n }\n\n pub fn public(context: &mut PublicContext) -> Context {\n Context {\n public: Option::some(context),\n private: Option::none()\n }\n }\n\n pub fn none() -> Context {\n Context {\n public: Option::none(),\n private: Option::none()\n }\n }\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/context.nr" - }, - "43": { - "source": "use dep::protocol_types::{\n abis::{\n block_header::BlockHeader,\n call_context::CallContext,\n private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_circuit_public_inputs::PublicCircuitPublicInputs,\n },\n contrakt::deployment_data::ContractDeploymentData,\n hash::hash_args,\n};\n\n// docs:start:private-global-variables\nstruct PrivateGlobalVariables {\n chain_id: Field,\n version: Field,\n}\n// docs:end:private-global-variables\n\nimpl PrivateGlobalVariables {\n fn serialize(self) -> [Field; 2] {\n [self.chain_id, self.version]\n }\n}\n\n// docs:start:public-global-variables\nstruct PublicGlobalVariables {\n chain_id: Field,\n version: Field,\n block_number: Field,\n timestamp: Field,\n}\n// docs:end:public-global-variables\n\nimpl PublicGlobalVariables {\n fn serialize(self) -> [Field; 4] {\n [self.chain_id, self.version, self.block_number, self.timestamp]\n }\n}\n\n// PrivateContextInputs are expected to be provided to each private function\n// docs:start:private-context-inputs\nstruct PrivateContextInputs {\n call_context : CallContext,\n block_header: BlockHeader,\n contract_deployment_data: ContractDeploymentData,\n private_global_variables: PrivateGlobalVariables,\n}\n// docs:end:private-context-inputs\n\n// PublicContextInputs are expected to be provided to each public function\n// docs:start:public-context-inputs\nstruct PublicContextInputs {\n call_context: CallContext,\n block_header: BlockHeader,\n\n public_global_variables: PublicGlobalVariables,\n}\n// docs:end:public-context-inputs\n\nstruct Hasher {\n fields: [Field],\n}\n\nimpl Hasher {\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 pub fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/abi.nr" - }, - "47": { - "source": "use dep::std::option::Option;\nuse crate::abi::PublicContextInputs;\nuse dep::protocol_types::{\n constants::{MAX_NOTES_PER_PAGE, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL},\n abis::side_effect::{SideEffect, SideEffectLinkedToNoteHash},\n};\nuse crate::context::{PrivateContext, PublicContext, Context};\nuse crate::note::{\n lifecycle::{create_note, create_note_hash_from_public, destroy_note},\n note_getter::{get_notes, view_notes},\n note_getter_options::NoteGetterOptions,\n note_header::NoteHeader,\n note_interface::NoteInterface,\n note_viewer_options::NoteViewerOptions,\n utils::compute_note_hash_for_read_or_nullify,\n};\n\n// docs:start:struct\nstruct Set {\n context: Context,\n storage_slot: Field,\n note_interface: NoteInterface,\n}\n// docs:end:struct\n\nimpl Set {\n // docs:start:new\n pub fn new(\n context: Context,\n storage_slot: Field,\n note_interface: NoteInterface,\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Set {\n context,\n storage_slot,\n note_interface,\n }\n }\n // docs:end:new\n\n // docs:start:insert\n pub fn insert(self,\n note: &mut Note,\n broadcast: bool,\n ) {\n create_note(\n self.context.private.unwrap(),\n self.storage_slot,\n note,\n self.note_interface,\n broadcast,\n );\n }\n // docs:end:insert\n\n // docs:start:insert_from_public\n pub fn insert_from_public(self, note: &mut Note) {\n create_note_hash_from_public(\n self.context.public.unwrap(),\n self.storage_slot,\n note,\n self.note_interface,\n );\n }\n // docs:end:insert_from_public\n \n // DEPRECATED\n fn assert_contains_and_remove(_self: Self, _note: &mut Note, _nonce: Field) {\n assert(false, \"`assert_contains_and_remove` has been deprecated. Please call PXE.addNote() to add a note to the database. Then use Set.get_notes() and Set.remove() in your contract to verify and remove a note.\");\n }\n\n // DEPRECATED\n fn assert_contains_and_remove_publicly_created(_self: Self, _note: &mut Note) {\n assert(false, \"`assert_contains_and_remove_publicly_created` has been deprecated. Please call PXE.addNote() to add a note to the database. Then use Set.get_notes() and Set.remove() in your contract to verify and remove a note.\");\n }\n\n // docs:start:remove\n pub fn remove(self, note: Note) {\n let context = self.context.private.unwrap();\n let note_hash = compute_note_hash_for_read_or_nullify(self.note_interface, note);\n let has_been_read = context.read_requests.any(|r: SideEffect| r.value == note_hash);\n assert(has_been_read, \"Can only remove a note that has been read from the set.\");\n\n destroy_note(\n context,\n note,\n self.note_interface,\n );\n }\n // docs:end:remove\n\n // docs:start:get_notes\n pub fn get_notes(\n self,\n options: NoteGetterOptions,\n ) -> [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] {\n let storage_slot = self.storage_slot;\n let opt_notes = get_notes(\n self.context.private.unwrap(),\n storage_slot,\n self.note_interface,\n options,\n );\n opt_notes\n }\n // docs:end:get_notes\n\n // docs:start:view_notes\n unconstrained pub fn view_notes(\n self,\n options: NoteViewerOptions,\n ) -> [Option; MAX_NOTES_PER_PAGE] {\n view_notes(self.storage_slot, self.note_interface, options)\n }\n // docs:end:view_notes\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/state_vars/set.nr" - }, - "49": { - "source": "use crate::context::{PrivateContext, PublicContext, Context};\nuse dep::std::option::Option;\nuse dep::protocol_types::{\n hash::pedersen_hash,\n traits::{ToField}\n};\n\n// docs:start:map\nstruct Map {\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V,\n}\n// docs:end:map\n\nimpl 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 {\n context,\n storage_slot,\n state_var_constructor,\n }\n }\n // docs:end:new\n\n // docs:start:at\n pub fn at(self, key: K) -> V where K: ToField {\n // TODO(#1204): use a generator index for the storage slot\n let derived_storage_slot = pedersen_hash([self.storage_slot, key.to_field()],0);\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", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/state_vars/map.nr" - }, - "50": { - "source": "use crate::context::{Context};\nuse crate::oracle::storage::storage_read;\nuse crate::oracle::storage::storage_write;\nuse crate::types::type_serialization::TypeSerializationInterface;\nuse dep::std::option::Option;\n\n// docs:start:public_mutable_struct\nstruct PublicState {\n context: Context,\n storage_slot: Field,\n serialization_methods: TypeSerializationInterface,\n}\n// docs:end:public_mutable_struct\n\nimpl PublicState {\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 serialization_methods: TypeSerializationInterface,\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n PublicState {\n context,\n storage_slot,\n serialization_methods,\n }\n }\n // docs:end:public_mutable_struct_new\n\n // docs:start:public_mutable_struct_read\n pub fn read(self) -> T {\n assert(self.context.private.is_none(), \"Public state reads only supported in public functions\");\n storage_read(self.storage_slot, self.serialization_methods.deserialize)\n }\n // docs:end:public_mutable_struct_read\n\n // docs:start:public_mutable_struct_write\n pub fn write(self, value: T) {\n assert(self.context.private.is_none(), \"Public state writes only supported in public functions\");\n let serialize = self.serialization_methods.serialize;\n let fields = serialize(value);\n storage_write(self.storage_slot, fields);\n }\n // docs:end:public_mutable_struct_write\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/state_vars/public_mutable.nr" - }, - "56": { - "source": "#[oracle(storageRead)]\nfn storage_read_oracle(_storage_slot: Field, _number_of_elements: Field) -> [Field; N] {}\n\nunconstrained fn storage_read_oracle_wrapper(_storage_slot: Field) -> [Field; N] {\n storage_read_oracle(_storage_slot, N)\n}\n\npub fn storage_read(storage_slot: Field, deserialize: fn([Field; N]) -> T) -> T {\n let fields = storage_read_oracle_wrapper(storage_slot);\n deserialize(fields)\n}\n\n#[oracle(storageWrite)]\nfn storage_write_oracle(_storage_slot: Field, _values: [Field; N]) -> [Field; N] {}\n\n// TODO: Remove return value.\nunconstrained pub fn storage_write(storage_slot: Field, fields: [Field; N]) {\n let _hash = storage_write_oracle(storage_slot, fields);\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/oracle/storage.nr" - }, - "57": { - "source": "use dep::protocol_types::{\n address::AztecAddress,\n constants::NUM_FIELDS_PER_SHA256,\n grumpkin_point::GrumpkinPoint,\n};\n\n// TODO: Should take encrypted data.\n#[oracle(emitEncryptedLog)]\nfn emit_encrypted_log_oracle(\n _contract_address: AztecAddress,\n _storage_slot: Field,\n _encryption_pub_key: GrumpkinPoint,\n _preimage: [Field; N]\n) -> Field {}\n\nunconstrained pub fn emit_encrypted_log(\n contract_address: AztecAddress,\n storage_slot: Field,\n encryption_pub_key: GrumpkinPoint,\n preimage: [Field; N]\n) -> [Field; NUM_FIELDS_PER_SHA256] {\n [emit_encrypted_log_oracle(contract_address, storage_slot, encryption_pub_key, preimage), 0]\n}\n\n#[oracle(emitUnencryptedLog)]\nfn emit_unencrypted_log_oracle(_contract_address: AztecAddress, _event_selector: Field, _message: T) -> Field {}\n\nunconstrained pub fn emit_unencrypted_log(\n contract_address: AztecAddress,\n event_selector: Field,\n message: T\n) -> [Field; NUM_FIELDS_PER_SHA256] {\n // https://github.com/AztecProtocol/aztec-packages/issues/885\n [emit_unencrypted_log_oracle(contract_address, event_selector, message), 0]\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/oracle/logs.nr" - }, - "59": { - "source": "#[oracle(packArguments)]\nfn pack_arguments_oracle(_args: [Field; N]) -> Field {}\n\n// TODO: explain what this does.\nunconstrained pub fn pack_arguments(args: [Field; N]) -> Field {\n pack_arguments_oracle(args)\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/oracle/arguments.nr" - }, - "61": { - "source": "use dep::protocol_types::{\n abis::function_selector::FunctionSelector,\n address::AztecAddress,\n constants::RETURN_VALUES_LENGTH,\n};\n\n#[oracle(callPublicFunction)]\nfn call_public_function_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field\n) -> [Field; RETURN_VALUES_LENGTH] {}\n\nunconstrained pub fn call_public_function_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field\n) -> [Field; RETURN_VALUES_LENGTH] {\n call_public_function_oracle(contract_address, function_selector, args_hash)\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/oracle/public_call.nr" - }, - "65": { - "source": "use dep::protocol_types::{\n address::{\n AztecAddress,\n PartialAddress,\n },\n grumpkin_point::GrumpkinPoint,\n};\n\n#[oracle(getPublicKeyAndPartialAddress)]\nfn get_public_key_and_partial_address_oracle(_address: AztecAddress) -> [Field; 3] {}\n\nunconstrained fn get_public_key_and_partial_address_internal(address: AztecAddress) -> [Field; 3] {\n get_public_key_and_partial_address_oracle(address)\n}\n\npub fn get_public_key(address: AztecAddress) -> GrumpkinPoint {\n let result = get_public_key_and_partial_address_internal(address);\n let pub_key = GrumpkinPoint::new(result[0], result[1]);\n let partial_address = PartialAddress::from_field(result[2]);\n\n let calculated_address = AztecAddress::compute(pub_key, partial_address);\n assert(calculated_address.eq(address));\n\n pub_key\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/oracle/get_public_key.nr" - }, - "69": { - "source": "#[oracle(getRandomField)]\nfn rand_oracle() -> Field {}\n\nunconstrained pub fn rand() -> Field {\n rand_oracle()\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/oracle/rand.nr" - }, - "70": { - "source": "use dep::std::option::Option;\nuse crate::note::{\n note_header::NoteHeader,\n note_interface::NoteInterface,\n};\nuse crate::utils::arr_copy_slice;\n\nuse dep::protocol_types::address::AztecAddress;\n\n#[oracle(notifyCreatedNote)]\nfn notify_created_note_oracle(_storage_slot: Field, _serialized_note: [Field; N], _inner_note_hash: Field) -> Field {}\n\nunconstrained pub fn notify_created_note(storage_slot: Field, serialized_note: [Field; N], inner_note_hash: Field) -> Field {\n notify_created_note_oracle(storage_slot, serialized_note, inner_note_hash)\n}\n\n#[oracle(notifyNullifiedNote)]\nfn notify_nullified_note_oracle(_nullifier: Field, _inner_note_hash: Field) -> Field {}\n\nunconstrained pub fn notify_nullified_note(nullifier: Field, inner_note_hash: Field) -> Field {\n notify_nullified_note_oracle(nullifier, inner_note_hash)\n}\n\n#[oracle(getNotes)]\nfn get_notes_oracle(\n _storage_slot: Field,\n _num_selects: u8,\n _select_by: [u8; N],\n _select_values: [Field; N],\n _sort_by: [u8; N],\n _sort_order: [u2; N],\n _limit: u32,\n _offset: u32,\n _return_size: u32,\n _placeholder_fields: [Field; S]\n) -> [Field; S] {}\n\nunconstrained fn get_notes_oracle_wrapper(\n storage_slot: Field,\n num_selects: u8,\n select_by: [u8; N],\n select_values: [Field; N],\n sort_by: [u8; N],\n sort_order: [u2; N],\n limit: u32,\n offset: u32,\n mut placeholder_fields: [Field; S]\n) -> [Field; S] {\n let return_size = placeholder_fields.len() as u32;\n get_notes_oracle(\n storage_slot,\n num_selects,\n select_by,\n select_values,\n sort_by,\n sort_order,\n limit,\n offset,\n return_size,\n placeholder_fields\n )\n}\n\nunconstrained pub fn get_notes(\n storage_slot: Field,\n note_interface: NoteInterface,\n num_selects: u8,\n select_by: [u8; M],\n select_values: [Field; M],\n sort_by: [u8; M],\n sort_order: [u2; M],\n limit: u32,\n offset: u32,\n mut placeholder_opt_notes: [Option; S], // TODO: Remove it and use `limit` to initialize the note array.\n placeholder_fields: [Field; NS] // TODO: Remove it and use `limit` to initialize the note array.\n) -> [Option; S] {\n let fields = get_notes_oracle_wrapper(\n storage_slot,\n num_selects,\n select_by,\n select_values,\n sort_by,\n sort_order,\n limit,\n offset,\n placeholder_fields\n );\n let num_notes = fields[0] as u32;\n let contract_address = AztecAddress::from_field(fields[1]);\n let deserialize = note_interface.deserialize;\n let set_header = note_interface.set_header;\n for i in 0..placeholder_opt_notes.len() {\n if i as u32 < num_notes {\n // lengths named as per typescript.\n let return_header_length: Field = 2; // num_notes & contract_address.\n let extra_preimage_length: Field = 2; // nonce & is_transient.\n let read_offset: Field = return_header_length + i * (N + extra_preimage_length);\n let nonce = fields[read_offset];\n let is_transient = fields[read_offset + 1] as bool;\n let header = NoteHeader { contract_address, nonce, storage_slot, is_transient };\n let serialized_note = arr_copy_slice(fields, [0; N], read_offset + 2);\n let mut note = deserialize(serialized_note);\n set_header(&mut note, header);\n placeholder_opt_notes[i] = Option::some(note);\n };\n }\n placeholder_opt_notes\n}\n\n#[oracle(checkNullifierExists)]\nfn check_nullifier_exists_oracle(_inner_nullifier: Field) -> Field {}\n\nunconstrained pub fn check_nullifier_exists(inner_nullifier: Field) -> bool {\n check_nullifier_exists_oracle(inner_nullifier) == 1\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/oracle/notes.nr" - }, - "73": { - "source": "use dep::protocol_types::{\n address::AztecAddress,\n grumpkin_point::GrumpkinPoint,\n};\nuse dep::std::grumpkin_scalar::GrumpkinScalar;\n\nstruct KeyPair {\n public_key: GrumpkinPoint,\n secret_key: GrumpkinScalar,\n}\n\n#[oracle(getNullifierKeyPair)]\nfn get_nullifier_key_pair_oracle(_account: AztecAddress) -> [Field; 4] {}\n\nunconstrained fn get_nullifier_key_pair_internal(account: AztecAddress) -> KeyPair {\n let result = get_nullifier_key_pair_oracle(account);\n KeyPair {\n public_key: GrumpkinPoint { x: result[0], y: result[1] },\n secret_key: GrumpkinScalar { high: result[2], low: result[3] }\n }\n}\n\npub fn get_nullifier_key_pair(account: AztecAddress) -> KeyPair {\n get_nullifier_key_pair_internal(account)\n}\n\npub fn get_nullifier_secret_key(account: AztecAddress) -> GrumpkinScalar {\n get_nullifier_key_pair_internal(account).secret_key\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/oracle/nullifier_key.nr" - }, - "76": { - "source": "pub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: Field) -> [T; M] {\n for i in 0..dst.len() {\n dst[i] = src[i + offset];\n }\n dst\n}\n\n// TODO(#3470): Copied over from https://github.com/AztecProtocol/aztec-packages/blob/a07c4bd47313be6aa604a63f37857eb0136b41ba/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr#L599\n// move to a shared place?\n\n// TODO to radix returns u8, so we cannot use bigger radixes. It'd be ideal to use a radix of the maximum range-constrained integer noir supports\npub fn full_field_less_than(lhs: Field, rhs: Field) -> bool {\n lhs.lt(rhs)\n}\n\npub fn full_field_greater_than(lhs: Field, rhs: Field) -> bool {\n rhs.lt(lhs)\n}\n\nstruct Reader {\n data: [Field; N],\n offset: Field,\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_array(&mut self, mut result: [Field; K]) -> [Field; K] {\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array([0; K]));\n result\n }\n\n pub fn read_struct_array(&mut self, deserialise: fn([Field; K]) -> T, mut result: [T; C]) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn finish(self) {\n assert(self.offset == self.data.len(), \"Reader did not read all data\");\n } \n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/utils.nr" - }, - "77": { - "source": "use crate::context::{PrivateContext, PublicContext};\nuse crate::oracle;\nuse dep::protocol_types::{\n address::AztecAddress,\n grumpkin_point::GrumpkinPoint,\n};\n\npub fn emit_encrypted_log(\n context: &mut PrivateContext,\n contract_address: AztecAddress,\n storage_slot: Field,\n encryption_pub_key: GrumpkinPoint,\n log: [Field; N]\n) {\n let _ = oracle::logs::emit_encrypted_log(contract_address, storage_slot, encryption_pub_key, log);\n context.accumulate_encrypted_logs(log);\n}\n\npub fn emit_unencrypted_log(context: &mut PublicContext, log: T) {\n let contract_address = context.this_address();\n let event_selector = 5; // TODO: compute actual event selector.\n let _ = oracle::logs::emit_unencrypted_log(contract_address, event_selector, log);\n // context.accumulate_unencrypted_logs(log);\n}\n\n// TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n// --> might be a better approach to force devs to make a public function call that emits the log if needed then\n// it would be less easy to accidentally leak information.\n// If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\npub fn emit_unencrypted_log_from_private(context: &mut PrivateContext, log: T) {\n let contract_address = context.this_address();\n let event_selector = 5; // TODO: compute actual event selector.\n let _ = oracle::logs::emit_unencrypted_log(contract_address, event_selector, log);\n // context.accumulate_unencrypted_logs(log);\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/log.nr" - }, - "78": { - "source": "use crate::oracle::get_public_key::get_public_key;\nuse dep::protocol_types::{\n address::AztecAddress,\n grumpkin_point::GrumpkinPoint,\n};\nuse dep::std::{\n grumpkin_scalar::GrumpkinScalar,\n grumpkin_scalar_mul::grumpkin_fixed_base,\n};\n\npub fn validate_nullifier_key_against_address(\n address: AztecAddress,\n nullifier_public_key: GrumpkinPoint,\n nullifier_secret_key: GrumpkinScalar\n) {\n // TODO: Nullifier public key should be part of the address.\n // Validation of the secret key should happen in the kernel circuit.\n let owner_public_key = get_public_key(address);\n assert(owner_public_key.x == nullifier_public_key.x);\n assert(owner_public_key.y == nullifier_public_key.y);\n let computed_public_key = grumpkin_fixed_base(nullifier_secret_key);\n assert(owner_public_key.x == computed_public_key[0]);\n assert(owner_public_key.y == computed_public_key[1]);\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/key/nullifier_key.nr" - }, - "87": { - "source": "use dep::std::option::Option;\nuse dep::protocol_types::constants::{\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n GET_NOTE_ORACLE_RETURN_LENGTH,\n GET_NOTES_ORACLE_RETURN_LENGTH,\n MAX_NOTES_PER_PAGE,\n VIEW_NOTE_ORACLE_RETURN_LENGTH,\n};\nuse crate::context::PrivateContext;\nuse crate::note::{\n note_getter_options::{NoteGetterOptions, Select, Sort, SortOrder},\n note_interface::NoteInterface,\n note_viewer_options::NoteViewerOptions,\n utils::compute_note_hash_for_read_or_nullify,\n};\nuse crate::oracle;\nuse crate::types::vec::BoundedVec;\n\nfn check_note_header(\n context: PrivateContext,\n storage_slot: Field,\n note_interface: NoteInterface,\n note: Note\n) {\n let get_header = note_interface.get_header;\n let header = get_header(note);\n let contract_address = context.this_address();\n assert(header.contract_address.eq(contract_address));\n assert(header.storage_slot == storage_slot);\n}\n\nfn check_note_fields(fields: [Field; N], selects: BoundedVec, N>) {\n for i in 0..selects.len {\n let select = selects.get_unchecked(i).unwrap_unchecked();\n assert(fields[select.field_index] == select.value, \"Mismatch return note field.\");\n }\n}\n\nfn check_notes_order(\n fields_0: [Field; N],\n fields_1: [Field; N],\n sorts: BoundedVec, N>\n) {\n for i in 0..sorts.len {\n let sort = sorts.get_unchecked(i).unwrap_unchecked();\n let eq = fields_0[sort.field_index] == fields_1[sort.field_index];\n let lt = fields_0[sort.field_index] as u120 < fields_1[sort.field_index] as u120;\n if sort.order == SortOrder.ASC {\n assert(eq | lt, \"Return notes not sorted in ascending order.\");\n } else if !eq {\n assert(!lt, \"Return notes not sorted in descending order.\");\n }\n }\n}\n\npub fn get_note(\n context: &mut PrivateContext,\n storage_slot: Field,\n note_interface: NoteInterface\n) -> Note {\n let note = get_note_internal(storage_slot, note_interface);\n\n check_note_header(*context, storage_slot, note_interface, note);\n\n let note_hash_for_read_request = compute_note_hash_for_read_or_nullify(note_interface, note);\n\n context.push_read_request(note_hash_for_read_request);\n note\n}\n\npub fn get_notes(\n context: &mut PrivateContext,\n storage_slot: Field,\n note_interface: NoteInterface,\n options: NoteGetterOptions\n) -> [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] {\n let opt_notes = get_notes_internal(storage_slot, note_interface, options);\n let mut num_notes = 0;\n let mut prev_fields = [0; N];\n for i in 0..opt_notes.len() {\n let opt_note = opt_notes[i];\n if opt_note.is_some() {\n let note = opt_note.unwrap_unchecked();\n let serialize = note_interface.serialize;\n let fields = serialize(note);\n check_note_header(*context, storage_slot, note_interface, note);\n check_note_fields(fields, options.selects);\n if i != 0 {\n check_notes_order(prev_fields, fields, options.sorts);\n }\n prev_fields = fields;\n\n let note_hash_for_read_request = compute_note_hash_for_read_or_nullify(note_interface, note);\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1410): test to ensure\n // failure if malicious oracle injects 0 nonce here for a \"pre-existing\" note.\n context.push_read_request(note_hash_for_read_request);\n\n num_notes += 1;\n };\n }\n if options.limit != 0 {\n assert(num_notes <= options.limit, \"Invalid number of return notes.\");\n }\n opt_notes\n}\n\nunconstrained fn get_note_internal(storage_slot: Field, note_interface: NoteInterface) -> Note {\n let placeholder_note = [Option::none()];\n let placeholder_fields = [0; GET_NOTE_ORACLE_RETURN_LENGTH];\n oracle::notes::get_notes(\n storage_slot,\n note_interface,\n 0,\n [],\n [],\n [],\n [],\n 1, // limit\n 0, // offset\n placeholder_note,\n placeholder_fields\n )[0].unwrap() // Notice: we don't allow dummies to be returned from get_note (singular).\n}\n\nunconstrained fn get_notes_internal(\n storage_slot: Field,\n note_interface: NoteInterface,\n options: NoteGetterOptions\n) -> [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] {\n let (num_selects, select_by, select_values, sort_by, sort_order) = flatten_options(options.selects, options.sorts);\n let placeholder_opt_notes = [Option::none(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL];\n let placeholder_fields = [0; GET_NOTES_ORACLE_RETURN_LENGTH];\n let opt_notes = oracle::notes::get_notes(\n storage_slot,\n note_interface,\n num_selects,\n select_by,\n select_values,\n sort_by,\n sort_order,\n options.limit,\n options.offset,\n placeholder_opt_notes,\n placeholder_fields\n );\n\n let filter = options.filter;\n let filter_args = options.filter_args;\n filter(opt_notes, filter_args)\n}\n\nunconstrained pub fn view_notes(\n storage_slot: Field,\n note_interface: NoteInterface,\n options: NoteViewerOptions\n) -> [Option; MAX_NOTES_PER_PAGE] {\n let (num_selects, select_by, select_values, sort_by, sort_order) = flatten_options(options.selects, options.sorts);\n let placeholder_opt_notes = [Option::none(); MAX_NOTES_PER_PAGE];\n let placeholder_fields = [0; VIEW_NOTE_ORACLE_RETURN_LENGTH];\n oracle::notes::get_notes(\n storage_slot,\n note_interface,\n num_selects,\n select_by,\n select_values,\n sort_by,\n sort_order,\n options.limit,\n options.offset,\n placeholder_opt_notes,\n placeholder_fields\n )\n}\n\nunconstrained fn flatten_options(\n selects: BoundedVec, N>,\n sorts: BoundedVec, N>\n) -> (u8, [u8; N], [Field; N], [u8; N], [u2; N]) {\n let mut num_selects = 0;\n let mut select_by = [0; N];\n let mut select_values = [0; N];\n for i in 0..selects.len {\n let select = selects.get(i);\n if select.is_some() {\n select_by[num_selects] = select.unwrap_unchecked().field_index;\n select_values[num_selects] = select.unwrap_unchecked().value;\n num_selects += 1;\n };\n }\n\n let mut sort_by = [0; N];\n let mut sort_order = [0; N];\n for i in 0..sorts.len {\n let sort = sorts.get(i);\n if sort.is_some() {\n sort_by[i] = sort.unwrap_unchecked().field_index;\n sort_order[i] = sort.unwrap_unchecked().order;\n };\n }\n\n (num_selects, select_by, select_values, sort_by, sort_order)\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/note/note_getter.nr" - }, - "88": { - "source": "use crate::abi::PublicContextInputs;\nuse crate::context::{\n PrivateContext,\n PublicContext,\n};\nuse crate::note::{\n note_header::NoteHeader,\n note_interface::NoteInterface,\n utils::compute_inner_note_hash,\n};\nuse crate::oracle::notes::{notify_created_note, notify_nullified_note};\n\npub fn create_note(\n context: &mut PrivateContext,\n storage_slot: Field,\n note: &mut Note,\n note_interface: NoteInterface,\n broadcast: bool\n) {\n let contract_address = (*context).this_address();\n\n let header = NoteHeader { contract_address, storage_slot, nonce: 0, is_transient: true };\n let set_header = note_interface.set_header;\n set_header(note, header);\n let inner_note_hash = compute_inner_note_hash(note_interface, *note);\n\n let serialize = note_interface.serialize;\n let serialized_note = serialize(*note);\n assert(notify_created_note(storage_slot, serialized_note, inner_note_hash) == 0);\n\n context.push_new_note_hash(inner_note_hash);\n\n if broadcast {\n let broadcast = note_interface.broadcast;\n broadcast(context, storage_slot, *note);\n }\n}\n\npub fn create_note_hash_from_public(\n context: &mut PublicContext,\n storage_slot: Field,\n note: &mut Note,\n note_interface: NoteInterface\n) {\n let contract_address = (*context).this_address();\n\n let header = NoteHeader { contract_address, storage_slot, nonce: 0, is_transient: true };\n let set_header = note_interface.set_header;\n set_header(note, header);\n let inner_note_hash = compute_inner_note_hash(note_interface, *note);\n\n context.push_new_note_hash(inner_note_hash);\n}\n\npub fn destroy_note(\n context: &mut PrivateContext,\n note: Note,\n note_interface: NoteInterface\n) {\n let mut nullifier = 0;\n let mut nullified_commitment: Field = 0;\n let compute_nullifier = note_interface.compute_nullifier;\n nullifier = compute_nullifier(note, context);\n\n // We also need the note commitment corresponding to the \"nullifier\"\n let get_header = note_interface.get_header;\n let header = get_header(note);\n // `nullified_commitment` is used to inform the kernel which pending note hash\n // the nullifier corresponds to so they can be matched and both squashed/deleted.\n // nonzero nonce implies \"persistable\" nullifier (nullifies a persistent/in-tree\n // commitment) in which case `nullified_commitment` is not used since the kernel\n // just siloes and forwards the nullifier to its output.\n if (header.is_transient) {\n // TODO(1718): Can we reuse the note commitment computed in `compute_nullifier`?\n nullified_commitment = compute_inner_note_hash(note_interface, note);\n }\n assert(notify_nullified_note(nullifier, nullified_commitment) == 0);\n\n context.push_new_nullifier(nullifier, nullified_commitment)\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/note/lifecycle.nr" - }, - "91": { - "source": "use dep::protocol_types::{\n address::AztecAddress,\n constants::{\n GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n GENERATOR_INDEX__SILOED_NOTE_HASH,\n },\n hash::pedersen_hash,\n};\n\npub fn compute_inner_hash(storage_slot: Field, note_hash: Field) -> Field {\n // TODO(#1205) Do we need a generator index here?\n pedersen_hash([storage_slot, note_hash], 0)\n}\n\npub fn compute_siloed_hash(contract_address: AztecAddress, inner_note_hash: Field) -> Field {\n let inputs = [contract_address.to_field(), inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__SILOED_NOTE_HASH)\n}\n\npub fn compute_unique_hash(nonce: Field, siloed_note_hash: Field) -> Field {\n let inputs = [nonce, siloed_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/note/note_hash.nr" - }, - "92": { - "source": "use dep::protocol_types::{\n constants::GENERATOR_INDEX__OUTER_NULLIFIER,\n hash::pedersen_hash,\n};\nuse crate::{\n context::PrivateContext,\n note::{\n note_hash::{compute_inner_hash, compute_siloed_hash, compute_unique_hash},\n note_header::NoteHeader,\n note_interface::NoteInterface,\n },\n utils::arr_copy_slice,\n};\n\npub fn compute_inner_note_hash(note_interface: NoteInterface, note: Note) -> Field {\n let get_header = note_interface.get_header;\n let header = get_header(note);\n\n let compute_note_hash = note_interface.compute_note_hash;\n let note_hash = compute_note_hash(note);\n\n compute_inner_hash(header.storage_slot, note_hash)\n}\n\npub fn compute_siloed_note_hash(note_interface: NoteInterface, note_with_header: Note) -> Field {\n let get_header = note_interface.get_header;\n let header = get_header(note_with_header);\n\n let inner_note_hash = compute_inner_note_hash(note_interface, note_with_header);\n\n compute_siloed_hash(header.contract_address, inner_note_hash)\n}\n\npub fn compute_unique_siloed_note_hash(note_interface: NoteInterface, note_with_header: Note) -> Field {\n let get_header = note_interface.get_header;\n let header = get_header(note_with_header);\n\n let siloed_note_hash = compute_siloed_note_hash(note_interface, note_with_header);\n\n compute_unique_hash(header.nonce, siloed_note_hash)\n}\n\npub fn compute_siloed_nullifier(\n note_interface: NoteInterface,\n note_with_header: Note,\n context: &mut PrivateContext\n) -> Field {\n let get_header = note_interface.get_header;\n let header = get_header(note_with_header);\n\n let compute_nullifier = note_interface.compute_nullifier;\n let inner_nullifier = compute_nullifier(note_with_header, context);\n\n let input = [header.contract_address.to_field(), inner_nullifier];\n pedersen_hash(input, GENERATOR_INDEX__OUTER_NULLIFIER)\n}\n\npub fn compute_note_hash_for_read_or_nullify(note_interface: NoteInterface, note_with_header: Note) -> Field {\n let get_header = note_interface.get_header;\n let header = get_header(note_with_header);\n\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386)\n if (header.is_transient) {\n // If a note is transient, we just read the inner_note_hash (kernel will silo by contract address).\n compute_inner_note_hash(note_interface, note_with_header)\n } else if (header.nonce == 0) {\n // If not transient and nonce is zero, that means we are reading a public note.\n compute_siloed_note_hash(note_interface, note_with_header)\n } else {\n // When nonce is nonzero, that means we are reading a settled note (from tree) created in a\n // previous TX. So we need the unique_siloed_note_hash which has already been hashed with\n // contract address and then nonce. This hash will match the existing leaf in the private\n // data tree, so the kernel can just perform a membership check directly on this hash/leaf.\n compute_unique_siloed_note_hash(note_interface, note_with_header)\n }\n}\n\npub fn compute_note_hash_and_nullifier(\n note_interface: NoteInterface,\n note_header: NoteHeader,\n serialized_note: [Field; S]\n) -> [Field; 4] {\n let deserialize = note_interface.deserialize;\n let set_header = note_interface.set_header;\n let mut note = deserialize(arr_copy_slice(serialized_note, [0; N], 0));\n set_header(&mut note, note_header);\n\n let compute_note_hash = note_interface.compute_note_hash;\n let note_hash = compute_note_hash(note);\n let inner_note_hash = compute_inner_hash(note_header.storage_slot, note_hash);\n\n let siloed_note_hash = compute_siloed_hash(note_header.contract_address, inner_note_hash);\n\n let unique_siloed_note_hash = compute_unique_hash(note_header.nonce, siloed_note_hash);\n\n let compute_nullifier_without_context = note_interface.compute_nullifier_without_context;\n let inner_nullifier = compute_nullifier_without_context(note);\n\n [inner_note_hash, siloed_note_hash, unique_siloed_note_hash, inner_nullifier]\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/note/utils.nr" - }, - "94": { - "source": "struct BoundedVec {\n storage: [T; MaxLen],\n len: Field,\n}\n\nimpl BoundedVec {\n pub fn new(initial_value: T) -> Self {\n BoundedVec { storage: [initial_value; MaxLen], len: 0 }\n }\n\n pub fn get(mut self: Self, index: Field) -> T {\n assert(index as u64 < self.len as u64);\n self.storage[index]\n }\n\n pub fn get_unchecked(mut self: Self, index: Field) -> T {\n self.storage[index]\n }\n\n pub fn push(&mut self, elem: T) {\n assert(self.len as u64 < MaxLen as u64);\n\n self.storage[self.len] = elem;\n self.len += 1;\n }\n\n pub fn push_array(&mut self, array: [T; Len]) {\n let newLen = self.len + array.len();\n assert(newLen as u64 <= MaxLen as u64);\n for i in 0..array.len() {\n self.storage[self.len + i] = array[i];\n }\n self.len = newLen;\n }\n\n pub fn pop(&mut self) -> T {\n assert(self.len as u64 > 0);\n\n let elem = self.storage[self.len - 1];\n self.len -= 1;\n elem\n }\n\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n let mut exceeded_len = false;\n for i in 0..MaxLen {\n exceeded_len |= i == self.len;\n if (!exceeded_len) {\n ret |= predicate(self.storage[i]);\n }\n }\n ret\n }\n}\n\n#[test]\nfn test_vec_push_pop() {\n let mut vec: BoundedVec = BoundedVec::new();\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/types/vec.nr" - }, - "97": { - "source": "use crate::types::type_serialization::TypeSerializationInterface;\n\n// docs:start:field_serialization\nglobal FIELD_SERIALIZED_LEN: Field = 1;\n\nfn deserializeField(fields: [Field; FIELD_SERIALIZED_LEN]) -> Field {\n fields[0]\n}\n\nfn serializeField(value: Field) -> [Field; FIELD_SERIALIZED_LEN] {\n [value]\n}\n\nglobal FieldSerializationMethods = TypeSerializationInterface {\n deserialize: deserializeField,\n serialize: serializeField,\n};\n// docs:end:field_serialization", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/aztec/src/types/type_serialization/field_serialization.nr" - }, - "105": { - "source": "global ARGS_LENGTH: Field = 16;\nglobal RETURN_VALUES_LENGTH: Field = 4;\n\n/**\n * Convention for constant array lengths are mainly divided in 2 classes:\n * - FUNCTION CALL\n * - TRANSACTION\n *\n * Agreed convention is to use MAX_XXX_PER_CALL resp. MAX_XXX_PER_TX, where XXX denotes a type of element such as\n * commitment, or nullifier, e.g.,:\n * - MAX_NEW_NULLIFIERS_PER_CALL\n * - MAX_NEW_NOTE_HASHES_PER_TX\n *\n * In the kernel circuits, we accumulate elements such as commitments and the nullifiers from all functions calls in a\n * transaction. Therefore, we always must have:\n * MAX_XXX_PER_TX ≥ MAX_XXX_PER_CALL\n *\n * For instance:\n * MAX_NEW_NOTE_HASHES_PER_TX ≥ MAX_NEW_NOTE_HASHES_PER_CALL\n * MAX_NEW_NULLIFIERS_PER_TX ≥ MAX_NEW_NULLIFIERS_PER_CALL\n *\n */\n\n// docs:start:constants\n// \"PER CALL\" CONSTANTS\nglobal MAX_NEW_NOTE_HASHES_PER_CALL: Field = 16;\nglobal MAX_NEW_NULLIFIERS_PER_CALL: Field = 16;\nglobal MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL: Field = 4;\nglobal MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL: Field = 4;\nglobal MAX_NEW_L2_TO_L1_MSGS_PER_CALL: Field = 2;\nglobal MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL: Field = 16;\nglobal MAX_PUBLIC_DATA_READS_PER_CALL: Field = 16;\nglobal MAX_NOTE_HASH_READ_REQUESTS_PER_CALL: Field = 32;\n\n// \"PER TRANSACTION\" CONSTANTS\nglobal MAX_NEW_NOTE_HASHES_PER_TX: Field = 64;\nglobal MAX_NEW_NULLIFIERS_PER_TX: Field = 64;\nglobal MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX: Field = 8;\nglobal MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX: Field = 8;\nglobal MAX_NEW_L2_TO_L1_MSGS_PER_TX: Field = 2;\nglobal MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: Field = 16;\nglobal MAX_PUBLIC_DATA_READS_PER_TX: Field = 16;\nglobal MAX_NEW_CONTRACTS_PER_TX: Field = 1;\nglobal MAX_OPTIONALLY_REVEALED_DATA_LENGTH_PER_TX: Field = 4;\nglobal MAX_NOTE_HASH_READ_REQUESTS_PER_TX: Field = 128;\nglobal NUM_ENCRYPTED_LOGS_HASHES_PER_TX: Field = 1;\nglobal NUM_UNENCRYPTED_LOGS_HASHES_PER_TX: Field = 1;\n// docs:end:constants\n\n// ROLLUP CONTRACT CONSTANTS - constants used only in l1-contracts\nglobal NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP: Field = 16;\n\n// TREES RELATED CONSTANTS\nglobal VK_TREE_HEIGHT: Field = 3;\nglobal FUNCTION_TREE_HEIGHT: Field = 5;\nglobal CONTRACT_TREE_HEIGHT: Field = 16;\nglobal NOTE_HASH_TREE_HEIGHT: Field = 32;\nglobal PUBLIC_DATA_TREE_HEIGHT: Field = 40;\nglobal NULLIFIER_TREE_HEIGHT: Field = 20;\nglobal L1_TO_L2_MSG_TREE_HEIGHT: Field = 16;\nglobal ROLLUP_VK_TREE_HEIGHT: Field = 8;\n\n// SUB-TREES RELATED CONSTANTS\nglobal CONTRACT_SUBTREE_HEIGHT: Field = 0;\nglobal CONTRACT_SUBTREE_SIBLING_PATH_LENGTH: Field = 16;\nglobal NOTE_HASH_SUBTREE_HEIGHT: Field = 6;\nglobal NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH: Field = 26;\nglobal NULLIFIER_SUBTREE_HEIGHT: Field = 6;\nglobal PUBLIC_DATA_SUBTREE_HEIGHT: Field = 4;\nglobal ARCHIVE_HEIGHT: Field = 16;\nglobal NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH: Field = 14;\nglobal PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH: Field = 36;\nglobal L1_TO_L2_MSG_SUBTREE_HEIGHT: Field = 4;\nglobal L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH: Field = 12;\n\n// MISC CONSTANTS\nglobal FUNCTION_SELECTOR_NUM_BYTES: Field = 4;\nglobal MAPPING_SLOT_PEDERSEN_SEPARATOR: Field = 4;\n// sha256 hash is stored in two fields to accommodate all 256-bits of the hash\nglobal NUM_FIELDS_PER_SHA256: Field = 2;\nglobal ARGS_HASH_CHUNK_LENGTH: u32 = 32;\nglobal ARGS_HASH_CHUNK_COUNT: u32 = 16;\n\n// NOIR CONSTANTS - constants used only in yarn-packages/noir-contracts\n// Some are defined here because Noir doesn't yet support globals referencing other globals yet.\n// Move these constants to a noir file once the issue bellow is resolved:\n// https://github.com/noir-lang/noir/issues/1734\nglobal L1_TO_L2_MESSAGE_LENGTH: Field = 8;\nglobal L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH: Field = 25;\nglobal MAX_NOTE_FIELDS_LENGTH: Field = 20;\n// GET_NOTE_ORACLE_RETURN_LENGT = MAX_NOTE_FIELDS_LENGTH + 1 + 2\n// The plus 1 is 1 extra field for nonce.\n// + 2 for EXTRA_DATA: [number_of_return_notes, contract_address]\nglobal GET_NOTE_ORACLE_RETURN_LENGTH: Field = 23;\nglobal MAX_NOTES_PER_PAGE: Field = 10;\n// VIEW_NOTE_ORACLE_RETURN_LENGTH = MAX_NOTES_PER_PAGE * (MAX_NOTE_FIELDS_LENGTH + 1) + 2;\nglobal VIEW_NOTE_ORACLE_RETURN_LENGTH: Field = 212;\nglobal CALL_CONTEXT_LENGTH: Field = 8;\nglobal BLOCK_HEADER_LENGTH: Field = 7;\nglobal FUNCTION_DATA_LENGTH: Field = 4;\nglobal CONTRACT_DEPLOYMENT_DATA_LENGTH: Field = 6;\n// Change this ONLY if you have changed the PrivateCircuitPublicInputs structure.\n// In other words, if the structure/size of the public inputs of a function call changes then we\n// should change this constant as well as the offsets in private_call_stack_item.nr\nglobal PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: Field = 189;\nglobal CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH: Field = 3;\nglobal CONTRACT_STORAGE_READ_LENGTH: Field = 2;\n// Change this ONLY if you have changed the PublicCircuitPublicInputs structure.\nglobal PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: Field = 190;\nglobal GET_NOTES_ORACLE_RETURN_LENGTH: Field = 674;\nglobal CALL_PRIVATE_FUNCTION_RETURN_SIZE: Field = 195;\nglobal PUBLIC_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH: Field = 87;\nglobal PRIVATE_CIRCUIT_PUBLIC_INPUTS_HASH_INPUT_LENGTH: Field = 177;\nglobal NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP: Field = 2048;\nglobal NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP: Field = 2048;\nglobal PUBLIC_DATA_WRITES_NUM_BYTES_PER_BASE_ROLLUP: Field = 1024;\nglobal CONTRACTS_NUM_BYTES_PER_BASE_ROLLUP: Field = 32;\nglobal CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP: Field = 64;\nglobal CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP_UNPADDED: Field = 52;\nglobal L2_TO_L1_MSGS_NUM_BYTES_PER_BASE_ROLLUP: Field = 64;\nglobal LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP: Field = 64;\n\n/**\n * Enumerate the hash_indices which are used for pedersen hashing.\n * We start from 1 to avoid the default generators. The generator indices are listed\n * based on the number of elements each index hashes. The following conditions must be met:\n *\n * +-----------+-------------------------------+----------------------+\n * | Hash size | Number of elements hashed (n) | Condition to use |\n * |-----------+-------------------------------+----------------------|\n * | LOW | n ≤ 8 | 0 < hash_index ≤ 32 |\n * | MID | 8 < n ≤ 16 | 32 < hash_index ≤ 40 |\n * | HIGH | 16 < n ≤ 48 | 40 < hash_index ≤ 48 |\n * +-----------+-------------------------------+----------------------+\n *\n * Note: When modifying, modify `GeneratorIndexPacker` in packer.hpp accordingly.\n */\n// Indices with size ≤ 8\nglobal GENERATOR_INDEX__COMMITMENT = 1;\nglobal GENERATOR_INDEX__NOTE_HASH_NONCE = 2;\nglobal GENERATOR_INDEX__UNIQUE_NOTE_HASH = 3;\nglobal GENERATOR_INDEX__SILOED_NOTE_HASH = 4;\nglobal GENERATOR_INDEX__NULLIFIER = 5;\nglobal GENERATOR_INDEX__INITIALIZATION_NULLIFIER = 6;\nglobal GENERATOR_INDEX__OUTER_NULLIFIER = 7;\nglobal GENERATOR_INDEX__PUBLIC_DATA_READ = 8;\nglobal GENERATOR_INDEX__PUBLIC_DATA_UPDATE_REQUEST = 9;\nglobal GENERATOR_INDEX__FUNCTION_DATA = 10;\nglobal GENERATOR_INDEX__FUNCTION_LEAF = 11;\nglobal GENERATOR_INDEX__CONTRACT_DEPLOYMENT_DATA = 12;\nglobal GENERATOR_INDEX__CONSTRUCTOR = 13;\nglobal GENERATOR_INDEX__CONSTRUCTOR_ARGS = 14;\nglobal GENERATOR_INDEX__CONTRACT_ADDRESS = 15;\nglobal GENERATOR_INDEX__CONTRACT_LEAF = 16;\nglobal GENERATOR_INDEX__CALL_CONTEXT = 17;\nglobal GENERATOR_INDEX__CALL_STACK_ITEM = 18;\nglobal GENERATOR_INDEX__CALL_STACK_ITEM_2 = 19;\nglobal GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET = 20;\nglobal GENERATOR_INDEX__L2_TO_L1_MSG = 21;\nglobal GENERATOR_INDEX__TX_CONTEXT = 22;\nglobal GENERATOR_INDEX__PUBLIC_LEAF_INDEX = 23;\nglobal GENERATOR_INDEX__PUBLIC_DATA_LEAF = 24;\nglobal GENERATOR_INDEX__SIGNED_TX_REQUEST = 25;\nglobal GENERATOR_INDEX__GLOBAL_VARIABLES = 26;\nglobal GENERATOR_INDEX__PARTIAL_ADDRESS = 27;\nglobal GENERATOR_INDEX__BLOCK_HASH = 28;\nglobal GENERATOR_INDEX__SIDE_EFFECT = 29;\n// Indices with size ≤ 16\nglobal GENERATOR_INDEX__TX_REQUEST = 33;\nglobal GENERATOR_INDEX__SIGNATURE_PAYLOAD = 34;\n// Indices with size ≤ 44\nglobal GENERATOR_INDEX__VK = 41;\nglobal GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS = 42;\nglobal GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS = 43;\nglobal GENERATOR_INDEX__FUNCTION_ARGS = 44;\n", - "path": "/home/santiago/Projects/aztec3-packages/noir-protocol-circuits/crates/types/src/constants.nr" - }, - "111": { - "source": "use crate::address::{AztecAddress, EthAddress};\nuse crate::mocked::VerificationKey;\nuse crate::abis::function_selector::FunctionSelector;\nuse crate::abis::function_leaf_preimage::FunctionLeafPreimage;\nuse crate::abis::new_contract_data::NewContractData as ContractLeafPreimage;\nuse crate::abis::function_data::FunctionData;\nuse crate::abis::side_effect::{SideEffect};\nuse crate::utils::uint256::U256;\nuse crate::utils::bounded_vec::BoundedVec;\nuse crate::constants::{\n ARGS_HASH_CHUNK_COUNT,\n ARGS_HASH_CHUNK_LENGTH,\n CONTRACT_TREE_HEIGHT, \n FUNCTION_TREE_HEIGHT, \n NOTE_HASH_TREE_HEIGHT,\n NUM_FIELDS_PER_SHA256,\n GENERATOR_INDEX__SILOED_NOTE_HASH,\n GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK,\n GENERATOR_INDEX__CONSTRUCTOR,\n GENERATOR_INDEX__PARTIAL_ADDRESS,\n GENERATOR_INDEX__CONTRACT_ADDRESS,\n GENERATOR_INDEX__NOTE_HASH_NONCE,\n GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n GENERATOR_INDEX__FUNCTION_ARGS,\n};\n\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n\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 + (sha256_hashed[15 - i] as Field) * v;\n low = low + (sha256_hashed[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n let hash_in_a_field = low + high * v;\n\n hash_in_a_field\n}\n\npub fn hash_args(args: [Field; N]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n for i in 0..ARGS_HASH_CHUNK_COUNT {\n let mut chunk_hash = 0;\n let start_chunk_index = i * ARGS_HASH_CHUNK_LENGTH;\n if start_chunk_index < (args.len() as u32) {\n let mut chunk_args = [0; ARGS_HASH_CHUNK_LENGTH];\n for j in 0..ARGS_HASH_CHUNK_LENGTH {\n let item_index = i * ARGS_HASH_CHUNK_LENGTH + j;\n if item_index < (args.len() as u32) {\n chunk_args[j] = args[item_index];\n }\n }\n chunk_hash = pedersen_hash(chunk_args, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n chunks_hashes[i] = chunk_hash;\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n// Checks that `value` is a member of a merkle tree with root `root` at position `index`\n// The witness being the `sibling_path`\npub fn assert_check_membership(value: Field, index: Field, sibling_path: [Field; N], root: Field) {\n let calculated_root = root_from_sibling_path(value, index, sibling_path);\n assert(calculated_root == root, \"membership check failed\");\n}\n\n// Calculate the Merkle tree root from the sibling path and leaf.\n//\n// The leaf is hashed with its sibling, and then the result is hashed\n// with the next sibling etc in the path. The last hash is the root.\n//\n// TODO(David/Someone): The cpp code is using a uint256, whereas its\n// TODO a bit simpler in Noir to just have a bit array.\n// TODO: I'd generally like to avoid u256 for algorithms like \n// this because it means we never even need to consider cases where \n// the index is greater than p.\npub fn root_from_sibling_path(leaf: Field, leaf_index: Field, sibling_path: [Field; N]) -> Field {\n let mut node = leaf;\n let indices = leaf_index.to_le_bits(N);\n\n for i in 0..N {\n let (hash_left, hash_right) = if indices[i] == 1 {\n (sibling_path[i], node)\n } else {\n (node, sibling_path[i])\n };\n node = merkle_hash(hash_left, hash_right);\n }\n node\n}\n\n// Calculate the function tree root from the sibling path and leaf preimage.\n//\n// TODO: The cpp code passes in components of the FunctionLeafPreimage and then \n// builds it up. We should build it up and then pass the leaf preimage as a parameter.\n// We can then choose to have a general method that takes in anything hashable\n// and deduplicate the logic in `contract_tree_root_from_siblings`\npub fn function_tree_root_from_siblings(\n selector: FunctionSelector,\n is_internal: bool,\n is_private: bool,\n vk_hash: Field,\n acir_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = FunctionLeafPreimage { selector, is_internal, is_private, vk_hash, acir_hash };\n\n let function_leaf = function_leaf_preimage.hash();\n\n let function_tree_root = root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path);\n\n function_tree_root\n}\n\n// Calculate the contract tree root from the sibling path and leaf preimage.\npub fn contract_tree_root_from_siblings(\n function_tree_root: Field,\n storage_contract_address: AztecAddress,\n portal_contract_address: EthAddress,\n contract_leaf_index: Field,\n contract_leaf_sibling_path: [Field; CONTRACT_TREE_HEIGHT]\n) -> Field {\n //TODO(Kev): if we use shorthand syntax here, we get an error as expected,\n // since variable name is `storage_contract_address` but the span is incorrect.\n let contract_leaf_preimage = ContractLeafPreimage { contract_address: storage_contract_address, portal_contract_address, function_tree_root };\n\n let contract_leaf = contract_leaf_preimage.hash();\n\n let computed_contract_tree_root = root_from_sibling_path(contract_leaf, contract_leaf_index, contract_leaf_sibling_path);\n\n computed_contract_tree_root\n}\n\npub fn read_request_root_from_siblings(\n read_request: Field,\n leaf_index: Field,\n sibling_path: [Field; NOTE_HASH_TREE_HEIGHT]\n) -> Field {\n root_from_sibling_path(read_request, leaf_index, sibling_path)\n}\n\npub fn silo_note_hash(address: AztecAddress, inner_commitment: Field) -> Field {\n pedersen_hash(\n [\n address.to_field(),\n inner_commitment\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_nullifier(address: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n address.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\nfn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\n// TODO CPP uses blake2s for this\npub fn compute_new_contract_address_hash(new_contract_address: AztecAddress) -> Field {\n dep::std::hash::pedersen_hash([new_contract_address.to_field()])\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n rollup_version_id: Field,\n portal_contract_address: EthAddress,\n chain_id: Field,\n content: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n unique_siloed_note_hashes[i] = SideEffect {\n value: compute_unique_siloed_note_hash(nonce, siloed_note_hash.value),\n counter: siloed_note_hash.counter\n };\n }\n }\n unique_siloed_note_hashes\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/noir-protocol-circuits/crates/types/src/hash.nr" - }, - "126": { - "source": "pub fn field_from_bytes(bytes: [u8; N], big_endian: bool) -> Field {\n assert(bytes.len() as u32 < 32, \"field_from_bytes: N must be less than 32\");\n let mut as_field = 0;\n let mut offset = 1;\n for i in 0..N {\n let mut index = i;\n if big_endian {\n index = N - i - 1;\n }\n as_field += (bytes[index] as Field) * offset;\n offset *= 256;\n }\n\n as_field\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/noir-protocol-circuits/crates/types/src/utils/field.nr" - }, - "150": { - "source": "use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n\n pub fn from_u32(value: u32) -> Self {\n Self {\n inner : value,\n }\n }\n\n pub fn from_field(value : Field) -> Self {\n Self {\n inner : value as u32,\n }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n\n pub fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/noir-protocol-circuits/crates/types/src/abis/function_selector.nr" - }, - "160": { - "source": "use crate::{\n constants::{\n GENERATOR_INDEX__CONTRACT_ADDRESS,\n GENERATOR_INDEX__PARTIAL_ADDRESS,\n },\n hash::pedersen_hash,\n utils,\n grumpkin_point::GrumpkinPoint,\n};\nuse dep::std::cmp::Eq;\nuse crate::traits::{Empty, ToField};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self {\n inner: 0\n }\n }\n\n pub fn from_field(field : Field) -> Self {\n Self {\n inner : field\n }\n }\n\n pub fn compute(pub_key: GrumpkinPoint, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n pedersen_hash(\n [pub_key.x, pub_key.y, partial_address.to_field()],\n GENERATOR_INDEX__CONTRACT_ADDRESS\n )\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n \n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs : Self, rhs : Self) -> Self{\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self {\n inner : result\n }\n }\n\n pub fn serialize(self: Self) -> [Field; 1] {\n [self.inner]\n }\n\n pub fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0]\n }\n }\n}\n\nstruct EthAddress{\n inner : Field\n}\n\nimpl Eq for EthAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for EthAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for EthAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl EthAddress{\n pub fn zero() -> Self {\n Self {\n inner: 0\n }\n }\n\n pub fn from_field(field : Field) -> Self {\n Self {\n inner : field\n }\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs : Self, rhs : Self) -> Self{\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self {\n inner : result\n }\n }\n\n pub fn serialize(self: Self) -> [Field; 1] {\n [self.inner]\n }\n\n pub fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0]\n }\n }\n}\n\n// Partial address\nstruct PartialAddress {\n inner : Field\n}\n\nimpl ToField for PartialAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl PartialAddress {\n pub fn from_field(field : Field) -> Self {\n Self {\n inner : field\n }\n }\n\n pub fn compute(contract_address_salt : Field, function_tree_root : Field, constructor_hash : Field) -> Self {\n PartialAddress::from_field(\n pedersen_hash([\n // TODO why the zeroes?\n 0,\n 0,\n contract_address_salt,\n function_tree_root,\n constructor_hash\n ], GENERATOR_INDEX__PARTIAL_ADDRESS)\n )\n }\n\n pub fn to_field(self) -> Field {\n self.inner\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/noir-protocol-circuits/crates/types/src/address.nr" - }, - "163": { - "source": "use crate::{\n constants::{\n CONTRACT_STORAGE_READ_LENGTH,\n GENERATOR_INDEX__PUBLIC_DATA_READ,\n },\n hash::pedersen_hash,\n};\nuse crate::traits::Empty;\n\nstruct StorageRead {\n storage_slot: Field,\n current_value: Field,\n}\n\nimpl Empty for StorageRead { \n fn empty() -> Self {\n Self {\n storage_slot: 0,\n current_value: 0,\n }\n }\n}\n\nimpl StorageRead {\n\n pub fn serialize(self) -> [Field; CONTRACT_STORAGE_READ_LENGTH] {\n [self.storage_slot, self.current_value]\n }\n\n pub fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PUBLIC_DATA_READ)\n }\n\n pub fn is_empty(self) -> bool {\n self.storage_slot == 0\n }\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/noir-protocol-circuits/crates/types/src/contrakt/storage_read.nr" - }, - "167": { - "source": "use dep::std::option::Option;\nuse dep::aztec::context::PrivateContext;\nuse dep::aztec::note::note_getter_options::{NoteGetterOptions, SortOrder};\nuse dep::aztec::oracle::get_public_key::get_public_key;\nuse dep::aztec::state_vars::set::Set;\nuse crate::{\n filter::filter_notes_min_sum,\n value_note::{ValueNote, VALUE_NOTE_LEN},\n};\nuse dep::aztec::protocol_types::address::AztecAddress;\n\n// Sort the note values (0th field) in descending order.\n// Pick the fewest notes whose sum is equal to or greater than `amount`.\npub fn create_note_getter_options_for_decreasing_balance(amount: Field) -> NoteGetterOptions {\n NoteGetterOptions::with_filter(filter_notes_min_sum, amount).sort(0, SortOrder.DESC)\n}\n\n// Creates a new note for the recipient.\n// Inserts it to the recipient's set of notes.\npub fn increment(balance: Set, amount: Field, recipient: AztecAddress) {\n let mut note = ValueNote::new(amount, recipient);\n // Insert the new note to the owner's set of notes and emit the log if value is non-zero.\n balance.insert(&mut note, amount != 0);\n}\n\n// Find some of the `owner`'s notes whose values add up to the `amount`.\n// Remove those notes.\n// If the value of the removed notes exceeds the requested `amount`, create a new note containing the excess value, so that exactly `amount` is removed.\n// Fail if the sum of the selected notes is less than the amount.\npub fn decrement(balance: Set, amount: Field, owner: AztecAddress) {\n let sum = decrement_by_at_most(balance, amount, owner);\n assert(sum == amount, \"Balance too low\");\n}\n\n// Similar to `decrement`, except that it doesn't fail if the decremented amount is less than max_amount.\n// The motivation behind this function is that there is an upper-bound on the number of notes a function may\n// read and nullify. The requested decrementation `amount` might be spread across too many of the `owner`'s\n// notes to 'fit' within this upper-bound, so we might have to remove an amount less than `amount`. A common\n// pattern is to repeatedly call this function across many function calls, until enough notes have been nullified to\n// equal `amount`.\n//\n// It returns the decremented amount, which should be less than or equal to max_amount.\npub fn decrement_by_at_most(\n balance: Set,\n max_amount: Field,\n owner: AztecAddress\n) -> Field {\n let options = create_note_getter_options_for_decreasing_balance(max_amount);\n let opt_notes = balance.get_notes(options);\n\n let mut decremented = 0;\n for i in 0..opt_notes.len() {\n if opt_notes[i].is_some() {\n decremented += destroy_note(balance, owner, opt_notes[i].unwrap_unchecked());\n }\n }\n\n // Add the change value back to the owner's balance.\n let mut change_value = 0;\n if decremented as u120 > max_amount as u120 {\n change_value = decremented - max_amount;\n decremented -= change_value;\n }\n increment(balance, change_value, owner);\n\n decremented\n}\n\n// Removes the note from the owner's set of notes.\n// Returns the value of the destroyed note.\npub fn destroy_note(\n balance: Set,\n owner: AztecAddress,\n note: ValueNote\n) -> Field {\n // Ensure the note is actually owned by the owner (to prevent user from generating a valid proof while\n // spending someone else's notes).\n assert(note.owner.eq(owner));\n\n balance.remove(note);\n\n note.value\n}\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/value-note/src/utils.nr" - }, - "169": { - "source": "use dep::aztec::{\n protocol_types::address::AztecAddress,\n note::{\n note_header::NoteHeader,\n note_interface::NoteInterface,\n utils::compute_note_hash_for_read_or_nullify,\n },\n oracle::{\n rand::rand,\n nullifier_key::get_nullifier_secret_key,\n get_public_key::get_public_key,\n },\n log::emit_encrypted_log,\n hash::pedersen_hash,\n context::PrivateContext,\n};\n\nglobal VALUE_NOTE_LEN: Field = 3; // 3 plus a header.\n\n// docs:start:value-note-def\nstruct ValueNote {\n value: Field,\n owner: AztecAddress,\n randomness: Field,\n header: NoteHeader,\n}\n// docs:end:value-note-def\n\nimpl ValueNote {\n pub fn new(value: Field, owner: AztecAddress) -> Self {\n let randomness = rand();\n let header = NoteHeader::empty();\n ValueNote {\n value,\n owner,\n randomness,\n header,\n }\n }\n\n pub fn serialize(self) -> [Field; VALUE_NOTE_LEN] {\n [self.value, self.owner.to_field(), self.randomness]\n }\n\n pub fn deserialize(serialized_note: [Field; VALUE_NOTE_LEN]) -> Self {\n ValueNote {\n value: serialized_note[0],\n owner: AztecAddress::from_field(serialized_note[1]),\n randomness: serialized_note[2],\n header: NoteHeader::empty(),\n }\n }\n\n pub fn compute_note_hash(self) -> Field {\n // TODO(#1205) Should use a non-zero generator index.\n pedersen_hash(self.serialize(),0)\n }\n\n // docs:start:nullifier\n\n pub fn compute_nullifier(self, context: &mut PrivateContext) -> Field {\n let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(ValueNoteMethods, self);\n let secret = context.request_nullifier_secret_key(self.owner);\n // TODO(#1205) Should use a non-zero generator index.\n pedersen_hash([\n note_hash_for_nullify,\n secret.low,\n secret.high,\n ],0)\n }\n\n // docs:end:nullifier\n\n pub fn compute_nullifier_without_context(self) -> Field {\n let note_hash_for_nullify = compute_note_hash_for_read_or_nullify(ValueNoteMethods, self);\n let secret = get_nullifier_secret_key(self.owner);\n // TODO(#1205) Should use a non-zero generator index.\n pedersen_hash([\n note_hash_for_nullify,\n secret.low,\n secret.high,\n ],0)\n }\n\n pub fn set_header(&mut self, header: NoteHeader) {\n self.header = header;\n }\n\n // Broadcasts the note as an encrypted log on L1.\n pub fn broadcast(self, context: &mut PrivateContext, slot: Field) {\n let encryption_pub_key = get_public_key(self.owner);\n emit_encrypted_log(\n context,\n (*context).this_address(),\n slot,\n encryption_pub_key,\n self.serialize(),\n );\n }\n}\n\nfn deserialize(serialized_note: [Field; VALUE_NOTE_LEN]) -> ValueNote {\n ValueNote::deserialize(serialized_note)\n}\n\nfn serialize(note: ValueNote) -> [Field; VALUE_NOTE_LEN] {\n note.serialize()\n}\n\nfn compute_note_hash(note: ValueNote) -> Field {\n note.compute_note_hash()\n}\n\nfn compute_nullifier(note: ValueNote, context: &mut PrivateContext) -> Field {\n note.compute_nullifier(context)\n}\n\nfn compute_nullifier_without_context(note: ValueNote) -> Field {\n note.compute_nullifier_without_context()\n}\n\nfn get_header(note: ValueNote) -> NoteHeader {\n note.header\n}\n\nfn set_header(note: &mut ValueNote, header: NoteHeader) {\n note.set_header(header)\n}\n\n// Broadcasts the note as an encrypted log on L1.\nfn broadcast(context: &mut PrivateContext, slot: Field, note: ValueNote) {\n note.broadcast(context, slot);\n}\n\nglobal ValueNoteMethods = NoteInterface {\n deserialize,\n serialize,\n compute_note_hash,\n compute_nullifier,\n compute_nullifier_without_context,\n get_header,\n set_header,\n broadcast,\n};\n", - "path": "/home/santiago/Projects/aztec3-packages/aztec-nr/value-note/src/value_note.nr" - } - } -} diff --git a/yarn-project/circuits.js/package.json b/yarn-project/circuits.js/package.json index 1384c153fc4..f6192beede0 100644 --- a/yarn-project/circuits.js/package.json +++ b/yarn-project/circuits.js/package.json @@ -21,7 +21,8 @@ "tsconfig": "./tsconfig.json" }, "scripts": { - "build": "yarn clean && tsc -b", + "build": "yarn clean && yarn generate && tsc -b", + "generate": "./scripts/copy-contracts.sh", "build:dev": "tsc -b --watch", "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src && run -T eslint ./src", diff --git a/yarn-project/circuits.js/scripts/copy-contracts.sh b/yarn-project/circuits.js/scripts/copy-contracts.sh new file mode 100755 index 00000000000..d64da5b967a --- /dev/null +++ b/yarn-project/circuits.js/scripts/copy-contracts.sh @@ -0,0 +1,5 @@ +#! /bin/bash +set -euo pipefail +mkdir -p ./fixtures + +cp "../../noir-projects/noir-contracts/target/benchmarking_contract-Benchmarking.json" ./fixtures/Benchmarking.test.json diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index af38c3081ca..a0af43b2763 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -11,6 +11,7 @@ export const MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL = 16; export const MAX_PUBLIC_DATA_READS_PER_CALL = 16; export const MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 32; export const MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 2; +export const MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 2; export const MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL = 1; export const MAX_NEW_NOTE_HASHES_PER_TX = 64; export const MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX = 8; @@ -29,24 +30,26 @@ export const MAX_PUBLIC_DATA_READS_PER_TX = 32; export const MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX = 16; export const MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX = 16; export const MAX_NEW_L2_TO_L1_MSGS_PER_TX = 2; -export const MAX_NEW_CONTRACTS_PER_TX = 1; export const MAX_NOTE_HASH_READ_REQUESTS_PER_TX = 128; export const MAX_NULLIFIER_READ_REQUESTS_PER_TX = 8; +export const MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX = 8; export const MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX = 4; export const NUM_ENCRYPTED_LOGS_HASHES_PER_TX = 1; export const NUM_UNENCRYPTED_LOGS_HASHES_PER_TX = 1; export const NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP = 16; export const VK_TREE_HEIGHT = 3; export const FUNCTION_TREE_HEIGHT = 5; -export const CONTRACT_TREE_HEIGHT = 16; export const NOTE_HASH_TREE_HEIGHT = 32; export const PUBLIC_DATA_TREE_HEIGHT = 40; export const NULLIFIER_TREE_HEIGHT = 20; export const L1_TO_L2_MSG_TREE_HEIGHT = 16; export const ROLLUP_VK_TREE_HEIGHT = 8; export const ARTIFACT_FUNCTION_TREE_MAX_HEIGHT = 5; -export const CONTRACT_SUBTREE_HEIGHT = 0; -export const CONTRACT_SUBTREE_SIBLING_PATH_LENGTH = 16; +export const NULLIFIER_TREE_ID = 0; +export const NOTE_HASH_TREE_ID = 1; +export const PUBLIC_DATA_TREE_ID = 2; +export const L1_TO_L2_MESSAGE_TREE_ID = 3; +export const ARCHIVE_TREE_ID = 4; export const NOTE_HASH_SUBTREE_HEIGHT = 6; export const NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH = 26; export const NULLIFIER_SUBTREE_HEIGHT = 6; @@ -62,7 +65,7 @@ export const ARGS_HASH_CHUNK_LENGTH = 32; export const ARGS_HASH_CHUNK_COUNT = 32; export const INITIAL_L2_BLOCK_NUM = 1; export const BLOB_SIZE_IN_BYTES = 126976; -export const MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 9000; +export const MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 15000; export const MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS = 500; export const MAX_PACKED_BYTECODE_SIZE_PER_UNCONSTRAINED_FUNCTION_IN_FIELDS = 500; export const REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE = @@ -80,9 +83,8 @@ export const GET_NOTE_ORACLE_RETURN_LENGTH = 23; export const MAX_NOTES_PER_PAGE = 10; export const VIEW_NOTE_ORACLE_RETURN_LENGTH = 212; export const AZTEC_ADDRESS_LENGTH = 1; -export const CALL_CONTEXT_LENGTH = 8; +export const CALL_CONTEXT_LENGTH = 7; export const CONTENT_COMMITMENT_LENGTH = 7; -export const CONTRACT_DEPLOYMENT_DATA_LENGTH = 6; export const CONTRACT_INSTANCE_LENGTH = 6; export const CONTRACT_STORAGE_READ_LENGTH = 2; export const CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 2; @@ -90,19 +92,19 @@ export const ETH_ADDRESS_LENGTH = 1; export const FUNCTION_DATA_LENGTH = 4; export const FUNCTION_LEAF_PREIMAGE_LENGTH = 5; export const GLOBAL_VARIABLES_LENGTH = 6; -export const HEADER_LENGTH = 25; +export const HEADER_LENGTH = 23; export const L1_TO_L2_MESSAGE_LENGTH = 8; export const L2_TO_L1_MESSAGE_LENGTH = 2; -export const NEW_CONTRACT_DATA_LENGTH = 3; export const NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 4; export const NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 5; -export const PARTIAL_STATE_REFERENCE_LENGTH = 8; -export const PRIVATE_CALL_STACK_ITEM_LENGTH = 223; -export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 218; -export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 199; -export const STATE_REFERENCE_LENGTH = 10; -export const TX_CONTEXT_DATA_LENGTH = 11; -export const TX_REQUEST_LENGTH = 17; +export const PARTIAL_STATE_REFERENCE_LENGTH = 6; +export const PRIVATE_CALL_STACK_ITEM_LENGTH = 214; +export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 209; +export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 200; +export const STATE_REFERENCE_LENGTH = 8; +export const TX_CONTEXT_DATA_LENGTH = 4; +export const TX_REQUEST_LENGTH = 10; +export const ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 13; export const GET_NOTES_ORACLE_RETURN_LENGTH = 674; export const NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048; export const NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; diff --git a/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap b/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap index 4b5fae56077..4b47ded0b49 100644 --- a/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap +++ b/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap @@ -6,131 +6,8 @@ exports[`ContractAddress Public key hash matches Noir 1`] = `"0x1923a6246e305720 exports[`ContractAddress computeContractAddressFromInstance 1`] = `"0x2fd71a4f0742364f194dd16d0ae32d2f47845ddc7f5d328f37d4148b565c4123"`; -exports[`ContractAddress computeInitializationHash 1`] = ` -Fr { - "asBigInt": 11287307308183188516369033835241775664908452274022428157981236923904607656063n, - "asBuffer": { - "data": [ - 24, - 244, - 99, - 184, - 236, - 16, - 42, - 8, - 156, - 101, - 39, - 106, - 125, - 199, - 236, - 87, - 43, - 9, - 28, - 163, - 148, - 181, - 224, - 108, - 3, - 191, - 211, - 120, - 203, - 68, - 24, - 127, - ], - "type": "Buffer", - }, -} -`; +exports[`ContractAddress computeInitializationHash 1`] = `Fr<0x18f463b8ec102a089c65276a7dc7ec572b091ca394b5e06c03bfd378cb44187f>`; -exports[`ContractAddress computePartialAddress 1`] = ` -Fr { - "asBigInt": 11370807533904788559065519582196668367978392224620203970943957018221100220632n, - "asBuffer": { - "data": [ - 25, - 35, - 166, - 36, - 110, - 48, - 87, - 32, - 182, - 170, - 247, - 81, - 253, - 224, - 52, - 38, - 19, - 233, - 60, - 130, - 228, - 85, - 195, - 131, - 30, - 40, - 55, - 92, - 22, - 221, - 64, - 216, - ], - "type": "Buffer", - }, -} -`; +exports[`ContractAddress computePartialAddress 1`] = `Fr<0x1923a6246e305720b6aaf751fde0342613e93c82e455c3831e28375c16dd40d8>`; -exports[`ContractAddress computeSaltedInitializationHash 1`] = ` -Fr { - "asBigInt": 11725758444245911667025964940014811412794639055001970719147766917493953867026n, - "asBuffer": { - "data": [ - 25, - 236, - 139, - 73, - 109, - 192, - 136, - 17, - 189, - 50, - 237, - 56, - 134, - 9, - 56, - 184, - 97, - 39, - 147, - 221, - 79, - 57, - 195, - 179, - 116, - 155, - 140, - 213, - 210, - 243, - 45, - 18, - ], - "type": "Buffer", - }, -} -`; +exports[`ContractAddress computeSaltedInitializationHash 1`] = `Fr<0x19ec8b496dc08811bd32ed38860938b8612793dd4f39c3b3749b8cd5d2f32d12>`; diff --git a/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap b/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap index 72fa7b91f5d..0c8262f95ee 100644 --- a/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap +++ b/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap @@ -9,18 +9,18 @@ exports[`ContractClass creates a contract class from a contract compilation arti "selector": { "value": 2381782501 }, - "bytecode": "0x1f8b08000000000000ffed9d097c1d55f5c7dfcb4bd2bcbcecfbd2242f4dd3360d69f3d28d5ad4b8518a0b1444aaa2a55bb0d8a6d8262c0a8a8ab8af7545140515dc57dc1744511064535054dc4041f6b52c65f99f3bef1ef2cbcdf425f3e7de97137ae7f339c99d7367eef99e73efdcb96fe6ceccb5b1582c1ecb2e0992fad8c485f307f5fffea7b7642c96d5ef92333e43380b66086762867016ce10cea219c2593c433867cd10ce9219c2999c219ca5338433354338cb660867f90ce1ac98219c953384b36a867056cf10ce9a19c2593b4338eb2c72b60027ffb66bd0ff1bf5ff26fdbf59ffe77d5af5ffd9fa7f9bf6b550afb7937490a4493a751e07660e4917c95c926e927924f3491690f4902c24e9253980a48f6411c962bdbffa813840b2846429c93292e5242b480e245949f22c92552407913c9be43924cfd5717b1ec9f3495e40f2429217911c4cb29ae4109235248792bc98e425242f257919c961248793acd5bea4b52f47901c49f27292a3485e417234c93a925792bc8ae4d524c790bc86e4b524eb498e25d940b2916413c966922d244324c791bc8e642bc9f124af27d946b29d64986407c909246f3062be936417c908c9a8c17922c9492427939c42f2469237919c4a721ac99b49de42723ac95b49de46f276923348de417226c93b49de45f26e92f790bc97e47d24ef27f900c907493e44f261928f90ec26f928c9c762e3ebffe3249f20f924c9a748ce22f934c9d9249f21f92cc939249f23f93cc9b924e7917c81e48b245f22399fe402922f937c85e4ab245f23f93ac93748be49f22d926f937c87e4bb24df23b990e4fb243f20f921c98f487e4cf213929f92fc8ce4e724bf20b988e497241793fc8ae4d72497685f0ab42fbf21f9ada1bb94e4329dfe9dfe7fb9fe7f85feff7bfdff4afdff2afdff6afdff1afdff5ac55f9d4dab31b3790d46e9f8988d838e8fdf02d0f1b19c001d1fd785a0e363bc08747cbc17838e8ffd59a06bd3e912d0b5439aff77e87429e8d23a9d025da74e97816e8e4e9783ae4ba72b403757a72b41d7add355a09ba7d3d5a09bafd335a05ba0d3b5a0ebd1e93afd9fe3a39641fdbfff692eaa4ccbe7917ec5ce6da31efce1b6d1003a6e1b8da0e3b6d1043af6bd1974dc365a40c76da31574dc3666838edb461be8b86d609be2b6d1013a6e1b69d071dbe8041db78d39a0e3b6d1053a6e1b7341c76da31b74dc36e6818edbc67cd071cc17808e63ce6d4ac5f810c8e7058f69bc3ecb3acec7633a0165b28ef3f198e67c3ca6391f8f69cce7ff9c8fc734e7e331cdf978fc723e1eab5caf785cf23e780c72bd623be672b0cd72bd62fbe4b2b12d72bd625b647bd816b95eb12d3203b645aed734e8980bdb221f4bd8169915fbb762286b50ffef7f7a4b06fb645ee2c6fa20a4d3fa7f31f86089a53f052c9d60a7cbae9d25782e998acf5dc0d26dd9673c5f4d85a51b58e6d96509aec9ceb75b6650a71c6bec43d9ce1cf06781657fe26087cbe575b695021df6e70b42f87aecf20dc4c10e97cbeb3dc0c7ba79ee62d58f7d1397adce131bc066dab24de53f1fe77cdf8219d85602b639b27a8c6b8bd695423e8e2d797fec53bb0d9d8b63280e76b85c5e9f077cdca774e7976f60aa7c730d3e077d5f10abb9064b985dcbc75d681d711bea716cd7ec8fba0cbbf8bb84975ce783f9c06bbbff54652eb45b6670ccf702f320d8c0f3ec010e62df0bf18c830dd627207d466c6c3900d269fd9f99d5b1d213b21da6e719fba420bfc7b1cf0b816310d6d996ea4b4f0106cb6d3ea8ef1e8381d7bb40bf30245e780ee4fc06d0717fdf0dba394619f85b1dfb55cbed3a93cb4fac77d6e16fc285217cbd76f90672b5855ee063dd02c7b1dad7b867e17e6cd7f6b187e5abe39c8f13b69380fc8e82b1edce0626cbbfbd06a2fedec17342da2a4ba63feaefc034b058feed1b9c6b3bec96d9efba4dc5207ecc8e7d089edb5c1c531d463df13af27956cfea593dab67f5ac9ed5b37ad6fd9b55b1cc3538f11ed85c017c61f7c06cff36c0fb8e5cb6faed7727d89c63d56626b81664fe9e33ef7d26609b2781eb5e9d2e857cbc9fd469e8ecff5eccd61fdbe172793d0d7cec0bd69feddf8bf1d8f8dfae83cf68bb039bec1f03997e35cf00e71099c75d5affc7b951ac536d724ec198bf768f95ec7d79bc3eaa965cd726e6388b7df61e6e97111bfbf531d08ff3160b62e3fb870eb06be99a468613786d94e3c71c61d7ca4a754594dbe5798a6b2af7855ddd9bc16bd8e9d8d83543b685d7ab795bf39e4e3a36f13e09de5ba9d1f153c7d085f1b1fd2cb7db81a8d7f7b06ddbadd3817e9ce7381516ac67cbe77e27f7f51cdcb308ae35e6baf786f7d1b0fd4dc77d34cfea593dab67f5ac9ed5b37a56cfea593dab67f5ac9ed5b37a56cfea593dab679d49ac389f3eadffef6bbefa74f1b10eef0fd9beb68dcfe372d9eadec57970ef226dd5e6c0b867e3b8fc66a32ef0d9b81be19ecaf93a5d0af961731db0fe5cdcc3dad75c07b6550abe60fdd9bedf81f715b9dc67aeddecbd72bbc7c0c053f7cab93d99c71d3eab633ed386f7f9707e04cedf481bbae9aa0f3c66d2a0e334ce5fb11be38c8b7b68c17b750f807a60dff09937cebf08fa908be3637563f6172aff9a907c5ee2c6fa20a4f13efb22bbbe067de662287f106ca0dd7ebb763368371e1bffce23d627207d3504085f1ac6f16566d5eefa42b6c37487b14f0af2fb1cfbbc083806619d6da9767209b4a96be07c69fb7c83fe625c9a202e9c9f86b8d83ede948be6f88e19f039bbb906278eabb00fec73c0b7af71551ff099733c70be20f627385f306d9575fc18c89c0f9406bb96ce13e3e603e1fc8bced8c4770c24609b9b74bb56f381cc714f1af66d8632f33187c93c37e31ca65b81d9cf610a9fc364cecdc5394cf740bfd65a904def6bbc2de5f9631cc7a0df3dfbf01bdfc1e0a29f64ae228303c726bccda3d05ed5827dec3cfd1fc770e66f45fbe38d8160bcb6d86a99d9f3189e3fd33a8de308ce8f178c6d97d0e924f8dc09e5d484e4f3926bbcb608e23760d7d7e0585d02e50f820db4bbd4aedd0cdae5f11adb607d02d2d50563f1583a967c2abeccacda5d26643b4c1f60ec9382fc8c639f07806310d6d9966a27c5d0a6b8cdb81887a0bf189766880be7e3b5b139c6f6aa3de3fb6599d7f67189637a2ed71ce3878dbdf1fc607f8c34f19984746ce27522bc7e857d025ebf72f17c09cf99c7e74be6388cc5fff75d76f8cc0d1feaaee6f47746e09b037cbc5f02f8e63ae08bf2ccc15ce0e3fdf0dd92f31cf07547e09b077cbc5f11f0d97e5f12bed76e2a7c61efa02b86ffb6c78838169d0a1ff6bbbcdf2ce0b37dcd5ff1f546e0c3fb00bc5f09f059bebe14f0f545e0c36b32bc5f12f86c5f9351652f8ec0d70f7cbc5f29f0591eef057c99087c3846ca409af96c8f9114df92087c4b8189f72b03bee50ef89645e05b0e7cbc5f39f01de8806f4504be03818ff7ab00be6739e05b1981ef59c0c7fb5502df410ef85645e03b08f878bf2ae07b8e03be6747e07b0ef0f17ed5c037e880efb911f806818ff7ab01bee73be07b5e04bee7031fef570b7c2f74c0f782087c2f043ede0fdf877fb003be1745e03b18f8783f3cff1ee2806f7504be43808ff76b01be43edf205cf43ae89c07728b0bcd42ecb52c5f2e2082c2f059697d865099e877c99dd32836b8387592e53957138c484e3c7ec29c83f0ce275b8e578c5c12697cbebc8e759f76f56c5b2c6e04cc2766b04f0b1ee250e5992068b5a72f575617c589747d8e50bce0b6b23f01d012c47596559125c373c3202cb51c0f272ab2cd9f3c22bec9619f4e147033ffbca7652908f757eb465dfe26093cbe575e4f3ac9ed5b37a56cfea593dab67f5ac9ed5b37a56cfea593dab67f5ac9ed5b37a56cfea593dab67f5ac9ed5b37a56cfea593dab7d56c5b2d6e04cc2766b05f0b1eee50e5992068b5a72cd1309e3c3ba7ca55dbe604ecdba087caf049663acb264bf3df1aa082cc700cbabadb264e7d4bcc66e99c19c9ad7023ffbca7652908f75fe5acbbec5c12697cbebc8e7593dab67f5ac9ed5b37a56cfea593dab67f5ac9ed5b37a56cfea593dab67f5ac338555b1ac333893b0dd3a017cac7bb54396a4c1a2965cd7d9c3f8b02e8fb5cb17dc93581f81ef5860d964972578ffc386082c9b8065a35d96e09ec466bb6506f724b6003ffbca7652908f75bec5b26f71b0c9e5f23af279d6fd9b55b1ac373893b0dd7a017cacdbe8902569b0a82557bf14c68775799c5dbea00f1f8ac0771cb01c6f95257b5ff97511588e0796ad5659b27df8ebed9619f4e1db809f7d653b29c8c73adf66d9b738d8e472797d9b3bbb81ffdb27f17f7b08c7f63cfa8f7c53653d6c06b1fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab84e9d55b10c199c49d86e48001febb63a64491a2c6ac975ed3e8c0fdbdd0ebb7cc17d8ee1087c3b8065a75596ec3ba94f88c0b21358de6095257b9f6397dd3283ebfc23c0cfbeb29d14e4639d8f58f62d0e36b95c5e47be6722ebb619c4eadb801b56df063cab6f039ed5b701cfeadb8067f56dc0b3fa36e0597d1bf0acbe0d7856df063cab6f039ed5b701cfeadb8067f56dc0b3fa36e059a7bb0d289661833309db0d0be063dd1b1cb2240d16b5e49a2712c687edee44bb7cc19c9ad1087c2702cb290e584e8ac0720ab09c6c97259853f346bb65f6ab32de04fcec2bdb49413ed6f99b2cfb16079b5c2eaf23df4c61552ca3066712b61b15c0c7ba931db2240d16b5e43a7ec2f8b02e4fb3cb171cdfa746e03b0d584e77c0f2e6082ca703cb5becb2047dcd5bed9619f4356f037ef695eda4201febfc6d967d8b834d2e97d7916fa6b02a96530dce246c77aa003ed6bdc5214bd260514baee3278c0febf20c077c6f8fc07706f0bd3d84ef4c077cef88c07726f0f17ea5c0f72e077cef8cc0f72ee07b27a499ef3d0ef8de1d81ef3dc0c4fb9501dffb1cf0bd3702dffb808ff72b07be0f38e07b7f04be0f001fef57017c1f72c0f7c1087c1f023edeaf12f83ee280efc311f83e027cbc5f15f07dd401dfee087c1f053ede0ffbbf8f3be0fb5804be8f03dfc742f83ee980ef1311f83e097c9f08e13bcb01dfa722f09d057c9f0ae13bdb01dfa723f09d0d7cbc1f5ec3faac03becf44e0fb2cb09c6397a53f052ce7809dcf3bf0f973b1a9fbccf653b01ff29de780efdc087ce701dfb9217c5f74c0f785087c5f043ede0fdbf4f90ef8be1481ef7ce0e3fdb04ff8b203be0b22f07d19f82e08e1fbaa03beaf44e0fb2af07d2584efeb0ef8be1681efebc0f7b510be6f3ae0fb4604be6f02df3742f8beed80ef5b11f8be0d7cdf0ae1fbae03beef44e0fb2ef07d2784ef42077cdf8bc07721f07d2f84ef070ef8be1f81ef07c0f7fd10be1f39e0fb6104be1f01df0f43f87ee280efc711f87e027c3f0ee1fb9903be9f46e0fb19f0fd3484ef170ef87e1e81ef17c0f7f310be5f3ae0bb2802df2f81efa210be5f39e0bb3802dfaf80efe210be4b1cf0fd3a02df25c0c7fbe1f8efb70ef87e1381efb7c0c7fb61fc2eb3cb17dc73b93402df65c072855d96e05b03bf8bc07205b05c6e9725b8fff37bbb6506f77fae047ef695eda4201febfc4acbbec5c12697cbebc8e759f76f56c572a9c19984ed2e15c0c7bacb1db2240d16b5e4ea97c2f8b02eafb6cb17f4e15745e0bb1a58fe60956569f00e9e6b22b0fc0158aeb5ca92edc3ff68b7cca00fbf0ef8d957b693827cacf3eb2cfb16079b5c2eaf23df5459b7cd20561f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571fd7a9b32a96ab0cce246c7795003ed65deb902569b0a825d73ce7303e6c777fb2cb17cc09bf3e02df9f80e52f5659068239e17f8ec0f21760b9c12a4b764ef85fed9619cc09ff1bf0b3af6c2705f958e77fb3ec5b1c6c72b9bc8e7c5365dd3683587d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c9f9971552cd71b9c49d8ee7a017cacbbc1214bd260514baeebec617cd8eefe6e972fb827716304bebf03cbbfacb22c09ee49fc2302cbbf80e59f5659b2f724fe6db7cce09ec44dc0cfbeb29d14e4639ddf64d9b738d8e472791df99e89acdb6610ab6f036e587d1bf0acbe0d7856df063cab6f039ed5b701cfeadb8067f56dc0b3fa36e0597d1bf0acbe0d7856df063cab6f039ed5b701cfeadb80679dee36a0586e343893b0dd8d02f858f74f872c4983452db9e68984f161bbfb8f5dbe604ecdcd11f8fe032cb7da6509bedff7df082cb702cb2d7659823935ffb35b6630a7e636e0675fd94e0af2b1ce6fb3ec5b1c6c72b9bc8e7c9e75ff66552c371b9c49d8ee66017cacbbc5214bd260514bae7e298c0febf20ebb7c411f7e7b04be3b80e56ebb2c411f7e670496bb81e52ebb2c411f7e8fdd32833efc5ee0675fd94e0af2b1ceefb5ec5b1c6c72b9bc8e7c9e75ff66552cb71b9c49d8ee76017cacbbcb214bd260514bae7e298c0febf27ebb7c411f7e5f04befb81658f03960722b0ec019607edb2047df84376cb0cfaf087819f7d653b29c8c73a7fd8b26f71b0c9e5f23af2cd1456c5729fc19984edee13c0c7ba071db2240d16b5e43a7ec2f8b02e1f75c0f74804be4781ef9110bec71cf0ed8dc0f718f0ed0de17bc201dfe311f89e00bec743f878679b7c4fc6a6cec79929d80ff90a1cf0c5e353e72b003ede0ff90a1df02522f015025f2284afd8015f5104be62e02b0ae14bdae50bc60fb322f0b17dc552623956aacc52bb65f6ab32539663a6ca28832071fc4aa1ee383f05f12ab31caf38d8e472791df9a6ca5a1f9b5e56077607ca62d971cd2cc316df7341a6729d2e043d1f7b6ab542eb8af43a6f7f8ede2601dbac4bea32758c79e98218573888312e8390ae80fae6a54910cb6e412cad82584605b1ac17c4b24610cb0a412c6d8258ea05b1f40a62490862e910c4d22d8825238865b6209661412ca571392ced82e2b24e10cb4a412c4b04b1340862e913c4325f104bb320964e412c438258d60a62592d88a55110cb2a412ccb04b12c16c4d22388253ecd2cc9d8c46be049c82f85ed0a8c7dd5b5c10f568fe557697d019453ad758990b2aba0ec4a9dae8e4fdc176354e52046686710d6d956293054c7a79fa54710cb62412ccb04b1ac12c4d2288865b52096b582588604b1740a626916c4325f104b9f209606412c4b04b1ac14c4b24e104bbb20161edf4a6019161497d98258328258ba05b1740862490862e915c4522f88a54d10cb0a412c6b04b1ac17c4322a88a55510cb6e412c4d8258baf2c4c2d70ab9dc4a83653aedd6d8b51b3c13540b76f9da690dc49dedd70247bd5d8e60ee3472a8c5581d777db91e58ea2cd7852ab3c1729c55998d9663a6ca68822071fc983d05f98d10af26076db7c168bbbc8e7c5365c5b96ed3c1eaaafe9b2dd73fcfc7e658361b31c578b7e87421e86bc0dfd996fd55c5b5ea32798e3733b0ad046cf38ad2ecff726dbf15d8b9ffc1791e1d96db858a635b84fea70362d7eea0ff493be8e73bc121f6350dc71fe7b7826f9d0e8ebfb471fcf17a27b0f08273fcd30e58701984743a84a54910cb6e412cd85ea69d45505c4605b1ac17c4d224a8bdac111497158258da04b1d40b62e915c49210c4d22188a55b104b4610cb6c412cc38258da05b1ac13c4b25210cb12412c7d8258e60b626916c4d22988654810cb5a412cab05b1340a6259258865992096c582587a04b1c4a799655f73fc39bf09b6e36b7c6da09ba3d3eda02b08b1c1bf773a4157a8755c86bad67c56f5c4b231462eae69a29d4158675b38c77f4e7cfa597a04b12c16c4b24c10cb2a412c8d8258560b62592b886548104ba7209666412cf305b1f4096259228865a52096758258da05b10c0b62992d88252388a55b104b8720968420965e412cf58258da04b1ac10c4b246100b5f5790c0b25e505c4605b1b44a6211d45e760b8a4b932096ae1016cbd73407f03a242fc66ae8754ec5d26d9725f86e545704966e60996bb98e5499f3ec9619cc7b9e6fb94c55c6020812c78fd953903f1fe2b5c0419b9e171f5f4fbc8e7c9e75ff66c5b9d5cc9984ed3a05f0b16e2eb0d8ee0b94cf3c1ee0b2d5fd9b8da9319b96e7f52f55c561ff3d080c6c2b01db9c5935c635a4b94a211fef3db587d45f9b83fa6b37ea8fd7dbe0bcc9beb4034bbb03960e8345925ddbb1c73ae6c5581d776e6e0316dbcfd3a4806536d86971e0736b049f5b80c5f2f34d9914b034831dcbcf8405fd125fc36b827ee9d494b3fa0cfaa536a35f62067c3e8ab719867ee974e897da428e8356cbf18903935ad260b715fac3d690f669fb993765a72542fbc47663f799be4cd06e9a22b034008be56741330e9ec9ed77f06ced84e78d9f7ae613c6229c5f07f1aa75704ea937ce29bc8e7c9ed5b37a56cfea593dab67f5ac9e75ff66552cfcfb03e735f3762d02f85887ef7cb1fddb20785f466c7c3da9dfa6d7c16f66bbbfd333c1ef50fc3d970606b695806d8ea81ce3ba017e33371b7595845861fd3538a8bf46a3fe789d6de17d6dacbf46072c4d06cb33d7eec026fbc740a69fdfbfd36cf457669d2adb96dfdb155ca7ab8338aac5581d77eda1c661bfa4caacb6dcbfa832aac021f6b51afa39cec7f703b87c371d976bbe9b0e9fc52900966a072cb80c42ba3a8465b7209651412cad8258d60b62592388252388a55e104bb720964a412c49412c09412c3806996e96d982e2d22e886589209606412cf305b15409626916c4522a88a55010cb902096b58258960962e911c4522d88252588a548104baba0b15493a0b8ac10c4d22688a557104b8d20960e412c6582588a05b10c0b6259278865a520963e412cb582583a05b1940b6299258865b5209646412cab04b12c16c4522788a54b104b85209612412c2d8258e2d3ccb2aff733727e1d6c677eeb0bdfc588e5f13d0ede5efd4e3fb77a62d905b1896563399cc618553a8811da198475b685ef67ac8e4f3f4b8b209612412c158258ba04b1d40962592c886595209646412cab05b1cc12c4522e88a553104bad20963e412c2b05b1ac13c4322c88a558104b9920960e412c3582587a05b1b40962592188a549100bdf1796c05224282e29412cd582587a04b12c13c4b25610cb90209642412ca582589a05b1540962992f88a54110cb12412ced8258660b62691034964a088a4b52104ba520966e412cf58258328258d60862592f88a55510cba82096dd8258cc7bdf98afc6e57cbee27bdb09c83f54df4c50fff6f58cb80bbf70198c4de4ded733e2d3cd322a88a55510cb7a412c6b04b16404b1740b62a914c49214c49210c4d2e0f8dc168565b6a0b8b40b62592288a54110cb7c412c5582589a05b1940a622914c432248865ad20966582587a04b1540b624909622912c4d22a682cd524282e2b04b1b40962e915c4522388a543104b99209662412cc38258d60962592988a54f104bad20964e412ce58258660962592d88a55110cb2a412c8b05b1d40962e912c4522188a544104b8b2096f834b3ecebb96cce4f80ae42ebf07b7be53add00ba82101b5c4e05e8f89a1c97a17ecf5f503d91a10018ca42b8787fb4c776cae213f7751d73b43308eb784f9f19ca1c5f37980a4b8b209612412c158258ba04b1d40962592c886595209646412cab05b1cc12c4522e88a553104bad20963e412c2b05b1ac13c4322c88a558104b9920960e412c3582587a05b1b40962592188a549100bfff696c05224282e29412cd582587a04b12c13c4b25610cb90209642412ca582589a05b1540962992f88a54110cb12412ced8258660b62691034964a088a4b52104ba520966e412c19412c6b04b1ac17c4d22a88655410cb6e412c05064b29e4f335abe0f7a5d67582ae54ebba4097d4ba6ed09568dd7cd0cdd2ba1ed0156b5d2fe88ab4ae0f74855ab7187409adcb80ae40eb96802eae75cb40c737a35780ee499d5e09ba27747a15e81ed7e9d5a07b4ca7b95f50e793470d9daaf347747a50ffef7f7a4b50e76c87cbe5f547806faf4e3f0a3a4eaf05e6870d9d627ec801f3c30633af3f047cccff30e838bd0e98f7183ac5fca003e63d0633af3f087cccbf07749c5e0fcc0f183ac57cbf03e6070c665ebf1ff898ff01d0717a0898ef33748af95e07ccf719ccbc7e2ff031ff7da0e3f43030df63e814f3dd0e98ef319879fd6ee063fe7b40c7e95160becbd029e63b1d30df6530f3fa9dc0c7fc77818ed3bb1df3ed35f8f61a7caeec3e62d87d244f761f32ec3e9427bb0f1a761fcc93ddfb0dbbf7e7c9eebd86dd7bf364f76ec3eedd79b2bbbfb5e7e9ea37f6b7f63c5dfdc6741d47fe7c941fbbfe7c941fbb53398e6eb76b772009e5f31237d607217d3bb0dc613906aaccdbec96d9afcafc9fe5325519b7424c387ecc9e82fcff41bc6eb51caf38d8e472791df9660a6b1274f81c05e7a740778bd69582eebf5c0ee8fea37525a0bb59eb6681ee26f61d74ffd6ba22d0fd4beb1e07e67feaf463a0fb874eef05dddf75fa51d0dda8d38f80ee6f3afd30e8feaad30f81ee2f3abd077437e8f483a0fbb34e3f00ba3fe9f4fda0bb5ea7ef03dd753a7d2fe8fea8d3f780ee0f3a7d37e8aed5e93b41778d4edf01baab75fa7fa0bb4aa70b21f6576a5d0274bfd7ba02d05da17571d05d1e63e598ee775af524d8bd4ca79f00dda53a7d17e8f89aed6da0e3fb67d89e792ec32da0e3394bff051dcfd9fc0fe8789ef8cda0e367536e021ddf2bfb37e878dec2bf40c7f393fe093a9e9ff90fd095ebf4df41c7cfa1dc083abe2ff637d0f1bc80bf828ee722fd05743cfff106d0f19ceb3f838e9ff3f813e8f8fdc2d7838eefbb5f073a7efee08fa0e379747f001dcfabb81674fc3cd235a0e37b2957838eef255f053a9ec37825e8f8fef7ef41c7d7f6af005d5aa72f075da74eff0e747374fa32d0f13d006eafaafda876d564f9be4610336390906bccd004f7581aedb2f4a780a511ecd45bb533d0af8ae37bf5ead84fc7c6eab91eecd6d9b19be1842aae16caef040eb695806d5ea30fca72bd7dade578c7c16e918e03f3d4020f6fb341f3a87eb0b0ca593b08c6b14d11da64a3fd3a6394fe24c4642a2c75ceda6d764c6dbb0da8326b2c97a9caa88620996d2a05f93510af6a07f76c6be3e3eb89d791cfb37a56cfea593dab67f5ac9ed5b37a56cfea593dab67f5ac9ed5b37a56cfea59670aab62e1ebe7f81e45deae49001febf07e8bed6bdb78af8ecb56f72eeeab1cb3d960d566f6de12de8f480303db4ac03607548d71edd15ca590df04f5571f527f750eeaafdea83f5e675bf8ac2bd65fbd03960683e5996b776093fd6360a05fcd0908ee9f1bfd9559a778efb50e8e15becf17bcb746eb5ba04d3618bae9aa0f3c661a42da69b3b37e26e3e21e5af0d85d35d443a3716e49407e25f421d555637563f6172a3f1d92cf8bb13aeebe26deb7b6fc6c65d0675640f9836003ed963b68576c37ae856d54409c39ddc11362603b8cefb8776ac4276e87e97a639f14e45739f6b9d238962a0d56d54eeaa04da5e15ebfedf30dfa8b71e1f91829c8c7ef4bd638880b8eefd2c0500375d462f43b38aec23eb02a8fe3aaaa9071551df0b11fd89f5c971a6375390632e7d734d83f4f8c9b5f83f32f3a81a31e8e67de6640b76b35bfc61cf7a4615ffc7e673ee60499e7669c13b40298f33527a8dee88b3186aba09f381ec60a61e3d73a43e7803f83fc5c6e9dc18fe3026c2fb67f0b61dfc08bb13aee1c5bedb07f73d02705f37cf05c12d61f713ecff374307e08eabccaa8f32ae3fc1a33b6a90d193fd6859c7f2b2cf78d2ecee9aa8c32e8db1b8cf37902f20f87e3f508180bb2cf8d50ce86907c5e72b5631ccb953ae89f92c658b1343ed16e8983369634c68a4f3d870071e6f4b130562c8160717c4ba1ddf1b310b85d4948bb2d85e38af3538e7d2e358eab528355b593a3a04d6d80b1a2ede31cfdc5b8f0f93905f9f8bbb6c938aef1db1d782e7231d62e33e257661c9ba9d8c4f7c8e0b9d4fef82ccbd5688c75cc6b5478ed0cfb04bc7636dbc1f9b22d423f331beaaed92ecb52555c0b1cef836003bf2ddfe8a06e9a0cbb2d46df9c823835858c69da216838164a87ec638e35719c86e7463e5fb642793c4629884d1c63a925ec7a39fe9662ce6ab05365d8b17e0ece8c1fb71480cd0a606b358e49c551e6a0aecb8dfec17c9f213e9782bfcf4f4d8dc58cebb5138f5d43a7f8db1cf0b71bfcbcde0675da61b4cb6288af1d96ec3cfd287d07b62fdbfd982ab3c56e99fdf6fbb8951b5519f89c05c7af25e4dc89d74f9b1cb4a316a31db5849c9fedda1dd8acca689cc4ffc6108ec63cfadfe8cceef24daa8c8649fc6f08e168c8a3ff0dceec2e1f5265d44fe27f7d08477d1efd7777bf6945701eac9bc4ffba108eba3cfa5fb78fb14c2ed6866966b56f7769d057d74ee27f6d08476d1efdaf756637b35c95513389ff35211c3579f4bfc699dd0383d766564fe27fbee69feccbff6a6776335b54195593f85f15c2519547ffab9cd95d19b4ffca49fcaf0ce1a8cca3ff95ceecaedca0caa898c4ff8a108e8a3cfa5fe1cceec6e0f5bae593f85f1ec2519e47ffcb9dd9dd70a02aa36c12ffcb4238caf2e87f9933bb0341fda726f13f15c291caa3ff2967763707e39fd249fc2f0de128cda3ffa5eeec06e7bfe424fe2743389279f43fe9cceee6e0b75ac924fe97847094e4d1ff1267763706f53f6b12ff678570cccaa3ffb39cd91d0aaed5144fe27f710847711efd2f7666777950ff4593f85f14c2519447ff8b9cd95d129cff0a27f1bf3084a3308ffe173ab3bb65a92a233189ff89108e441efd4f38b3bb2138fe0b26f1bf2084a3208ffe1738b33b10fcfe8f4fe27f3c84239e47ffe3ceec2edf983590dbff5808472c8ffec7dcd90dfc7f3296dbffa7f281e3c958fefc675bf6ed6e0efaff2762b9fde77ce478228ffe3fe1ce6ed0ff3d1ecbed3fe723c7e379f4ff7167765706fddf63b1dcfe733e723c9647ff1f736677e30655c6de49fce77ce4d89b47fff73ab3bb3418ff3e3a89ff9c8f1c8fe6d17fe46b093957f13b47836f681afc8ad5f2f7ab96aa321fb6ecbf2a83df5bace6a1f0dc0eb69380fce5d563db1da8d349f099e7ada8fcd521f9bc18abe3e67170cc94af96bf4b15cc357d00ca1f041b68d7e5b7a5e25ad806eb13903e985fca1b1bff9e7d8e2f7e436b4fc876986e31f64941fe1ec73eefebdb046c4bb59355d0a6b8cdb838ced15f8c4b2bc485f3715e93ede34d156d7e2b82191e06964ea33f51c711b7d14ee0dbe3806f5fdfd0d8037cacc3f7a5b31fd89f6c84796d9d5a8fdf4d4cebf41c28a7dbd0293fe739f093ed70b9bc3e0ff8f8bdcdddf9e51b982adf5c834fb12cb01cab24d8e425571fbe0058e65b665165f6d82d339837b310f8d957b693827c7cee65a165dfe26093cbe575e4eb0961e5f7a9e377887b80d572cc02d6b906ebdc10bb7d798811f72b7d8eedf61a76bb0cbbea38c17a524baee3a417780fb0ccabca5c64b7cc60fcb4189807c14617e8fb1dc47e31c4330e36589f80f469307eea1f4b3e75ae616675acf4856c87e985c63e29c8ef73ecf322e0188475b6a5ceaf3b61cc64b9cd07f5dd6730f07a17e81785c4ab0fe2c5f9dda0e33100f6b1738c3292500e9e6b2db7eb4c2e3fb1de59d70b7c8b42f816dbe51bc8d51616031feb0e001617fda0c9c2e71eec071b8df805cf920157c23257b12ed76699f88d185e72f5e7c5f0bfc8328bfab68c1e4ac7768decd8b9e1b82d476cd9b019af54171a88058086690e3d7ec6a61074fc199b22d0f1feb340c7e594409e0bd7d1372eb7d0602c06365b76f17340bce4aafe59c062bb29aa18f3e78074f51fbd73ebc816acff228331acfe555ec2d88eebadd03233dae272799d6d29bff89346276cd8f4fae7ed3c6e74fb96e1915d1868b361c70d87d48295858d99b72b329cb5dc58964a6b2cfc0da74d1bb66d3b7c74e3b6ad9b0e1e1dde34b275c7705893e1886175857519b8edbeba8a2478c63a2eab0474d80d7144cc88590b493d94c9cd27a19d298a8d358992d8d827ba822988b16cfb549fd8524fcaaaa778d5884b85577d12ab0ecafdb9feaf6ca94f5ea953a0faa495fa8495fa6495ba3ca21efd53af4e518fe2aa21503a96fdf9a2860f6a48a57e42a96192fa59a77e3aab9fd26a88a486446ad8a14eedea34ab4eabead4af8682eadad600c9121235af40dd5b53f38b5790a87996ea5ecbb34856911c44f26c92e7903c57c7f77924cf277901c90b495e447230c96a924348d6901c4af262929790bc94e4652487911c4eb296e4089223495e4e7214c92b488e265947f24a925791bc9ae41892d790bc96643dc9b1b1ecb040dd0f55cf2fa9fb62eadec010c97124af23d94a723cc9eb49b6916c8f653f51bf83e404923790ec24d9453212cb7e0afe449293484e263985e48d246f223995e434923793bc85e47492b792bc8de4ed246790bc83e44c927792bc8be4dd24ef21792fc9fb48de4ff201920f927c88e4c3241f89653ff1fe51928f917c9ce413249f24f914c959249f26399be433249f253987e473249f273997e43c922f907c91e44b24e7935c40f26592af907c95e46b245f27f906c93749be45f26d92ef907c97e47b2417927c9fe407243f24f911c98f497e42f253929fc5b26df517241791fc92e462925f91fc9ae41292df90fc3696fd5cd965b1ece7cd2e8f653f87a63e93a63e9fa63eaba63eb7a63ec3a63ecfc607321ec43c758f7fa26f1819d9b2fd8491f4c88ef4f6d16d235b4fd8764afaa4ad23af4bef3871cbcea16d3b4ec29dfffd7476be45afcc9eb8f386cd9bf7bddf237a853f78b76678f39693d33b4647d23b86d21b778c0e6f1e776e3a5a7b7d905e3f327b724eefdab66324dd9f1ea6bfd403ef3869cbe64569ccdb452eec1a49ef1ad9b073243db473c7f6746611967b54a99b728fa97c1a31cd543d8d9d97574dbd42fe0f6b585bbcfe160300", + "bytecode": "0x1f8b08000000000000ffed9d0774154796f75b4280f0d3b3088e045b3860c004e9492449c023679325030e801019e3210c382272c618b0c946e0999d4db339cfe69c739cd9303bb333bb3b3b73ce37bb5ffecef1f9aafad51dfd55543ff4e4aec77dd2ed734aaffaaabaefaffe7dab3a55777f270882a22033f550e9e9e0ee89fe9f36bf959f6eaa8a715d953e398b0a84b3b840387b140867498170f62c10ce5e05c2d9bb40384b0b84b34f8c9c9aad38683fc5cdfb80075de3664c1498a66505a069b2c0347db000342d0f0aa38fea5b209cfd0a84b37f81700e2810ce870a84f3e102e17ca440381f2d10cec70a84f3f102e11c58209c830a84737081700e2910ce270a84f3c902e1ac2810cea105c2f95481703e5d209ccf1408e7b331728e00ce61e6f739f33bdcfc529991e6f779f33bcafc8e36752c31f363541aabd954aab2fe9752a95aa51a95c659ff1bafd2049526aa34c9fcafc2fcaf56a53a95ea559aacd21495a61a1da6a9345da5192acd5469964ab3559aa3d25c95e6a9345fa5052a2d5469914a2fa8b458a5252a2d5569994acb555aa1d24a951a546a54e9459556592cab555aa3d24b2abdacd22b2abdaad25a95d6a9b45ea5269536a8d4acd2469536a9b459a52d2a6d55699b4adb55daa1d26b2aed54e975953ea3d22e9576abb447a5bd2a7d56a57d2aed57e90d4bb337557a4ba5b7557ac7e27c57a5032ab5a87450a5432a1d56e9884a47553aa6d271954ea87452a5532a9d56e98c4a67553aa7d27b2a9d57e97d952ea87451a54b2a7da0d2872a5d56e98a4a5755baa6d275956ea874d3b05043f848a55b2ab5aa745ba53b2a7dacd2e754fabc4adfa7d21754fa7e957e40a51f54e98754fa6195bea8d28fa8f4a32afd984a3faed24fa8f4932afd944a3fadd2cfa8f4b32afd9c4a3fafd22fa8f425957e51a55f52e99755fa15957e55a55f53e9d755fa0d957e53a5df52e9b755fa1d957e57a5df53e9f755fa0395fe50a53fb234ff6395fe44a53f55e9cfccffe83ad89fabf41726ff97e6f7afccef5f9bdfbfb196f95b95feceb27d59a5af58b6bf57e91f4cfe1fcdef3f99dfaf9adf7f36bf5f33bf5f37bfff627ebf617ebf697effd5fcfe9bf9fd77f3fb2df3fb1fe6f7dbe6f73b2add1c9cc997066d533a88a94faa696ed6f75048ec6141fb496bd1c3fc8f7e2b8cbdc4ccd32f69d7d3ccf7b4ecbdcc7c2f6b3da566bed4b2f733f3fd2cfb00333fc0b23f6ce61fb6ec8f9af947c19e08e05aaab16b5b0f632a021bc56131d87a06ed35d1b65eb43ab0f50eda6ba16db41d7b81ad8fb1f506db03c6560ab684b1f521cd542a33b67410574c54aed3eb4dc6bd5e737fe9c1f8799bf47acb3df1f68d9fb759afb79f075e1d1ffdcdbafa42dc0c30b67e607bc8d8fa83ed61631b00b6478ced21b03d6a6c0f83ed31637b046c8f1bdba3601b686c8f816d90b13d0e36d3ed0503c136c4d80681ed09631b0cb6278d6d08d82a8ced09b00d35b627c1f694b155808dc6ae0c05db33c6f614d89e35b6a7c1467dea3360a363be678d4df7133d8b601963a73e2a5c86fa61b00da73e186c23a8ff05db48ea7bc1f63cf826db28e857c836dad8a88fd2ff9b68f2e920ae36910adbc4a4b8d7abd6acd75b17ff7ac3fb71f5419bae69f03309b49a6cf2318ef9a942df4526911fb297407e2e94a572a407ed67885def4f6a4d7e7296e5265acb25a14cada3fee920defad7593c7516734fc8fb89d9ea94c46c87a79c63b601cadab147c73c5d316617008787981d2f31dbe129e798dd0065edd8a3e3deae18b3ab80c343ccaef313b3a94a89d9ccf5af2070c71e9dfb74c598dd041cf1c7ec3889d98e4f39c76c0b94b5638fce7fbb62ccee058ef86376c23a3936e8f09473cc9e83b276ecd1b598ae18b38781c343cc364b3fdbe129e798bd0165edd8a3eb825d3166df078ef8637692a798ad96980d32f73283c01d7b748dba2bc6ec2de0883f669be4fa6cc7a79c63f6e7a0ac1d7b74bfa42bc6ec178123fe98dde0ebfa6c4a623633862308dcb147f7eeba62cc7ec9e4f5bdb1bf34f7c69e00db5f19db9360fb6b187b40b6bf31b6a1502f0f6d60a2b4810e4f39b781bf85b2762c3f65f25db10dfc11707888d97512b31d9e728ed96f42593bf6684c43578cd9af008787986d9298edf09473ccfe77286bc71e8dafe98a314be343f5f1c23f9ae385e160fb27631b01b6af1adb48b0fdb3b13d0fb6af19db28b07dddd84683ed5f8c6d0cd8be616c63c1f64d63ab04dbbf1a5b15d8fecdd85260fb7763ab06dbb78cad066cff616ce3c0f66d631b0fb6ef18db0463d3f7b1684cd5ef1a5b2970a583f8b66d0234a0a9c89a4f43beca2f4f651278d05775fcbeaa75dd5341c7eb5e0d3c351eea9e001f1de1a9019e71f1f384e349c7c7bfde701ba72c4d13e02b05f59ae0a15e45e08bd64df3e42f09366cd3131c8cb1ef9fd57eb4087cd1ba697e2230920dfb18ea73a9fde8be7948511baf87b614ee9fd15f1a38c85f09941937b8adec50c35606ffc7fe769c65f31497615c902f5a37cd93bf32a8cfb8fc33a63aca586331faea238ac017addbf65d06f94abffa64e519cfc477ad27df769f469ad7e6c1f744cb77b5e51bfb4e9ab2eddb2602b387f394aafb719e82c70f1cce536616b595b5cf37a81fcef53c6582b51cc7f39449b02ff4d01ec218a8b53868be1ab4ab8bd0ae16b4a332cf8176befaf149160fcd8f031eeabfb13fabcc334f2503df780c4bdb0dcfa5f038c0d7f6aab41869deb5bd2602a3eb58c5c3f94cd663951a60241b5ec74979d22c6abba698f8f6102b617f443ee8d89cda2ff92b81320b7ab4955d0b7da58f18c178a4a9a3e7bcf16fa754780e5e93030f6e3b0fe755559ee2b112afdf7c12c41b6b76bf54636915758dc7575f9eb278689efc09b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300b337f66bc9f84e3b6a8dc38268cf6f8375fd7f9c377ec9975e13da0ef7a1d0f96aac4b130340e628455e71228535edcc6f63f603c983d96286a5bfa181b9b6d5b923f1c0f968f7b88d5168fedbbcca10fde9746cd7c8d81b2fb0c9ac7f169a45f25f0f86a8f55168fed1bfb8c1453cda2fa595f630ba2e2cc359eb02236dfa9265ff775f5fbccf43b41edfdd7384bd3f05da3964df7492ff468abb78ffbbcb9de77c6fd06e5e3bc8f9b041ef4157f3f9b6a373ea13868bfafc058f735568bda158d8da8b57c97409921c56ddba60efe9f0eeede3760195a37cd8f8065ebac7597fbab6fd67128b5c04df95e56ddc6033795790af6dd7f66f29ef681a95c9f91c07d72fcfb97cc7891540e3cb8bff371cce2693f5a89f118f778117b1ca4eb7899cae018520fe377b3ee8bc99f300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330f367d63cf63d74bcf75bcd84314f636cc2fb19f42e36bc2ff693c56d7e7ddf03a47b4e23ad3ae333ca013ca3fcb3860dc73ee07ba55cdbd2d7bdb5a86d49feb88d7d2873e8a335ab736856ef89d1ee3368be1e1849bf3ae0f1d51ea3dedde1ea332a996a16d5cffa18bb902dce5ce3142a62f39d192fe2e3be2e8d17b1f75ff67b8d709c04d9f03e78d4fbc2aa2cdbfdee035ce3da288fef5c88bfdf4cb5bb076c8f15247f384ee22b465b1a27117f3f90aaf4b98fa0364a6342528eba5299af16b795fd9ac9e358a16a58d7771dffa729db9804ec53a7c45fe770fb4e35eba2ed3bc5e13b0dac31f9ae42df45d6bac95e02f9ff567c3703e9415a13bb6e23f81eaba8e56aace5925066b2a3fee998eb3fc5e2c16dac271d3bdf8038fb2e1cebf9ea93264768340234a2329edf03eb1ce76b8f55c67eb4b7558696c5f75bfe1fe8a3a2c6a4bbf601be8e17a2f60178bc60ef173a3276bcbb8f07ec63ce437c8c07a4759707edc7e405d6fa47c2fa89ab7710bd6ff9deb938acdfe798f57bbdf7ca75ee47bc38de90caf48773bf99269fcbb9dffd3a8f779dfbe1725175c77e21ee7d23c623b2e0fb22a9cc602b1eeb22b8273a967d326259d2ca7ef7219e97e23142fcef8dccf43753acba509b9a0c75a132cf5aed26fe63a6ccf1a7af7764d2b10ef541558eba529991d0d646997c02b613ee17ea1cffa729dbf127e9a7eb3c2dfe3a87db77ba59176ddf690edf33803526df55e89b8e3fc90fd94b205f0bfb132a477a90d6c45e069cc86e2f576b2d9784326947fdd331d77f9ac533cd62d6b13316e2ac0e9eb5f0d557a703b7462341a3eff9039bebbdc6ae7d8cafe7d1a2f63155c068f79bb89fcce7b372f6f55bd7f10995c163682a330ffad984a3ac7d5d9a968b737c3a3e0f84c785f83c90af73a464d05ecfa4c5e1d377b9e5bb3c8fbefb59befbe5d1b7682e9a73d29cd3377f70df520c8c3ece1bf1fa484718f17d04b45c0f60f4f5cc662a07c66a60c4fd1d317a78bf725567bf2984c73a3d81d1c7f3c6b95eafc6f79be33b0688d1c733dab9bea71a9fdba6e57a03a38fef1ae137943ac2e8fad65129fc7af8ae515567bf0382df3aea038c3ebe0d9208da7fcfe45e8c938091967b00187ddc474a04edafabdd8b11ef57d27209cf8cd9f6ed9ec7fea472bd06918f710551c71ae8dbc3f5ff148e4de88816f57e79b21efba06f0fd7bf422dea838e6b81f7e73cdc1b0ddbf1e41c78f01e222dd71f18a77a629c9203e35460a4e5060063da13e3d41c18d3c048cb3d048c1eae43868ce91c18f17a1dd91f06c6e99e18a7e5c0381d1869b94780d1c735c504f8ed08e30c60a4e51e05c6999e1867e4c038131869b9c780719627c6993930ce02465aee71609ced8971560e8cb38191961b088c733c31cece81710e30d272838071ae27c6393930ce05465a6e3030cef3c4383707c679c048cb0d01c6f99e18e7e5c0381f1869b92780718127c6f939302e00465aee49605ce88971410e8c0b819196ab2800c6a105c0f85401303e5d008ccf1400e3b305c0585a008ccf03e3a2f819c3f3d48539302e029e17e2e709355b9403cf0b7e79c2f7132e72f85a1cbfaf54ae755f0c3c4be2e709b7c5e21c78882109cbbde09731d55946cdb3347e9e50b32539f02c05cd963834f3c098ea2ca3e659163f4fa8d9d21c789681664b1d9a79604c759651f32c8f9f27d46c590e3ccb41b3650ecd3c30a63acba87956c4cf136ab63c079e15a0d97287661e18539d65d43c2be3e709355b9103cf4ad06c8543330f8ca9ce326a9e86f87942cd56e6c0d3009aad7468e68131d55946cdd3183f4fa859430e3c8da0598343330f8ca9ce326a9e17e3e709356bcc81e745d0acd1a1192746e489fb7de38d0e5fab18d49d1890b14f01303e50008c3806c147ff956d0c42a35f7d529dd5c7d7f6ca3606017daff6a4c5aaa0e35aacf6cb93750c02fa5ee3498bd541c7b558033c2f79d022013e3ac2430c4958ae7f01300e2800c6870a80f1e102607ca400181f2d00c6c70a80f1f102601c58008c830a80717001300e2900c6270a80f1c902607cd13363b6f39797bab8efa87395aeee3beabca4abfb96389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389734ebe5ff6e03b013e68ca768d9f1892b0dc8bc2d8a51991a7223e9e4aac3bfa7a8541dd5f71f01479aa3bfa7a9541dd89a1d0185f2e00c6170b805174cc8c41ec0ca3e659eb89e7d51c78d602cf3a4f3c6b73e059073cebe3e709636a5d0e3cc49084e55e2c00c6970b805174141d39318a8edd47476114466114c6fbc158087db8ec6732e72e9d61d43c4df1f3849aadcf81a70934a3e55ef0cb98ea2ca3e6d9103f4fa859530e3c1b40b32687661e18539d65d43ccdf1f3849a6dc881a71934dbe0d0cc0363aab38c9a6763fc3ca166cd39f06c04cd9a1d9a79604c759651f36c8a9f27d46c630e3c9b40b38d0ecd3c30a63acba87936c7cf136ab629079ecda0d92687661e18539d65d43c5be2e70935db9c03cf16d06cb343330f8ca9ce326a9eadf1f3849a6dc981672b68b6c5a19907c654671935cfb6f87942cdb6e6c0b30d34dbead08c2be38b05c0f87201307ad631d55946cdb3dd13cfb61c78b603cf0e4f3cdb73e0d9013cafc5cf13c6d48e1c78882109cbbd58008c2f1700a3e8283a7262141dbb8f8ec2288cc2981be32b05c028db5a18b9327a38bfcafa7cca8e2eee3beaf994aeee3beaf994aeee5be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25ce39f9de19bfef54aecfb0ee041e1fcfd47aaa67a55eefeb665d9fc4a89fd6ea3396563b2cad9250e675d0ef331ef42b02bfb46e9a277fb9320f63c0ecc977ea41b58e3e507ff2f1b2a587f6bfcb53dda3fafa5d5ddc77545fdfd57d47f5f55dddb7c4b9c47977f02d712e71de1d7c4b9c4b9c73f18df992a0edb89ddeafa4d7b1dbe47b9a792aff0a2c4765e6f5cefc9607d2867cf8963624fb8aeee05be25ce2bc3bf896389738ef0ebe25cef9c539c6c3bc3cf004164f9085271ff70f72e119c38c6706339ec9cc782630e3a962c6339219cf66663ccdcc78d633e3e9c18c673e339e99cc785e62c6338519cf44663c29663c5b99f1ac64c6b38c19cf68663c8b99f1bcca8c6716339ea9cc78d630e399c48ca79a19cf36663c5b98f10c63c6b391194f13339e05cc78d632e399cd8c27cd8ca79619cf70663c35cc78b633e3798e194f23339e06663ccb99f12c61c653c68c27c98c6721339e39cc78a631e3a963c6338e19cf2a663c9b98f16c60c6b38e19cf08663c0f32e32967c6339619cf5c663cd399f1d433e319cf8ca79219cf6a663c2b98f12c65c6d397194f3f663c8b98f18c62c653c4802711dcfd8e9304fc7f27d88aad65f563616f0e6efbff1e632f8665f69a7c0fc7baf7808d9e35dbeb581675da0375499b7ce5a79b429dd0571ae6c95f1970ec65c2338a19cf22663cfd98f1f465c6b39419cf0a663cab99f15432e319cf8ca79e19cf74663c7399f18c65c653ce8ce741663c2398f1ac63c6b38119cf26663cab98f18c63c653c78c671a339e39cc781632e34932e32963c6b38419cf72663c0dcc781a99f13cc78c673b339e1a663cc399f1d432e34933e399cd8c672d339e05cc789a98f16c64c6338c19cf16663cdb98f15433e399c48c670d339ea9cc786631e3799519cf62663ca399f12c63c6b39219cf56663c29663c1399f14c61c6f312339e99cc78e633e3e9c18c673d339e66663c9b99f18c64c653c58c6702339ec9cc786630e319c38c6727339e790e1e0fdfcf0b7968bc2aad9be67732f1ed613b84df0dfcaca73aed33ebea65d64bfce4af04ca2cea93f9d5e3757059e2b2c71763acee038d767baa4bd43b99777771df51ef64eeeabea3dec9dcd57d4b9c4b9c73f2bd2f7edf297c3685a6226b3e0d79dcbff878a6c7533ddbeddbe3fe26f07e4babdd96564928f359d06fbf07fd5cc70b344ffe72651ec68019e3a22288372ede88bf4edffbd630e9fa86a52fd6eb4d4f9a46ed43deece2bea3f6215ddd77d43ea4abfb96389738ef0ebe25ce25cebb836f897389734ebedf32f918cf1b2bd187bef64be7036f81df774cbe2846bf7a5d6f9b75d1b79189e31de0a1323f02d7a2a5cd4b9b8fcbb7ecdb24cebb836fce716ee7e91e22beb7dbd73ddea858ccc7fde5fbe93b2a16bbbaefa858eceabe25ce25ce39f97e377edfe13dc49d41fb29db3dc47781e76d0f5a78aa6778ee74c0aad34eab4e492883e772073cd4b308fcd2ba69fe006c874263d63c34961ddfcf48e55e62c248b6b7fdf284edeba5a0fd94ad7d1d001e0feda0ca533dc3f6d562d5e92587ee540663b5c5433d5d6d87e65b603bb41418b3e6a167e7883501e55e65c248b677fdf284edebd5a0fd94ad7db5008f8ffec7533dc3f675d0aad3ab0edda90cc6ea410ff574b51d9a277f85c8ac79d69a3cb126a0dc5a268c643be097a7260175a6295bfb3a083c2d1ef4f154cfb07d1db2eab436b85b772a83b17ac8433d5d6d87e60fc17610666176316b9e7526bfd6fc26a0dc3a268c646bf1ca535399803ad394ad1f3b043c3efa794fba87fdd861ab4eeb1cba53198cd5c31eeae96a3b347f18b6432eccfb0a905974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974ee1cb3e6596ff2c49a8072eb993092eda05f9ef0f99df541fba9c89a4f43fe30f01cf2a08fa77a86e3de8f58755aefd09dca60fb3ae2a19eaeb643f347603be4c2bcaf009945e7ce316b9e269327d604946b62c248b6437e79c27eac29683f65ebc78e008f8f7ede533dc37eeca855a72687ee5406dbd7510ff574b51d9a3f0adb419885d9c5ac7936983cb126a0dc06268c643bec9527153e87b821683f65ebc78e028f8f7ede93ee613f76ccaad30687ee540663f598877abada0ecd1f83ed900bf3be0264169d45e72866d159748e62169d45e72866d159748e62169d45e72866d159748e62169d45e72866d159748e62169d45e72866d1b9fbe8ac799a4d9e581350ae990923d98e78e5a90eef3b3407eda76cf71d8e018f8ffb329e740fef3b1cb7ead4ecd09dca60fb3aeea19eaeb643f3c7613b7475e67d05c82cb1911f66890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e628660eb1a179369a3cb126a0dc46268c643bea97277cefc1c6a0fd946ddcce71e039e6411f4ff50cc7ed9cb0eab4d1a13b95c1f675c2433d5d6d87e64fc07610666176316b9e4d264fac0928b7890923d98ef9e509fbb14d41fb295b3f7602787cf4f39eea19f66327ad3a6d72e84e6530564f7aa8a7abedd0fc49d80ec22ccc2e66cdb3d9e4893501e536336124db71bf3c613fb639683f65ebc74e028f8f7ede533dc37eec9455a7cd0edda90cc6ea290ff574b51d9a3f05db419885d9c5ac79b6983cb126a0dc16268c643be1972795803ad394ad1f3b053c3efa794ff50cfbb1d3569db63874a73218aba73dd4d3d57668fe346c874263d63c5b4d9e5813506e2b1346b29df4cb13b6afad41fb295bfb3a0d3c3efa1f4ff50cdbd719ab4e5b1dba53198cd5331eeae96a3b347f06b643a1316b9e6d264fac0928b78d0923d94ef9e509dbd7b6a0fd94ad7d9d011e1ffd8fa77a86edebac55a76d0edda90cc6ea590ff574b51d9a3f0bdba1d09835cf769327d60494dbce84916ca73df324a0ce34656b5f6781c747ffe3a99e61fb3a67d569bb43772af326d4f39c877abada0ecd9f031e9ae6018fafb80c2c9ec0a10f4d6398f1cc60c6339919cf04663c55cc784632e3e9c18c673e339e99cc78a630e399c88c27c58c6725339e65cc784633e3799319cf62663cb398f14c65c6b38619cf24663cd5cc788631e359c08c6736339e34339e5a663cc399f1d430e36964c6d3c08c6739339e25cc78ca98f12499f12c64c6338719cf34663c75cc78c631e359c58c6704339e0799f19433e319cb8c673f339eb9cc78a633e3a967c6339e194f25339ed5cc785630e359ca8ca72f339e7ecc781631e319c58ca788014f22b87b2c4d02febf1f6c34e6633bd8de33f933602b76f8a07bc5e7c05662f2b48ede2a1d1d7cf7ba51275fe35cd0571ae6c95f1970bcc7846714339e45cc78fa31e3e9cb8c6729339e15cc785633e3a964c6339e194f3d339ee9cc78e632e3d9cf8c672c339e72663c0f32e319c18c6715339e71cc78ea98f14c63c6338719cf42663c49663c65cc789630e359ce8ca781194f23339e1a663cc399f1d432e34933e399cd8c6701339e61cc78aa99f14c62c6b38619cf54663cb398f12c66c6f326339ed1cc789631e359c98c27c58c6722339e29cc786632e399cf8ca707339e91cc78aa98f14c60c6339919cf0c663c6398f1cc73f0ecf7c4633fe745f3fb19f8d6f3b5a08b9e12f07f7c0eec4d4f8cfb2d469a7f131891d7b766e5164fb9a5d9fdf4adeb4ff72a1e34bfb8bdf0b9070edbab3c0f9af5b378fa599add4fdf5a0bbaf74f636c707be138680edb0bc7697ae89f6b12168f9e8aacf934e4cf79d6c7533d2b71dce42731ae576b75ded26abfa55512ca9c05fdce7bd0af08fcd2ba699efc09b33047316b1eba97eb1acfbb900923d9f03d2aefc7cf5393b078f494ad7f7cdfb33e9eea19f6631702b7eeef83ee540663f582877a16815f5a37cd5f70f8ae08e2d5e26207b4b8e8e0b998672dc85faecc670b909983ce9a87c6ae136b02ca2d62c248b6f3c073297e9e9a84c5a3a76cfde325cffa78aa67d8277c10b875bf04ba53196c5f1f78a86711f8a575d3fc07b01d7261be5080cca273e79835cf629327d604945bcc84916c1781e7c3d8795295098b474fd9fab10f3debe3a79e997eec72e0d6fd43d09dca60fbbaeca19e45e097d64df397613b08b3300bb3300bb3300bb3300bb3300bb3300bb330eb32c22cccc22cccc22cccc2cc9759f3d0b3e7c49a80724b983092ed03e0b9123b4fe6be03f2e829db7d872b9ef5f153cfcc7d87ab815bf72ba03b95c158bdeaa19e45e097d64df357613b08b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300b336f66cd43dfb020d604945bca84916c9781e75afc3c35098b474fd9ee3b5cf3ac8fa77a86f71dae076eddaf81ee540663f5ba877a16815f5a37cd5f87ed20ccc2ec62d63cf42e44624d40b9654c18c97615786ec4ce93b97f8a3c7acad68fddf0ac8f9f7a66fab19b815bf71ba03b95c158bde9a19e45e097d64df337613be4c27ca100994567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974ee3e3a6b1efa4627b126a0dc72268c64bb0e3c1fc5ce535d99b078f494edbec3479ef5f153cfcc7d875b815bf78f40772a83edeb96877a16815f5a37cddf82edd0d5992f1420b3c4467e98253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a39839c486e65961f2c49a80722b983092ed26f0b4c6cf5393b078f4946ddc4eab677d3cd5331cb7733b70ebde0aba53196c5fb73dd4b308fcd2ba699efc09b33047316b9e95264fac0928b7920923d96e01cf9df87952098b474fd9fab13b9ef5f154cfb01ffb3870eb7e0774a73218ab1f7ba86711f8a575d3fcc7b01d0a8d59f334987cabf94d40b906268c64bb0d3c1ee22ee4495a3c347f87816f3ddf68f265e617b757233072d85ec93c68566ef1945b9add4fdfbafeab4cfe41f38bdb6b153072d85ee579d0ac9fc5d3cfd2ec7efad65aac36f9bee617b7d76a60e4b0bdfaf9e549252c1e3d653bdef818783e1f3f4f781ef7710e3c9f079ecfc5cf53e5a99e957abddf07ec71ad576bf5054bab8f2dad92500619bee041bf22f04beba679f227ccc21cc58c7d21b126a0dc1d268c64fb1cf0f8e83774dd479975d1fa7baaf450ff36bfadf1fbadc16b0bbdcc7a8983fc9540999707b5b13d66d8cae0ffb4dd747d6e59364fcfbc55b9aef3d23cf92b0bdce7fabeaea1b65a3cb6ef32873e5ab39b0ecd6e7862b49f69a5f91bc0e8baceebeb79d1a8ebcef8bce81d4b476e9ae173c01f018fafe3e2568ba7d5a1858f3697ebf1e5470e9e4fe2e3a9c4d8405f3e6215fbb68ed4ddd57662ac7b15dec3425f1eda40b89f1a6dd645ebd7fb82dafe5e35afc1fe81f653a3ad3a97409949b09f9a92653f551cdc7d5db8c2d8a90cfdff1363b7d75111dcdf6b4b6590af35bf18a36493fd6ffb7b98b5968edc34c376dd0a3cad9e78a2ae89913fdc86750ecdea1868866d211f7176c7e2b17d27419756a69a619ce17183affeec5ed7f2701bd63b34ab67a019c7feacded2919b66aefe0c755ce8e05ec8809b639fb2d0d2919b66ae3e05755ce4e05ec4809b63bb5e64e9c84db37bb5ebc50eeec50cb839b6ebc5968edc34bb57bb5ee2e05ec2809b63bb5e62e9c84db37bb5eba50eeea50cb839b6eba5968edc34bb57bb5ee6e05ec6809b63bb5e66e9c84db37bb5ebe50eeee50cb839b6ebe5968edc34bb57bb5ee1e05ec1809b63bb5e61e9c84db37bb5eb950eee950cb839b6eb95968edc34bb57bb6e70703730e0e6d8ae1b2c1db96996effb0051f79bc81f6ec34687668d0c34e3d8a7345a3a72d32cdff701ee35061bb7e12a8766ab1868c6b13f5b65e9c84db37cf76751f79bc81f6ec3d50ecd5633d08c637fb6dad2919b6651fd596bfc3c398fb76ff5aa4fe63bcbad39f0e098291f31e5290e2a3d8da90ac7dbdbdfaf68b5b44a06777fd3c2e7d8c3a8f191e44f98855998855998855998855998855998855998855998855998855998855998f933e3f3ccade617df857a870923d9f09e948febfcbaee63ccba68fdfad9de5b03dafcc67fdf225589f75ce9b9e331569d4ba0ccff7dbc8ded63c386f71769bb456dcbfbf56e057c1f05de0bba9ff73b3f726876c3a1d9754f8c769f41f3d781d17effc3fd7ef7c41d4b476e9a45f5b3773cf144c5d91d87ef8ad87ca79a7cddd7d5ef22ec13dcbdffbae3d0d4471ce6faee0b6c17ad1e787cbde742d7e9ba55a75b569d92506618d4f37eb62d9ae6018faffe28b07802873e341533e399c18c670c339ec9cc784a99f14c60c653c58c6724339e6798f13cc18ce731663cfd99f1f461c6d38319cf7c663c3399f14c61c63391194f8a19cfb3cc785632e3799219cf32663c8f33e359cc8c6700339e0798f18c66c653c28ce779663cb398f14c65c6b38619cf24663cd5cc78f2710f34179e61cc782a98f10c64c6f310339e05cc7812cc787a32e399cd8c27cd8ca79619cf70663c35cc781a99f13cc78ca78119cf50663ccb99f10c62c6b38419cfc3cc781632e32963c69364c6d38b19cf1c663cd398f1d431e319c78c6715339ea798f10c66c6f308339e11cc781e64c653ce8c672c339edecc78e632e399ce8ca79e19cf78663c95cc785633e3799a19cf0a663c4398f1dc66c6b39419cf22663c8f32e3e9cb8ca71f339e51cc788a18f02482bb9f5dc2e7e56e818d9eb169055bb1637d342e97caebe3ceb383ef5e77b163dd371c0ca8d335a84bdae42b3fddd4eeb9a222b35e9a277f65c0718309cf28663cfd98f1f465c6f328339e45cc789632e3b9cd8c6708339e15cc789e66c6b39a194f25339ef1cc78ea99f14c67c63397194f6f663c6399f19433e3799019cf08663c8f30e319cc8ce729663cab98f18c63c653c78c671a339e39cc787a31e34932e32963c6b39019cfc3cc789630e319c48c6739339ea1cc781a98f13cc78ca791194f0d339ee1cc786a99f1a499f1cc66c6d393194f8219cf02663c0f31e319c88ca78219cf30663c3799f15433e399c48c670d339ea9cc786631e3799e194f09339ed1cc781e60c6338019cf62663c8f33e359c68ce749663c2b99f13ccb8c27c58c6722339e29cc786632e399cf8ca707339e3ecc78fa33e3798c19cf13cc789e61c63392194f15339e09cc784a99f14c66c6338619cf0c663cc5cc78e6593cf87f7dad81ae2f5e071bfdff3fcdcdfb72538feb96bf18ea5119f56d1e5f9ae194766812f56d1e0e3c3398f18c61c63399194f29339e09cc78aa98f18c64c6f30c339e2798f13cc68ca73f339e3ecc787a30e399cf8c6726339e29cc782632e34931e3799619cf4a663c4f32e359c68ce771663c8b99f10c60c6f300339ed1cc784a98f13ccf8c6716339ea9cc78d630e399c48ca79a19cf4d663c15cc780632e3798819cf02663c09663c3d99f1cc66c69366c653cb8c6738339e1a663c8dcc789e63c6d3c08c6728339ee5cc780631e359c28ce761663c0b99f19431e34932e3e9c58c670e339e69cc78ea98f18c63c6b38a19cf53cc780633e3798419cf08663c0f32e32967c63396194f6f663c7399f14c67c653cf8c673c339e4a663cab99f13ccd8c6705339e21cc786e33e359ca8c6711339e4799f1f465c6d38f19cf28663c450c78a2be8543ffef01b6ab267f1b6c574cfe26d82e9bfc75b07de8b0153b58c8df55b0d138972b60a37b7597c146d78bc8973edebd38f86ed662479d7a3858af38ea74d5b12c6e475a261dc4bb1dd1571ae6c91f7eabe72a139e51cc78fa31e3e9cb8ce751663c8b98f12c65c6739b19cf10663c2b98f13ccd8c6735339e4a663ce399f1d433e399ce8c672e339edecc78c632e32967c6f320339e11cc781e61c6339819cf53cc785631e319c78ca78e19cf34663c7398f1f462c69364c653c68c6721339e8799f12c61c6338819cf72663c4399f13430e3798e194f23339e1a663cc399f1d432e34933e399cd8ca727339e04339e05cc781e62c63390194f05339e9bcc78aa99f14c62c6b38619cf54663cb398f13ccf8ca78419cf68663c0f30e319c08c6731339ec799f12c63c6f324339e95cc789e65c69362c6339119cf14663c3399f1cc67c6d383194f1f663cfd99f13cc68ce709663ccf30e319c98ca78a19cf04663ca5cc782633e319c38c6706339e62663cf32c1ebca6580936ca57818df229b051be1a6c94af011be5c7818df2e3c146f90960a3fc44b0517e12d8284ff78cf0f99e7cbc178e7cd1ba69fe1a30de3679dc2694af03ee0f2c9be6bee489fb038b9be62f0123d5e103b051be1eb82f5a36cd7dc113f7458b9be62f0023d5e122d8283f196c949f0236ca4f05db54f04736ca4f031be5a7838df233c046f99960a3fc2cb0517e36d8283f076c949f0b36cacf031be5e7838df20bc046f985e6576fe3f72d9bdec6e74d3e1dc4bb8dc917ad9be6cf03236deff7c146f945c0fd9e65d3dce73c71bf6771d3fc3960a43abc0736ca2f06eeb3964d739ff1c47dd6e2a6f933c04875380b36ca2f01eed3964d739ff2c47ddae2a6f953c04875380d36ca2f05ee93964d739ff0c47dd2e2a6f913c04875380936ca2f03eee3964d731ff3c47ddce2a6f963c04875380e36ca2f07eea3964d731ff1c47dd4e2a6f923c04875380a36caaf00eec3964d731ff2c47dd8e2a6f943c04875380c36caaf04ee83964d73b778e23e6871d37c0b30521d0e828df2f83efa359e186f5b8cb72ddf781f178f2d0f5836cdf8ae27c6031623cdbf0b8c2d267f00780e78e269b1786cdf49d0650d53cd92606b019e5a4f3cd72c9e6b961638de0dcf05d658369fdb758dc548f30780b1c5e4f3d1365b2c1edb771274a965aa59126c2dc053e789e792c573c9d2029f73c173b75acbe673bbd65a8c765f8171867d85afb6d962f1d8be93a04b1d53cdb0cf6d019e7a4f3c172c9e0b96166590c7f3c73acbe673bbd6598c765f8171867d85afb6d962f1d8be93a04b3d53cdb0cf6d019e164f3ce72d9ef3966fdc8678bebfd0b2f9dcae0b2d469ac73ed76e0ba5908f9ba7dee2b17d27419716a69ab9da82cffeec9cc573cef28ddb10afcf2cb26c3eb7eb228b91e61702638bc9e3365ce489a7c5e2b17d2741977aa69ab9da4229b0c5cd73c6e239636981e3f6f07a5abd65f3b95da3fa8f45c0d862f2f9689b2d168fed3b09ba2c66aa191e43b6004f8b279e5316cf29cb376e43bcfeb9c4b2f9dcae4b2c469ac73ed76e0ba5908f9b67b1c563fb4e822e2d4c3573b5059ffdd9098be784e51bb7215eaf5e6ad97c6ed7a51623cd2f01c61693c76db8d4134f8bc563fb4e822e8b996ae66a0b3efbb36316cf31cb376e43bcbfb0ccb2f9dcaecb2c469a5f0a8c765b28857cdc3c51fd19f94b822e2d4c3573b58552608b9be788c573c4d2a20cf2783fa8c5b2f9dcae2d1623cd2f0346d2aa05785a3cf144c519f94b822ecb996a96045b3ef69b872c9e43966fdc8678ff6e8565f3b95d57588c34df028c765b28857cdc3ccb2d1edb77127459cc5433575b401d1b807ba565f3a9ed4a8b9be65700e362878e2b3df144f5292b41c7064b476e9ab9e211756c04ee06cbe653db068bbbc1d2d6158fa5908f9b27aa5d37808e8d968edc3473c56319b0ad02eec596cda7b651eda80118975bdafadcef456debc5a023e9d2c85433bcae89db9ad8560377a365f3a96da3c56db719dcd6d8661a3df1446deb46d0917459c55433ec7bf07cc8d7f947d4fdae7cf88eba07920fdf51d7c5f3e13bea5a693e7c47dd47cf87efa86b2af9f07daff36c9fbea3ae59e6c377d4795f3e7cdfb67cdfcea3efa8f16ff9f01d3526aaabb76fd99774af7dc9fdecd7baebbe44fa739efdf9eaf87da71241fb731a3d1559f369c8e3f9cb2a0f5a78aa67259e137e12e37a5de7d6cb2dadf0dc1acf517d9dffadb678689efc152233c645517cbe2bf13a0c7edf91ae8b54828dae8b55818dae8ba6c0d662f2d560a37b323560a3fb81e3c046f7a2e7838dc6412c001b8dc1b900361afff53ed868ece179b0d1b8d7f7c04663aecf818dc6fb9f051b3d6b72066cef98fc69b0bd6df2a7c0f696c99f04db9b267f026c6f98fc71b0ed37f96360db67f247c1f659933f02b6bd267f186c7b4cfe10d8769b3c5e7bdf65f2782de733268fd7f25e37f9f160db69f213c0f69ac94f04db0e939f04b6ed267f1b6cdb4cfe0ad8b69a3c7e5f748bc97f00b6cd267f096c9b4cfe22d8369afc64b0359bfc14b06d30f9a9606b32f934d8d69bfc34b0ad33f9e9605b6bf233c0f6aac9cf04db2b263f0b6c2f9bfc6cb0bd64f273c0f6a2c9cf05db0b263f0f6c1f9bfc41b07dcee4f13a68b1c9e3f57b7adf14def3a2775ee23d4f7aaf34de6fa76f7fb4808dbeaf85e38c4a4d1ec7b8d17ba5707c25bd4b12c7a9264c1ec79597993c3ed340dffdc06743e8db51f85c52b9c9e33371f4cdcf0360a3ef92be0b367af7d43b601b60f26f838ddee9fc16d8e83b176f828dbeddf406d8e87b9ffbc146ef98da07b6c74dfeb3601b68f27bc136c8e4f7808dbed1b41b6cf49dc85d60a377497d066cf47ec4d7c15661f23bc136d4e45f03db5326bf036cf4fdc5ed60a377466d031bbd77702bd88699fc16b0d1f70e36836db8c96f021b7dc76b23d8e8dd50cd607bdee437806d94c937816db4c9af071bbd9b671dd8c69afc5ab0d13efb55b0d13efb15b0d13efb65b0d13efb25b0d13efb45b0d13efb05b051dfff31d8a8efa7fe43b753dd7e6f99f97410df7194f6d71ab49fb21dcb1303f2c4796c9c041ef47533f6baa7c2e3f08fccba8acd7a295e6e82efebb1fbce9c03dc30ebea69d67bddf25d02654a07b66d9b6bf0ff34d48196c332b46e9a1f03cb5eb3d65d6eea7bc3537daf5b4cc47d0398a84cd9c0b6b25f32f952582646b6f07c96622d000d714a439e18fc68950acf2f3eca81e706f0c4df4e32e7d73e6202db56dce7d7f675193bd69250e63ae8e7ebbd58372c1e9a277fc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc2cc9f59f3d0fd04624d40b95b4c18c986f7ba7c5ce7c77bae78cfebe6c036bfbeefeff532eb1d6bd5b904ca7c6b601bdb6d932f83ffd3768bda961eee1366dd96dfbb5706f5c17b411eb665c873d3e2b17d9739f4d19a5d736876d513a3dd67d03c7ef385f4bb063cbedae3758bc7f68d7dc60da69a45f5b33ec625648b33d718848ad87ca79a7cddd7d563a1f4580e7bff75cbd214c740e03df32f419f44cbdc31bf09d0e70ee8733ffb007b5c02f653adc0187fbf996a770f98fafe3196a63806e2b78cb6340622fe7e2055e9731f416dd41e5b8175a532bf0ffbb93f34791c07740bd6f515c7ff69ca362601fbd4cbf1d739dcbe1f9a75d1f6bdecf0fd01b0c6e4bb0a7d1799447ec85e02f92f0f6c2b6b7f678ab42676fc1616b2dbcbb55acb25a1cc1547fdd341bcf5bf6cf15cb69875ecfc09c4d957e058cf579f742542a331a01195c1635e5ffbaf8f2c1ee2207fd88ff6b6cad0b22550e6ebd047e9ba503fdf6a7ea3f601be8e17a2f60178bc60ef17128e3aeaf8b835a08db7bb8ff5fb2fe82faec1ffd3c1a71febf75f1043aee3525aff58583f71f50ea2f72d54e67f59fb511fe793b82d6d3d712c2195f97fd00fa50665f2b99cd7ddaf73f4a8f33a1fdfcec4730d9ab2eddf711fe3a37ff154cf4ad7beeb9a55a724941906f5f4701ce3dc6fd1fc65f0edeb7ba9e4838ea1ae5b5a944099a4693bd47744e988d7256ee4a52e29e7f1e058475da8cc00a84b29d8e364f2b9ddf0384baff7a6a3ae54e6b1416d65079a7c02b613f6a5231cffa7295b7f40fae93a5f8cbfcee1f6a5e71669fb5e74f87e1f5863f2ddeefd1574bc4f7ec85e02f9e183dacadadfee24adf15bacf47c1db2dbcb5db7964b42994b8efaa78378eb1ff59d59f2a7636708c419c591cf7ef35284466341232a83f70aeceb2d51fb7d1f63e9b3edf76f02a3dd6fe2b18b4f36fb9cc5be5eee3a1ea43278ce426526403f9b7094f57f1f20736c83f5a27a04565d03abae9e8e5f6b8a2c3dd3e06734d8293e4967fa1f1ee3529969d6feccf7756ce2a67ae0fdbaab16f7354b57bc16351bb875dcdbe716789ceef99cb6068fc5ece3a1abc04e65165ac743f671dc6d475decfd747170f7b9e02756597c3629db7276fe236b19bc66e0ba268b7ddf1560499b7ce5a799aa2a2b91a9d8a185ebbea9ab4fa2768031675f47196dad07afa3acb1fa24bbacee936afbb7e943db11afb5dbd7df3d3d9b16b6b95b56fd6d8d3463abc9e336f4710fa33b3e9b561adb7a27ad2fc4f10ca5563e1edfa90db8afc8a6c555078faf6b9a515a5c75f88e4f8bf14daefd874b8b2b0e1e5fe798515a5c71f88e518b8dae6b0b2e2d2e3b787c9d6b446971d9e13b3e2d26b4bbae914d8b0f1d3cf15fd3c8ae05de13cb85f90a03e6522b1f8fef9af5ae7b772e2d3e70f0f8ba7717a5c5070edff1695135de75ceeed2e29283e7529eb5b8e4f01d9f161327b9aea9b8b4b8e8e0f1707d2dab16171dbe638c8b66bcbe964d8b0b0e9e0b79d6e282c3778cc787e3b35d33442dde77f0f8baf617a5c5fb0edf316ab14efb3edf012dce3b78cee7598bf30edff169b17e9cf6fd5e07b478cfc1f35e9eb578cfe13b3e2dd64dd4becf75408b730e9e7379d6e29cc3778ce750615c9ced8016671d3c67f3acc55987eff8b4d8101e6b9de98016671c3c67f2acc51987eff8b4a80cf7a9a73ba0c56907cfe93c6b71dae13bc6b808cf274f75408b530e9e5379d6e294c3778cfb91302e4e76408b930e9e9379d6e2a4c3777c5a6c0caf3f9de88016271c3c27f2acc50987ef18afb9847171bc035a1c77f01ccfb316c71dbee3d3a23adca71eeb8016c71c3cc7f2acc53187eff8b4680eef891ded8016471d3c47f3acc55187ef188f3bc3fee24807b438e2e03992672d8e387cc778dc195ebf38dc012d0e3b780ee7598bc30edf31f69de171e7a10e6871c8c17328cf5a1c72f88ef1b833d4e26007b438e8e03998672d0e3a7cc778dc19ee475a3aa0458b83a725cf5ab4387cc7181761df79a0035a1c70f01cc8b316071cbe63bcae15f69def76408b771d3cefe6598b771dbe633c1f09aff1bdd3012dde71f0bc93672dde71f88ef15e51780cfe7607b478dbc1f3769eb5781b7cfb1867825ad058ac5196162550e681c1995f1a8b15a523ad039fa1c5babc157b5d32e3cade8ca8cb5b50172ad317ea520af638993cd5358c19fa96028d4d6f75d495ca3c3cb8adeca3269f806d721bd635ccf17f9ab28d4122fd749df7c55fe73056e91b10b47df7397cef05d6987c57a16f1a9b4e7ec85e02f96707b795a572a407694decba8dd0373090dd5eee6d6bb92494d9efa87f3a88b7fefb2c9e7d1673f8dc03c419c5919fbe2bc3b43f42a351a01195c1317bad9e78ec3184c441fe7419dafebdad32b46c099419037d148e2ba57a2682bbc74deafabde1a97ee48bd64df3e42f09b61bc068d751c7c74330f693be0142df07d136fade077ebf6bbc65d3759de0a9aee48bd64df3138091be3f323eff8ca98e328eb31835cf240f9ae1375568cab6bf98043c133df078aa67b81faab5ea34c1aa5312cae0b38db51eea59047e69dd345f0bbe7d6c73d482f6c9c32d2d4aa0cc42ebf8314a475a878edff18ebaf8d2719cc533cee17bb2671d69ddd4274ece83ef3acb778de55bb76d8c313d656bdb75c05cef8159af774afceb0ddbf654b32e8a67f25303754a830671d5097d1759eb267b09e49b06dfcd407ad0be93d8753bc2d8895a6e92b55c12ca4c76d43f1d73fda7583cb88df5a48f1b5e84e34a0fed218c81c91607cdd780765322b49b0cda5119dcf75679d2aedee2a1f92ae0a1e3ab5ab0d1710a7ee392fe9fca03b7ddefd53ab8c986df3cac72308e8f9f313cceaab218697e3c3092ad1e78ea3c69666febe1963e784cd0db2a43cb964099fdb05f4e38ca86cf1d17b5d58bbea5f9498cf5d2ebede5412ffcce6700fa04968634114369d0f62dd038791e08dabef5b97bcfce5deb36352f6bcedcf624b4120b137f8b1cd528061be67b386c41d0fe93a62560a34f9af6045bb1250b7e4a95cad3a7137dc8857ad0ba4b2cce526089d3377e0e96a66ca1d31b787c84b20e1dfa24ac099dc65d5bf634637cf4b4383b133bfa7f3db2948b5a17c5418987ba2313ad9be6c99fd6873e8ffbfabaa66dd3766ddabba3f9b53dbb11d66e5c982fb244b07f5dcb60906063a2f5f4b4c4e913bf3835d8786dbe00fc05c012189ed2f879c240a56f0837addbbe7dc9def5dbb734cddefb5ad39e2d3b5f43457b5bca45a96d37793db9ba3a2c6b97efe5b0d9137eb1b937d8e88bcda56023ff7dc0461c0fc0ffec2de1a54d0c83f55318ebff95980af73215a210a4dd90ee4f749bd1af4dd5bb7ffd8968fd4968bdf9f4dbe2f4279ef5279df5279cf5279bf5279af52799f5db24f413defac8614890f984f29341e615b14383cc2790f5278f9f09da3e69aca7df055efd09637da8a13f51ac3f49fc7c90b954383ac8bc564dbfc6421fb2ea432b7d98a74f6bf421b83e2dd7875efa7281be74a40f63f421a23efcd1872cfa105c1f7a4f355a4f0b329f34d79f309f19643e51ae3f49ae3f413e37c87c627cbe4a0b82cca7b6170599cf07ebcf87ebcf76ebcf79ebcf7cebcfcfebcf82ebcf85ebcf88ebcfcceb4f0feb4fd0af0e329fda7e29c87cb6f89520f399e3b541e6b3c8eb83cc6794370499cf2eebcf31ebcf346f0e329f75d69f7bde16643e0fbd23c87c4e5a7f665a7f7e5a7f965a7fae5a7fc65a7fde5a5f72d7b71af425787d795b5f7ed5b740f4ad1f7d6958dfb2d4b770f52ded962033e4e150901912a38708e921537a08991e527722c80cb9d44350f5905c3d44590fd9d643d8f5907efd88837ee4433f02a31f09d28f48e947c6f42374fa3148fd58a17e4c563f36ac1fa3d6977df523e8fa56a0bedcdb1a642e09df09329f5ffe9c4a9f57e9fb54fa824adfafd20fa8f4832afd904a3facd21755fa11957e54a51f53e9c755fa09957e52a59f52e9a755fa19957e56a59f53e9e755fa0595bea4d22faaf44b2afdb24abfa2d2afaaf46b2afdba4abfa1d26faaf45b2afdb64abf1364e2f1f754fa7d95fe40a53f54e98f54fa6395fe44a53f55e9cf54fa7395fe42a5bf54e9af54fa6b95fe46a5bf55e9ef54fab24a5f51e9ef55fa0795fe51a57f52e9ab2afdb34a5f53e9eb2afd8b4adf50e99b2afdab4affa6d2bfabf42d95fe43a56fabf49da0ed33e5d8790c363dce5033bf6ecf9ee61dafefa9d8b3b362c7deed7bb6bcbefd8d8a7d5bf66caed8f9d9e65d1bb7efdc870b7fd92cfcb8999fb66bd7ba372ab6bcb6a1797fc5cebd7b2a766eac58bf73ef6b1bdaed2cffb75968f0dd1ed76dd810edacb4c7a7202debd139a783cc72f4a5fa79d9ebf6448f4e08f24c67169adbc90acd357b203a0d5b9e39e6abd8bd7de79e8aca8ad7d45fb573ddb9af79c3980afcdf6e25f2ee3d15bbf7acdbb5a762e3ae9d3b2aaac6e07a17f6e94425bed8c70f4c6ff35ea24e85ca6f0eec444dbe36b0739be33f3f0de9ffeca4d3b2419da861ffce2c347e50e708d3832265d9bd77fd9e5deb9af6442f3cebd32cbca033d55cddc96af619dc0967e59d5968f4e0ce112ee88cb37d39380bfe3f4095c818d4550500", "isInternal": false }, { "selector": { "value": 2603445359 }, - "bytecode": "0x1f8b08000000000000ffed9d077815c7b5c7efd54582ab2b01a6096424ad2aa24b028c316084e9cd0df70a06516c40188471efbdf7de7bc1bdf7827b27cf7e71123f3bcdce4b9ec94b5e122771e2e49dd93b07fd19966bedc70cda0b67bfefcfee9edd9df39b3367677767579775b1582c1e4b4f09528fd8a6136f6fd4f3ba2d9bea2d9655e792339e259c3959c299c812ce0e59c2999b259c7959c2d9314b383b650967324b38f3b3843395259c0559c25998259c9db384b34b967076cd12ce1db284b35b967076b7c8590c9cfcccd453cf7be979919ef7d6f33e7acec7eea8e77d755d3be8f5125229a98ce4e96d1c98725205a9925445aa26d590fa916a49fd4903480349834883494348437519eae1ab81348c349c3482b41369246967d228d22ea4d1a431a4b1a45d49e374ecc69376234d204d244d224d264d214d254d234d27cd20cd24cd22ed4eda83b4a7ae8ba7ebb217696fd26cd23ea47d49fb91f6271d403a907410e960d221a4434987910e27cd21cd251d419a479a4f6a222d202d242d222d261d493a8ab484b494b48cd44c5a6ec4fc68d20ad24a528bc1b98a740c6935e958d271a4e34927904e249d443a99740ae954d269a4d3496790ce249d453a9b740ee95cd279a4f34917902e245d44ba987409e952d265a4cb495790ae8c6ddcfe5791ae265d43ba96741de97ad20da41b4937916e26dd42ba95741be976d21da43b497791ee26dd43ba97741fe97ed203a435a407490f911e263d427a94f418e971d213a427494f919e263d437a96f41ce979d20ba417492f915e26bd427a95f41a692de9755d971c5d9737486f1ab6b7486febe577f4fc5d3d7f4fcfdfd7f30ff4fc433dff48cf3fd6f375aabcc2f4b2ba1735c736948dcfd938d8f8fccd011b9fcb09b0f179dd016c7c8ee7828dcff73cb0f1b9df116c7df57227b095c032cf4bf5723ed8caf4720a6c9e5e2e005bb95e2e045b855eee0cb64abddc056c557ab92bd8aaf5f20e60abd1cbddc0d64f2f77d7738e859a1af5bc6e0b2755a6e56b469d62e73ce801f5e13ce80936ce835e60e33c28021bd7bd37d8380ffa808df3a0186c9c073b828df3a02fd8380f307f380f4ac1c679500636ce030f6c9c07e560e33ca8001be74125d8380faac0c679500d368e6f0dd838be9c3f2a9e93613b4f78aee27826db783b9eab0928936dbc1dcf55de8ee72a6fc77315b7f39cb7e3b9cadbf15ce5ed785ef2763c07b90df17ce363ba838ddb10f393cbc15ce436c4bce3b231c7b80d31c7d81fe618b721e61833608ef139e2818db930c7f81cc11c6356ce3155d73ce06dd4f3ba2d9beab1efe6296eac37c232fb572c7dedb2d4a580a52ff829b5eb67185e73da52e75260f12cd719af6b6d61f180a5dc2e8b3f865961b74cbf4d39d6786eb09f12a84fa5e5fac4c10f97cbebec2b05360ff82a03f8aaecf235c4c10f97cbeb55c0c7b67277b1aac3fe8acb56d789c3c1a7e5bea74ed59fcf731ee76706f695807d9614b672cdd3b67cd85e0c363e1efb6dcfb0b93887f0998acbe5f572e0e33ec5dbba7c0d6de52b33f81cf47d7eacca0c16f16bbdcdebb07c75eef0f9c27e12b0fdbb78eb7eab81a9d82e5343d86b303e5fdabd46d5d7e1b9d716960a6071710db6ddb73bb876f939550d31f1f41cafabbcbd0ae2556d395e99aea1c827acc22aacc22aacc22aacc22aacdb372b8e4b797abeb9719ff6e2db5ae33e3c268de33e6f834fcfaacf7a7fdca7d828bfc8688b04ecf353e0e2f7a238ee83633cc586cdc1f8713df273b9bc8eef2d790c0aeb6af939da67d9d160d976fd36cc536596592db3be4ebd6fc277d365463df03d4f1fc3a672f2fb786b7d3dab6ce1dfcf78b15616dbe348f87ec65d9fd45087e3f639b18dfb874af06b694ca39e1794df6a237eccc1be12b0cf577a5e6897670357a6f14287d74f3f0e55e0d78bb59e1bf82edbbc96abe36a80cb83f85543fc789ff57aaecea14be11cb23de61d767c0f73db6e9b36d4e1bbafb6b0603bdb7e3fe6227754993596cb5465f4839898399582ed987ffd2cc70bfb072e97d7914f5885555885555885555885555885555885555885555885555885555885355b58158b6770e2f8bf17013eb6e1fb21db63dbf8b75a5cb67a777132bcbba8b0ea33fd2e0cdf4778b14dff5e2c01fb3c03df6f9fae97f361bba7e7f8ad8307e5bb7887f5437fe3921fdbf4ef725cbcefc0f78a5ceeb6eb37fdaedcee39d0b0e15d39e79379dee1df2d151b367ccfa7dadcd376fc7ea3c2b0b5577be0395301365ec66f1cecc6b8dec53b34fff708fb413b70ddd84f02b6df007dc84df1d6b631fb0bb57d4dc0769ee2c67a232ce37bf6fe76ebeaf79903a0fc46f0817e07daf55b8f7ee35aec83ed09587e000234b07571437c9959e55d6dc07eb85c691c9382edb58eebdc1f381a619d7da93cb915726a0d5c2f6d5f6fb0be189722880b6faf80b8d83edf5415f1fece03861a60293138f1be0afbc05a077c9bbbafaa053ef31b0ffc5e10fb13fc5ed0e53d508e114b6c434bd7898dbe07c2ef2fca81837d25609f97745eabef81ccfb1e0f8eed0d656e8d6f98cc6b337ec3b41698e51ba6e06f98cc6f73f11ba6f7a05ffb16ee6d2ac02ffbaa326c0eea5d6fd6bb11d6d917dedb60bdab36536ffc2d0617fd2473e51a1c786fc2fb7c0af9aa26ec63f9fb53bc87339f15eddf6f34f8f76b03ac9699be8ee1f593db0bef2378fbe790835fc0fd18d7b902ca591fb09da74cf76bfd217e83edd6d53f578740f98de003fd0eb5ebb71efdf2fd1afb607b0296bf81000d6d5ddc105f6656793728603f5cee671c9382ed831cd779307034c23afb5279f20bc8a9f570bf66fb3e04eb8b71e90d71e1ed3836e619fbab7ce6f3c183f8d93e2ff19e9ecb35eff183eebdf1fa60ff1e29cd550e5c5e2cf87785d8560e5c387e65f9ef04eaf09bf962f089dfcc47e5378d70cc2227d6ca57e280af6f08be12e0e3e312c067f7ef21d27ca521f8f077f9f0ef2298afdc019f1782af1cf8f8b85ce0b33dbe14f61befa0df22ca83b9ed7b44bc176d0b1ff6bb7c5c47e0b33de68fbfafd8163e7c0fc0c775023ecbe34b3e5f6d083e1c93e1e392c0677b4c46953d2004df40e0e3e3f281cff2fd9ecf3728041fde230d8265e6b37d8fa4f88684e01b0a4c7c5c01f0d53be0ab8bb59daf1ef8f8b842e01be680af2104df30e0e3e33a03df08077cc343f08d003e3eae0bf08d74c0b75308be91c0c7c77505be510ef8760ec1370af8f8b81d806fb403be5d42f08d063e3eae1bf08d75c0372604df58e0e3e3f03786c739e0db3504df38e0e3e37a00df78077c8d21f8c6031fdbf1fa3bc101df6e21f826001f1fd707f826d9e5f3ff1e726208be49c032d52ecb70c5323904cb5460996297c5ff7bc86976cbf4c706a75b2e5395310362c2f163f6146c9f0ef19a61395e71f0c9e5f23af209ebf6cdaa58261a9c49d86f6204f8d836c5214bd2605153a6be2e880fdb72965d3effba303304df2c60d9d32acb307fdc70f7102c7b02cb1e5659d2d785bdec96e9f7e17b033fd795fda4603bb6f9de96eb16079f5c2eaf239fb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb0da67552c330dce24ec3733027c6cdbc3214bd2605153a6ef4482f8b02df7b1cbe77f53333b04df3ec0b2bf5596f4ff3db16f0896fd81653fab2ce96f6a0eb05ba6ff4dcd81c0cf75653f29d88e6d7ea0e5bac5c12797cbebc827acc22aacc22aacc22aacc22aacc22aacc22aacc22aacc22aacc22aacc29a2dac8a65b6c19984fd6647808f6dfb3964491a2c6aca34ce1ec4876d79b05d3eff9dc44121f80e0696c3ecb2f8bfff70480896c380e550bb2cfe3b89c3ed96e9bf939803fc5c57f69382edd8e6732cd72d0e3eb95c5e9f037661ddbe5915cb41066712f63b28027c6c3bd4214bd2605153a67e694e001fb6e51176f9fc3e7c6e08be2380a5c92a4bfabdf2bc102c4dc032df2a4bba0f5f60b74cbf0f5f08fc5c57f69382edd8e60b2dd72d0e3eb95c5e5fe8ceaf5fff453f50ff45011c8bb662fd91afadacd3b38855e22a7195b84a5c25ae125789abc455e22a7195b84a5c25ae125789abc455e22a7195b8b69d55b1cc353893b0dfdc08f0b16dbe4396a4c1a2a64c63f7417c987747dae5f3df732c0ec17724b02cb5ca92fe4deaa342b02c0596255659d2ef3996d92dd31fe76f067eae2bfb49c1766cf366cb758b834f2e97d7916f5b645d9845ac92036e5825078455724058250784557240582507845572405825078455724058250784557240582507845572405825078455724058db3b0714cb62833309fb2d8e001fdb963864491a2c6acaf49d48101fe6ddd176f9fc6f6a9687e03b1a585a1cb0ac08c1d2022c2bedb2f8dfd4acb25ba6ff4dcd31c0cf75653f29d88e6d7e8ce5bac5c12797cbebc8972dac8a65b9c19984fd9647808f6d2b1db2240d1635653a7f82f8b02d8fb5cbe79fdfab43f01d0b2c273860392e04cb09c072bc5d16bfaf39d16e997e5f7312f0735dd94f0ab6639b9f64b96e71f0c9e5f23af2650bab62596d702661bfd511e063dbf10e5992068b9a329d3f417cd896a738e03b3904df29c0777200df690ef84e0dc1771af0f171f9c0778603bed343f09d017ca7c332f39de580efcc107c6701131f57007ce738e03b3b04df39c0c7c71502df790ef8ce0dc1771ef0f1719d81ef02077ce787e0bb00f8f8b82ec0779103be0b43f05d047c7c5c57e0bbc401dfc521f82e013e3e0efbbfcb1cf05d1a82ef32e0bb3480ef0a077c9787e0bb02f82e0fe0bbca01df9521f8ae02be2b03f8ae71c0777508be6b808f8fc331aceb1cf05d1b82ef3a60b9de2e4b5d0a58ae073f373aa8f30db1b6d799fda7e038e4bbd901df4d21f86e06be9b02f86e75c0774b08be5b818f8fc39cbedd01df6d21f86e073e3e0efb843b1df0dd1182ef4ee0bb2380ef6e077c7785e0bb1bf8ee0ae0bbd701df3d21f8ee05be7b02f8ee77c0775f08befb81efbe00be350ef81e08c1b706f81e08e07bc801df8321f81e02be0703f81e71c0f77008be4780efe100bec71cf03d1a82ef31e07b3480ef09077c8f87e07b02f81e0fe07bca01df9321f89e02be2703f89e71c0f77408be6780efe900bee71cf03d1b82ef39e07b3680ef05077ccf87e07b01f89e0fe07bc901df8b21f85e02be1703f85e71c0f77208be57808f8fc3fbbfd71cf0bd1a82ef35e0e3e3307eafdbe5f3dfb9ac0dc1f73ab0bc6597c5ffbf06de08c1f216b0bc6997c57ffff3b6dd32fdf73fef003fd795fda4603bb6f93b96eb16079f5c2eaf239fb06edfac8a65adc19984fdd646808f6d6f3a64491a2c6acad42f05f1615bbe6797cfefc3df0dc1f71eb07c689565b8ff1b3cef8760f910583eb0ca92eec33fb25ba6df877f0cfc5c57f69382edd8e61f5bae5b1c7c72b9bc8e7c6d655d9845ac125789abc455e22a7195b84a5c25ae125789abc455e22a7195b84a5c25ae125789abc455e22a7195b84a5c25ae125789abc455e22a7195b84a5c25ae125789abc455e22a7195b84a5c25ae12d7b6b32a96770dce24ecf76e04f8d8f6814396a4c1a2a64cdf3907f161defdc82e9fff4df8ba107c3f02964fadb234f8df84ff4708964f81e513ab2ce96fc2ffd36e9975aa8c1f033fd795fda4603bb6f98f2dd72d0e3eb95c5e47beb6b22ecc225689abc455e22a7195b84a5c25ae125789abc455e22a7195b84a5c25ae125789abc455e2ba6dc655b1ac333893b0dfba08f0b1ed13872c4983454d99c6d983f830ef7e6297cf7f27f15908be9f00cbe7565986f9ef247e1a82e57360f9995596f43b89ffb25ba6ff4ee20be0e7bab29f146cc736ffc272dde2e093cbe575e4db1659176611abe4801b56c90161951c1056c90161951c1056c90161951c1056c90161951c1056c90161951c1056c90161951c1056c90161951c10d6f6ce01c5f299c19984fd3e8b001fdb7ee6902569b0a829d37722417c98773fb7cbe77f53f36508be9f03cbafecb2f8ff7fdf2f42b0fc0a587e6997c5ffa6e6d776cbf4bfa9f90af8b9aeec2705dbb1cdbfb25cb738f8e472791df98475fb66552c5f1a9c49d8efcb08f0b1ed970e5992068b9a32f54b417cd896bfb1cbe7f7e15f87e0fb0db0fcce2e8bdf87ff770896df01cb6fedb2f87df8ffd82dd3efc3bf017eae2bfb49c1766cf36f2cd72d0e3eb95c5e473e61ddbe5915cbd7066712f6fb3a027c6cfbad4396a4c1a2a64cfd52101fb6e5efedf2f97df8fa107cbf07963f3a60f9df102c7f04963fd865f1fbf0ffb35ba6df87ff09f8b9aeec2705dbb1cdff64b96e71f0c9e5f23af2650bab62596f702661bff511e063db1f1cb2240d1635653a7f82f8b02dffe280efcf21f8fe027c7f0ee0fbab03be6f43f0fd15f8be0de0fbbb03bebf85e0fb3bf0fd2d80ef1f0ef8be0bc1f70fe0fb2e80ef7b077cff0cc1f73df0fd3380efdf0ef8fe1582efdfc0f7af00be78dc3e9f0994898ffda76047e4eb6097cfbf7fc809c1c7fe154bc272ac5499b976cbac5365e6598e992aa3230489e3970b6dc7dbf3205e1d2dc72b0e3eb95c5e47beb6b2f68cb52fab03bf0d05b1f47d4d8ee18bdfb9205327bddc01ec7ceea9d524c74eaff3fed7eb7d12b0cfb0647a5ea863cc530ec438e920c63835c27212fb153df589104b518458ba4488a520422cc908b1e44588251121965e1162e91a2196c208b1e44788a56384583a4488a577845872e3d161e91ca1b8a422c4d229422cb9116289b7334b32b6e9f36c12b6e7c27e39c6b12a8ef716b66e4f697b0e9453a06d8980b2535076be5e2e886f7a2cc628e52046e8a711d6d9573e3014c4db9f2537422c9d22c4928a104be708b1e4c6a3c3d23b4271e91021968e1162c98f104b618458ba4688a5578458121162c98b104b32422c051162e9122196a208b1f489104bce5662e1fb7e2e37df60694fbf8576fdfadfea7406bffc1c54087167ff9d81a3b35d8e119b7bdfd2c5419c716a8465f6b5b9f72dedcd52142116ccc9f666e912a1b814448825192196bc08b12422c4d22b422c5d23c452182196fc08b1748c104b8708b1f48e104be708b1a422c4d229422cb9116289b733cbe6deb7f0767c4fd2d5781650b61d8ce7147c2f833eb89cae60e33e84cb50edf278e1a60cf8fea65b00171f8ffed84fb7f8a6c7ba8e7937e379b69bc187ef6fba39be976e0b4b6e84583a458825152196ce1162e91d21960e1162e9182196fc08b1144688a56b84587a458825112196bc08b12423c4521021962e1162e17bcf28b01445282e7d22c49213c0d2c32ecb707c66e0c958dde819a807b074b71c1755664fbb65fa7f1bd5cb7299aa8c220812c78fd953b0bd17c4abc8411ef58c6fdc4ebc8e7cc2ba7db32abfbdadfa4dff7f833d43f41bbd1dc64095d9c7c1395e0c15e2baf681f62d0e68df6207eddbc7685f5e473e61155661155661155661155661155661155661155661155661155661155661155661155661155661155661155661b5cfaafcee68d56f83ffcd05fa5593b1bac1570cfcbb88812ab3afdd32fd6f2e4aa0425cd7bed0be2501ed5be2a07dfb1aedcbebc827acc22aacc22aacc22aacc22aacc22aacc22aacc22aacc22aacc22aacc29a2dacca6fa95dbffedf17a35f3519ab1b8d59973a8c812ab3cc6e99fe98b50715e2ba9641fb7a01edeb3968df32a37d791df98475fb66557ecbadfa4dbf972a0b718e973b8c812ab3c2c1395e0915e2ba5640fb5606b46fa583f6ad30da97d72bddf9f5eb5ff503f5af0ae0a8da8af547beb6b2f6ca225689abc455e22a7195b84a5c25ae125789abc455e22a7195b84a5c25ae125789abc455e2da7656e5b7daaadff46f62a25f3519ab1b8d83573b8c812ab3c66e99fe38703fa810d7b506dab75f402ef673d0be3546fbf23af26d8bac9512d7ed9e55724058250784557240582507845572405825078455724058250784557240582507845572405825078455724058250784b5bd7340f9adb5ebb72169f85593b1bac1570cfcbb88812ab3bfdd32fd6f2e064085b8aefda17d0704e4e20007eddbdf685f5e47be6c61557e073ac8c5fe217271a0c318a8320739c8c5c15021aeeb2068dfc101ed3bd841fb0e32da97d7912f5b589360cb89b5da787b026c43b4ad03d8866a5b2ed8eaa04e6cabd7b68e606bd0b64e601b065c3c1fae6d7dc03642dbbac0fe3be9e5ee601ba9977b826d67bd5c04b651ec036cbbe8e562b08dd6cb7dc136462f97806dac5e2e03dbae7ad903db38bd5c01b646bd5c05b6f1c6b555d97633ae71ca36c1e8f7946da2d1ff28db2423ff946db25ece8fb5daa640ceb26daab615806d9ab615826dbab67506db0c6e37b0cdd4b6ae609b15c0c7f939086c9c9f98cf9c9f43c0c6f939146c9c9f7560e3fcac071be76703d8383f315f396ec3c1c6711b01368edb4e60e3b88d041bc76d67b071dc46818de3b60bd876d0b6d160eba66d63c0d65ddbc682ad87b6ed0ab69eda360e6cbdb4ad116c45da361e6cbdb56d37b0f1b93c016cc5da36116c3b6adb24b0f5d5b6c9602bd1b629602bd5b6a9602bd3b66960f3b46d3ad8cab56d06d82ab46d26d82ab56d16f46ff9c0c875ca87ba302bfa665b1ef86ed4f3ba2d9bfc54663f5c2eaf97031fc7cbdbba7c0d6de52b33f8fcdf9bb0cb528f6dcf53dc586f84e54a60a9b0cce27f9b6db74cff3eaa1af8b9aeec2705db7b42ddaa2dd72d0e3eb95c5e47beaa0056ee77544e78c67e0e6296fe6d1b83b52cc06fed568811f72bb58efdd6187e4b0dbfea3cc1765253a6f3a40678fb59e6f59f7ded96e9df120c00e646f0510af68196eb827ee35aec83ed0958be9a6f1c603f35f1b58699d5b9521bb01f2e571bc7a4607bade33af7078e4658675fea9eee82c25606cb39efb777adc1c0eba560ef1f10af5a88176ff7c0c6f700d8c796186524a11cbcd65aceebfa4cf5c476675b0df0f50fe01b6097af21532e0c003eb6f5031617fda0c9c2d71eec077b19f153b97a3870252c73e5c55a9f5d6c9589cf4d3c65eacff3609e6b99453d6ff173d3ca96e615731736eddd34777e1cb03a1888398086cb387cc18f76387cc18f76387cc1c7e3500597d309b6a9657ea46a5abab865df654dcbe6ad386e794bd3fc99cd0b3178b906cde628912e0fbc35ea79dd964d0df8d0cb53a646ee042c1dedb2f8499cb45ba67f739b0ffc3800a5a6146ccf857df22dd72d0e3eb95c5ecf77e7b78eeb98a9fea9008ed456ac3f0e24250338793b9e7d3830c9f384519edadfcc656b15ea0165c635900250276b6eacf504e9146b1d0952606aa447ddb4a8911c3572a3466ad4c88cea36ba43992fe9b9f2a39ebad415458da4a891133552a2ee20d41d9dbafb57575f7547a29e40bc58faa9483d79aa27517587a1ee28d4555b5d19d5554a5d95d49553dd490d220d260d210d557121d5931a48c348c34923483b91469276268d22ed421a4d1a431a4bda95344ec7773c6937d204d244d224d264d214d254d234d274d20cd24cd22cd2eea43d487b92f622ed4d9a4dda87b42f693fd2fea4034807920e221d4c3a847428e9b058fa0a3b8734977404691e693ea989b480b490b488b4987424e928d212d252d23252336939e968d20ad24a520b6915e918d26ad2b1a4e348c7934e209d483a897432e914d2a9a4d348a793ce209d493a8b7436e91cd2b9a4f348e7932e205d48ba887431e912d2a5a4cb489793ae205d49ba8a7435e91ad2b5a4eb48d7936e20dd48ba897433e916d2ada4db48b793ee20dd49ba8b7437e91ed2bda4fb48f7931e20ad213d487a88f430e911d2a3a4c7488f939e203d497a8af434e919d2b3a4e748cf935e20bd184be7ebcba45748af925e23ad25bd4e7a83f426e92dd2dba47748ef92de23bd4ffa80f421e923d2c7a475b1d6ce184fe05feb393ff5cf6d69695ababcc56b69f696ae5ad2b278f992e3bcd58b5b1679cdc734ad58b0a479351efc627c0b0e7e8dc7f8373d78eefcf99b3fee13bdc267f6b465f39b8ef59a57b578cd0bbc239a572d9bbf12776fd0ddd918bd3e3b7dabe3ad5cd2dce2d579cbe8dfb94bc845d3fc211e6e5b495558d9e2ad6c99bba2c55bb0a279a9573fe4ff01285f3937f75f0200", + "bytecode": "0x1f8b08000000000000ffed9d69741cc5b5c77b24595e46832d5bde37b1056fb246a3dd968d8cf70dcc8e018317c960b02d638b7d271b092121fb4202bcac2421fbbeef09d9f7852424908484247c7839efbdf3ce791f38afaa5537fa4f51dd6886be72b5e6f639d7537d55d3f7776fdfaaeea9aa6e3f1304412618daaa959c143c77a3bff79acffc0bdb5a123c569e93339312ceaa947056a784b326259ce352c2599b12cef129e19c9012ce8909726ab6aaa0784b9a7712435c9366cca62ca6752988692e65313d2105319d1ca4a38f9a9212cefa94704e4d09e7b4947036a484737a4a3867a48473664a3867a58473764a38e7a484736e4a38e7a584737e4a3817a48473614a381b53c279624a384f4a09e7c929e13c2541cec5c079aaf97c91f93ccd7c2e329f547789f95c6a3e97191f6bcc7e9392e54a9a359ff5373dd15050d2aaa4cdfa5bbb920e259d4abaccdf1acddfba95ac50b252498f92554a562b39ddc4628d923394ac55b24ec97a251b946c54b249c966255b946c55b24dc97625672a394bc90e25672b3947c9b94ace5372be920b945ca8e4228b65a7928b955ca2e45225bb945ca6e47225bb95ec51b257c93e257d4afa95ec577285922b951c50729592ab951c547248c96125034a8e28b946c95125c7940c2ab956c9754aae57728315b31b95dca4e46625b7589cb72ab94dc9ed4aee5072a792bb94bc58c94b94bc54c9cb94bc5cc9dd4a5ea1e4954aee51f22a25f72a79b592d728b94fc96b95bc4ec9eb95bc41c91b95bc49c99b95bc45c95b95bc4dc9fd4ade6e58a821bc43c9034a1e54f29092ff50f24e25ef52f26e25ef51f25e25ef53f2b092f72bf980920f2a7944c987947c58c947947c54c9c7947c5cc927947c52c9a7947c5ac967947c56c9e7947c5ec917947c51c997947c59c957947c55c9d7947c5dc937947c53c9b7947c5bc977943caae4bb4abea7e4fb4a7e60c5fc874a7ea4e4c74a7e62fe46e34b3f55f23353feb9f9fc85f9fca5f9fc95f59d5f2bf98da57b4cc96f2dddef94fcde941f379f7f309f7f349f4f98cf27cde79fcce79fcde75fcce753e6f3afe6f36fe6f369f3f977f3f90ff3f94ff3f98c92fe86a1f2846078eb0d12ea93dafafbf4dc0405fbd4a078d3b1a8367fa3cf46a3af31fbf449b11b67f6c759fa5ab35f6b1d6782d99f60e9ebcd7ebda59f66f6a759fae9667fbaa59f69f667823e1bc018a5d16b5db551654047795805ba7141714cb4ae960e07baf141712cb48ece632de8261add78d04d32ba09a0cb1add448a99923aa3eb0d92ca89fc1e7ddc5cd2c735f3362724cfbb4f1f773213ef94e479fbf571eb1978757e4c35c79a027933cde8ea4167ba95602ae8a61bdd34d0cd30ba06d0cd34bae9a09b6574334037dbe866826e8ed1cd02dd5ca39b0dba7946370774f38d6e2ee81618dd3cd02d34baf9a06b34ba05a03bd1e81682ee24a36b04ddc9467722e84e31ba934047fde7c9a0a3fbbb538c4ef7093519f88ed1537f147e87fa5cd09d46fd2de816515f0bbac5d4cf826e09d826dd52e84348b7cce8a83fd27feb32e5de20a9fc2ff4e9e376277d5c75647ddc95c91f379cd3ea0986e3da0b76ba2156ab4c39c175332d683b6384ec90be06ca1ba12ed5a378d03585d8f5b5638529af8af95e97f5bd1cd459e1f0bf3748d6ff9516cf4a8b791cf8cf93b3ad2d92b323de4aced9f3a1ae9d7b747f331673760b7030e46cbbe4ec88b79273761fd4b5738fee71c762ce5e041c0c39dbcd93b385bce4ecd0585710b8738f7ee78cc59cdd0f1cc9e76cbbe4ecc8b79273f676a86be71efdd61d8b393b081cc9e76c67b7dc1b8c782b3967ef85ba76eed1b8cb58ccd9bb80832167fba49f1df15672cede0f75eddca331c0b198b3f70147f239dbcd94b3ad92b3c1d0bc6510b8738fc6a3c762ce3e001cc9e7ec3e199f1df95672ce7e06eadab94773236331671f018ee473b68f6b7cb620393bb45e2308dcb947f3746331673f6fca7a6eece7666e6c01e87e61740b41f74b586740ba5f19dd89e017431be8943630e2ade436f06ba86be7f249a63c16dbc00f80832167bb256747bc959cb34f415d3bf768fdc258ccd9df020743ceee959c1df15672cefe17d4b5738fd6d28cc59c7dda94f5fdc2e3e67e6111e8fe60748b41f747a35b02ba278c6e29e89e34ba65a0fb93d13581eecf46b71c747f31ba66d03d657479d0fdd5e85a40f737a32b80ee69a36b05dddf8dae0d74ff30ba76d0fdd3e83a40f78cd1751a9d9ec7a235558f1add04f0bd3748eedc86eba882e22d63edf74279192f4f3e17143f2740b696276fab55fbde148cdcf7e5c0d3cce07b166c8c84a71978f2c9f384bf475b923f6e788e9bac9866c15613f85560f02b03b6e8d8b44ff672a0c37ea3e0606c4d9eb190015b746cda6f0546d2613f46cfe150fbd17df3bccc302f435b0aafcf68af1738c85e0dd4c9340cd76d346c75f077ea03eaa08cfd7cded231e56a982bf870562fecb70023f9981f7dc6c248199b2d46ae7e2303b6e8d8b6ed3a477c74cc5a1d316b63626cb51869bf0d18297eada3cf581829a3dd2f30f5492d23ed93282ef9d18fd988ce6b0e7478afd7e6606c4f9e313caf6d1623edb70323e90ac0c3753d8c6aafbed8e6b80fc17ca66b165d7fc85e0dd469ad1eaebb09aea70c7d68a1d47b53ecd3933f4f853c5ecf46c2c37cee5a98f2318f7de7b341b2b966b7f9bc152b6cf3d89773f593517d39d91366611666611666611666611666611666611666611666611666611666611666ff99a3e6e55ceb198e2723e95a8087639c3f7cf7943916ce013d06f33ac9cf5b14f238574feb1817593ed7409dffcd0cb33dee58278173e7cb2d1dd33aa5f05ce23aa55ed8277bb86e03d74d31ac3d0979965a3cb6ed3a477c7c5c47e2d31a8da8755a3ec52c073a5c0fd7c4c41395674d0edb8d89d92eece3693b85bc7ecf8f7e571ef527761bc1b56f4b2c9dee933aaa87fde6c88152e79df1ba41e524e77131dfd056f2eb6d0a45eb13aa82e26b05de5330ac51299aafa6b511ed96ed1aac5315fcfbdc74c0df7b83e7ae11c23a746cda5f04dfedb08e3d99cfdfd8feb01db8a95c6bf9b60cb8a9cea4aa611f3f67ca4cf733055c3f1b006f60f9441baecf48fe7e6f68bd48a1049e36e0e158bbc6745f9bc77c4c7abd4887152bd7fd32d56987f87530c42f6ecd1ad91366611666611666611666611666611666611666611666611666611666611666ff99f1fd17c48acf48b778c2384a6b6cc2f90c7a6f11ce8bdd5f356c977b0e90e69c165b3ee333ca4f570db33d68caf88e00d7f3ee782eb9e6d6a2ce25d9ab0b9efb9c3ed3b91cf1bb1fda1c31eb70c4ac9389d1ee3368bf1318297e1dc0c3d51edb2d1edb36f6196d9ec62caa9fe55abf129567ae750a8d89d91e5a2fc231af4beb45eceb578b15535c27413a9c07c777abe07a2cdfdeff62af5dc07e0ad76825df6f168ae680edb582640fd7497cc3c496d64924df0f14f29cd7086aa3b426a4e0f095ea3c0ad7b9ef9932ae156a81633de6f83b6d716b12b04f65785766787ee9dd8d747ebb1db657026b42b65bd076c608d9217d0d947f53355cd77e1724c59ad8751bb1df57e9fa5edefa5e0eea7439fcef0d92f5bfdbe2e9b69875eefc10f2ec31b8d7e3ea93ba02778c16418ca80edef332ac2972f691f69a695d87ceff78ab0ede9f529d27a18f8a5a93ee7a0f20d7fd42d47b00f17ec1754f63fb68af1daff4f580ff82fea203fede1bbcf0f580ff821c72dd97d2f117c3f1896b7c107d6da13aff635d47b9dad6f3bdf7caf5db8f7871bd21d5f93fe8ab969975b951bf635ccf5970fd6e887aee83ece13d5529be63bf90f4b511f31159c81ee6638d8935e5634704f772c777c7477c976245ebcbf177b21d3f1d87c4df116efa9b6ecb176a535de0cbbfafdfe00bcf3dd3d0fd67f2be16df0f511fd4eaf095ea4c8577c135987216ce13f695273bfe4e5bdcfd27bed7bc27799fc3f34befefa6f3dbe3b0bd1a5813b2dd82b6e9fe93ec90be06ca27550fd7a57a140f8a35b1eb3642f770c86e7fafddfa5e0eeaac74f8df1b24eb7f8fc5d36331ebdc99097976323c6bc1d557af8c88d1628811d5c1671deddffff85b1eaf31c7ebb73cbef313fbf66510d3d17a67aa3d7eebba3f596cc518ef4f5aa09fcd3aeadae3d2740d49727d3a3e0fb414ece2f3404b99e2990b8ae399b338386d4fb66c4f1e45dbf596edfa51b42d319798fb14739ffe2f0cfc3f2baa52c0589d02c69a14308e4b01636d0a18c7a78071420a1827a68071520a18b3c0783cafed0cf12978f6ff3dc5de6ba06d86f73984b158168c3c164dbc3cb1f73e689be11d2a25ff7f03ccff17564bb9ff17560ebe3735058cd352c0d89002c6e929609c9102c69929609c9502c6d929609c9302c6b929609c9702c6f929605c9002c68529606c4c01e38929603c29058c27a780f19414309e9a02c60929605cc2cb58289751f370bc47331b14afe37a3e1ee6f77a86ef2774bd4394e3ff9d2dd577e677fab694fb0e3c5cbfc0fbff28beb0f7f471ac4f28f53d7d71fff7341363a15c46aef526b8b665243cae3528795ec642b98c5ccf77e0f38623e171fd3fb8bccfdb0cc5ac1c46aef558a5ae17c4e7f0da1d3163602c94cbc8b5a61f9f371c098febb9c03c2f63a15c46aeb5af59b031129e2e8859a723660c8c857219999edd0a63d655020f3ee3d4e588190363a15c46cdb3822966dd25f0ac8098753b62e61323f224fdbef16e872d8e67e24af59d189071620a1827a58011d72070f45f716b10ba79e35328373e5ce72b6e0d02da667806238c05aeb97fbe58f4f0f2c4ae4140dbab986281cf443c5f2c56010fc7331a59b031121e62c8c1f7a6a680715a0a181b52c0383d058c3352c03833058cb352c0383b058c7352c03837058cf352c0383f058c0b52c0b830058cf85b95e15e31f6f7cbaa316e3beab7ca58b71df5bb64acdb963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf7db29d86317e611c7b8cc8d3981c4f1e7d475ba77be0fbe90e9e0c93ef68abd703dfa99c36c6d529605c91024689e3d01ac4721835cf1a269ede1278d600cf194c3c6b4ae0390378d626cf13e6d41925f010430ebeb722058cab53c028719438fac42871ac9c380aa3300aa3301e0fc634f4e1729d19faed520ea3e659973c4f18b3b525f0ac8398d1f7f2bc8c85721935cffae479c298ad2b81673dc46c9d23660c8c85721935cf86e479c298ad2f816703c46cbd23660c8c85721935cfc6e479c2986d28816723c46c8323660c8c85721935cfa6e479c2986d2c816713c46ca323660c8c85721935cfe6e479c2986d2a816733c46c9323660c8c85721935cf96e479c2986d2e81670bc46cb323660c8c85721935cfd6e479c2986d2981672bc46c8b23660c8c85721935cfb6e479c2986d2d81671bc46cab2366be32ae4801e3ea143032c7b1502ea3e6d9cec4b3ad049eedc0732613cff61278ce049eb392e70973eacc1278882107df5b9102c6d5296094384a1c7d629438564e1c85511885b134c6d353c028e75a187d6564f87d15fb7cca9963dc76d4f32963dd76d4f32963ddb6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e73ed9de91bced42a9cfb0ee009eb31862c1e4675e1ff76c73ac67138c9f8ed53956acceb46295833a6743fcce61885f06ecd2b1699fec95cafc220f98996c174e50c79808fe938dd5563cb4fd73997c8feaebcf1de3b6a3fafab16e3baaaf1febb625cf25cf2bc1b6e4b9e47925d8963c973cf7c536966b82e1fb767abf923ec679a63cceec53fdd3e17b54a765fcd0e7e440da10876d694372ada804db92e792e795605bf25cf2bc126c4b9efb99e7e7276f3b9c1bc3df177a8b9b1b3b1f78ce638805939f79edd305964fe75a3ee5a00ebeb3f602063f3360978e4dfb17c079481bb3e65965cac49a857aab3c6124dd79bc3c61fb5a15146f71edeb02e06168072d4c7e86edeb42cba7558eb8531dccd50b19fc74b51ddabf10ce43da9873608f58b341f139f5819174e7f3f284edab3728dee2dad785c0c3d1ff30f919b6af8b2c9f7a1d71a73a98ab1731f8e96a3bb47f119c87b4316b9e35f077bd65a1de1a4f184977012f4f5b167ca62dae7d5d043c1cfd0f939f61fbda69f9b4c61177aa83b9ba93c14f57dba1fd9d701e8459985dcc9ae70c5326d62cd43bc31346d25dc8cad396cf82cfb4c5f5633b8187a39f678a7bd88f5d6cf9748623ee540773f562063f5d6d87f62f86f3500af3ea14324b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9ccb63d63c6b4d9958b3506fad278ca4bb8897277c7e676d50bc65acfd5e285f0c3c3b19e2c3e467b8eefd12cba7b58eb8531d6c5f9730f8e96a3bb47f099c87529857a79059e25c1eb3e65967cac49a857aeb3c6124dd4e5e9eb01f5b17146f71fdd825c0c3d1cf33f919f663975a3ead73c49dea60fbba94c14f57dba1fd4be13c08b330bb9835cf7a5326d62cd45bef0923e92e66e52984cf21ae0f8ab7b87eec52e0e1e8e799e21ef663bb2c9fd63be24e7530577731f8e96a3bb4bf0bce4329ccab53c82c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c2b27ce9a678329136b16ea6df084917497b0f2b486f30e1b82e22d6ede6117f070cccb30c53d9c77b8ccf2698323ee5407dbd7650c7ebada0eed5f06e761ac33af4e21b3e4c6e8304b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e486304731fb901b9a67a329136b16ea6df484917497f2f284ef3dd818146f71eb762e039e5d0cf161f2335cb773b9e5d34647dca90eb6afcb19fc74b51ddabf1cce83300bb38b59f36c326562cd42bd4d9e30926e172f4fd88f6d0a8ab7b87eec72e0e1e8e799fc0cfbb1dd964f9b1c71a73a98abbb19fc74b51ddadf0de761b7300bb38359f36c366562cd42bdcd9e3092ee325e9eb01fdb1c146f71fdd86ee0e1e8e799fc0cfbb13d964f9b1d71a73a98ab7b18fc74b51dda277bc22ccc51cc9a678b29136b16ea6df184917497f3f214b2e0336d71fdd81ee0d9cd101f263fc37e6cafe5d31647dca90ee6ea5e063f5d6d87f6f7c279481bb3e6d96acac49a857a5b3d6124dd6e5e9eb07d6d0d8ab7b8f6b5177838fa1f263fc3f6b5cff269ab23ee540773751f839faeb643fbfbe03ca48d59f36c336562cd42bd6d9e30926e0f2f4fd8beb605c55b5cfbda073c1cfd0f939f61fbeab37cdae6883bd5c15ced63f0d3d57668bf0fce43da9835cf765326d62cd4dbee0923e9b09fa2ad0a18b7333106166360c507791678c633cb339ea99ef14cf48ca7da339ea59ef1747bc6d3e519cf42cf78167bc633db339e82673cd33ce359ee19cf24cf78da3de3a9f18c6799673ca779c6b3d2339e399ef13478c6b3c4339eac673ce33ce369f28ca7c7339e0ecf78e67ac6d3ea19cf74cf789a3de3a9f38c27e7194fad673c3b3ce399e719cf0ccf784ef08c67b2673ce33de3e9f48c67be673c6d9ef1ccf48ca7c5339e299ef1d47bc633c1339e459ef1643ce0c906cf5d379085bfef005d95f55d7d7dd9d030fc779aa7ad82eff49b72b5e3d87da0a379dd7ec777314e5c73cf68ab17f6c95e1d70f47bc2b3c8339e099ef1d47bc633c5339e16cf78667ac6d3e619cf7ccf783a3de319ef19cf64cf784ef08c6786673cf33ce3d9e1194fad673c39cf78ea3ce369f68c67ba673cad9ef1ccf58ca7c3339e1ecf789a3ce319e7194fd6339e259ef13478c633c7339e959ef19ce619cf32cf786a3ce369f78c6792673ccb3de399e6194fc1339ed99ef12cf68c67a1673c5d9ef1747bc6b3d4339e6acf78267ac633d5339e599ef12cf08ca7cac1b3838927ead9dd1d9ed866380f797ddcfd4c3e5d618e556b8e4bfc64af06ead49b81473ddf80df252e7bbe1dc796af801871bd372167f1d0febe316e7bb2657b7285d8aeb76cd757886dc973c9f34ab02d792e795e09b625cf25cf7db4fd6c72b6db31cfaac0960feba3e5fd49f13cf2fea4789e6acf78e4fd49f13cf2fea4781e797f523c8fbc3f299e47de9f14cf23ef4f8ae7f1edf978799f533c8fbccf299e47dee714cf23ef738ae769f28c47dee714cf23ef738ae791f739c5f3d479c693f38cc7b7f739c9fb93e279e4fd49f13cf2fea4781e797f523c8fbc3f299e47de9f14cf33c1339e459ef1643ce079bef727e17b8f68ade53ed0d17aceb8f72c65e13857808ec607e918fa7a7576c37319aae03b573ab8f63bec919d2b1ddf1d8db8a3ad5ed8277bf83ea62b3de159e419cf04cf78ea3de399e2194f8b673c333de369f38c67be673c9d9ef18cf78c67b2673c2778c633c3339e799ef1d47ac693f38ca7ce339e66cf78a67bc6d3ea19cf5ccf783a3ce3e9f18ca7c9339e719ef1643de359e2194f83673c733ce359e919cf699ef12cf38c6787673c359ef1b47bc633c9339ee59ef14cf38ca7e019cf6ccf78167bc6b3d0339e2ecf78ba3de359ea194fb5673c133de399ea19cf2ccf781678c653e5e0e17a27522e18de7a617f34dec7f47cb6f5fe52888bdeb2f0f7d1784e7287c548fbb8ce0079896729134fd473ef4b3db0adfda7df5a34679185bfe373385c39b5d462a47d574ee13ac2654c3c51cfeb2ff3c0b68e459329d31c7716fede048c5c39b5cc62a47d574ed5f3f2b465c167dae2d6f6609be338874c7ee6b1fd25f88e88bc8ed5762b564d56ac725067349e138cea0fc89e300b7314b3e6a1b11662c5ebd9683c273d1246d7f5958127ec1f9707c55b5cffb81d7838ae1f4c7e86fdd801cba7e58eb8531dccd5030c7ebada0eed1f70d86e0c928dc5552388c5550e9eab46391664af54e61d2964f621ce9a87d64e102bae276ef68491744b7979c2feb13928dee2fac7ab8087e3fac1e467d8275c6df9d4ec883bd5c1f67535839faeb643fb57c3792885f9400a9925cee5316b1e5a534dac59a8d7e20923e9b6b3f214f259f099b6b87eec6ae0e1e8e799e21ef663072d9f5a1c71a73ad8be0e32f8e96a3bb47f10ce83300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbcdac79e8591562cd42bd82278ca4bb8a956768dea110146f71f30e078187635e8629eee1bcc321cba78223ee540773f510839faeb643fb87e03c08b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3dfcc9a87dee94aac59a8d7ea0923e9aee6e5099fdb6a0d8ab7b8798743c0c3312fc3e46738ef70d8f2a9d51177aa83b97a98c14f57dba1fdc3701e8459985dcc9a87feaf0762cd42bd364f18497790956768feb42d28dee2fab1c3c0c3d1cf33c53decc7062c9fda1c71a73a98ab030c7ebada0eed0fc0792885f9400a9925ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e728668973e5c459f3d0ff5145ac59a8d7ee0923e90eb1f2b486f30eed41f11637ef30003c1cf3324c710fe71d8e583eb53be24e75b07d1d61f0d3d57668ff089c87b1ce7c2085cc921ba3c32cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc5ec436e689e0e5326d62cd4ebf0849174877979c2f71e7404c55bdcba9d23c033c0101f263fc3753bd7583e7538e24e75b07d5dc3e0a7abedd0fe35701e8459985dcc9aa7d39489350bf53a3d6124dd002f4f210b3ed316d78f5d033c1cfd3c939f613f76d4f2a9d31177aa83b97a94c14f57dba1fda3701ed2c6ac79ba4c9958b350afcb1346d2e175b98b892767f1e41cb1385eb6f57eb729d799cf2cfcbd1b18b9fac32e8b91f631c7919778ba9978265b3c931db1385eb6b5ff2b4df904f39985bfaf0446ae9ceab61869df955393816725134fbdc553ef88c5f1b2ad63d163ca53cc6716fede038c5c39b5d262a47d574ed5034f0f134f549fd4330ab6a3dad768d88eca95d1b02d318f8e3943bb0bc7077a82e22deebe1aaf2d1c7d15939f79d7f5bbc7f209afdf788f7abcae4fc22ccc51cc4cf7b96d59cb36c527b07868bb863916a3f93bbbdbf2290dbfb3e3980fa49059e25c1eb3b67d2c79db6d59cb36c527b078683bc61c0b263fc3fe603070c798ece5a00ee6e920839f19b04bc7a6fd41380fa5301f4821b3c4b93c666dfbdac46d0fbd7f186d537c028b87b66b9963c1e3e7507f705de08e31d9cb411dccd3eb18fccc805d3a36ed5f07e74198855998855998855998855998855998855998855998855998855998855998fd66d6b6af4fdcf6d0f83ddaa6f804160f6dd733c782c7cfa1f1fb1b02778cc95e0eeae039bf81c1cf0cd8a563d3fe0d701e84599885599885599885599885599885599885599885599885599885599885d96f666dfbc6e46d87cfe3a06d8a4f60f1d07623732c98fc0cc7ef6f0adc31267b39a883e7fc26063f3360978e4dfb37c17910666176316bdb37276e7b683e0f6d537c028b87b69b9963c1e3e7507f704be08e31d9cb411d3ce7b730f89901bb746cdabf05ce4329cc0752c82c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c2b27cedaf6ad89db6e0dc7efd136c527b07868bb9539163c7e0e8ddfdf16b8634cf6725007f3f436063f3360978e4dfbb7c17918ebcc0752c82cb9313acc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc3ee486b67d7bf2b6c3e7d9d136c527b07868bb9d39164c7e86eb5fee08dc31267b39a883797a07839f19b04bc7a6fd3be03cdc21ccc2ec60d6b6ef4cde76216bd9a6f804160f6d7732c782c9cfb03fb82b70c798ece5a00e9ef3bb18fccc805d3a36eddf05e7216dcc78fe32c9d90ed76d928d2af3a9752f36e56ad0bdc4946b40f752531e07ba9799722de85e6ecae3417737f846ba5798f212d0bdd2947b40778f29af04ddab4cb91b74f79a7217e85e6dcad780ee35a67c1474f799f231d0bdd6940741f73a53be1674af37e5eb40f70653be1e746f34e51b40f72653be11746f36e59b40f71653be19746f35e55b40f73653be1574f79bf26da07bbb29df0eba7798f21da07bc0947780ee41539e08ba874c7912e8fe03caf4f94e53ae03ddbb4c3907ba779bf209a07b8f294f06dd7b4d790ae8de67caf5a07bd894a782eefda63c0d741f30e506d07dd094a783ee11539e01ba0f99f24cd07dd8946781ee23a63c1b741f35e539a0fb9829cf05ddc74d791ee83e61caf341f749535e00ba4f99f242d07dda94f1fc7ec694ef041df51777818efa8b17838efa8b97808efa8b97828efa8b97818efa8b97838efa8bbb414779f70ad051debd12749477f7808ef2ee55a0a3bcbb17749477af061de5dd6b404779771fe828ef5e0b3acabbd7818ef2eef5a0a3bc7b03e828efde083acabb37818ef2eecda0a3bc7b0be828efde0a3acabbb7818ef2ee7ed051debd1d749477ef001de5dd03a0a3bc7b10748da6fc10e84e3465ec3f4e32e57782ee64537e17e84e31e57783ee54537e0fe85e64caef05dd69a6fc3ed02d32e58741b7d894df0f3aba867d00744b4df983a05b66ca8f80aec9943f04bae5a6fc61d0359bf247409737e58f82aec5943f06ba82297f1c74ada6fc09d0b599f22741d76eca9f025d87297f1a749da64cfd876ea7babd91cf148f3af0afc9c14dba09c0dd1b247b0f46b6e8d8b45f00468a77cbe8331646ca98b718354f1b43cc3087688bfb8dd3063cad0c3c4c7e86bf71da2d9f0a964f39a8f322f0b39dc1cf0cd8a563d37e3bd8e638e7188b5a73dcd3ac58d4409d59e6e2a5af937171a463e8fc6d71f8c215c7bcc59377d8ee628e231d9bfac4ae51b0dd61d96eb66c63bf4f5b5cdbee00e64e06667ddceee48f1bb6ed15e65894cf64a7197c5a093148ca27b49d314276485f03e5e686e1ba548fe241d74e62d7ed88ce25b2dbdf6bb3be97833a5d0eff7b8364fdefb678ba2d66fd3be19486610e86f610e64097c541fbcd10bbee88d87541eca80e5e7bf34cb1ebb478683f0f3c747fd50e3aba4f217ebc9f6b1a056ebbdf6b777093ae0318f30ec6e6e4190b71d7856660245d27f07430c5cc3ed7a759f1c17b82f1561dfa6e0dd45907d7e5aca3ae6e77f332c37ed1effa678364fbf45a8678e1984300f109ac18d2460c1382e1718924792605c3e30ec706078eeeb9a2ff9cfe3d7d1940abb130f133e370a30a7458ae76e882a0787805876f697805876fabacb0e0b00ed5d73fe3b45b3484d17fe8c0e0f987fb0fef3b7ae391c1febe6d035720f5388b1e49a33c4052d4d13621181e08ea0d929db8a9b56cc525cf04f81c9f3c4f0b939fe1456fa2e553ade5530eea8c83bf4d64f0330376e9d8b43fd1613bc18e288cc5a411c462928367d228c70207d349872d95fe8e132d55962fd8a2d1273bcf1375880c9e0ac7cf1838fd37ddd8c71967c607c3279b7a4f7d47ab4f821e85d5572d3dcaaa47557517a4474df5054d8f8aea51503deaa94739f5a8a61ec5d4a3967a94528f4aea51483dead8180c8d2aea51443d6a780a703d0aacfad7bcbe3aea513f3dcaa747f5f45d95feb5a6ef44f49db7be2bd07703faae4fffa2d5a31bfa4aabef62f4155a5f55f55da2be3bd477f3faee56cf66ad52b25ac9e926d66b949ca164ad92754ad62bd9a064a3924d4a362bd9a264ab926d4ab62b3953c959c1d068fdd94ace5172ae92f3949cafe40225172ab948c94e25172bb944c9a54a7629b94cc9e54a762bd9a364af927d4afa94f42bd9afe40a255706432b78ae5272b592834a0e2939ac6440c9916068464dcfa0e919333d43a667c4f40c989ef1d2335c7a464bcf60e9192b3d43a567a4f40c949e71ba23189a5dd0b3097af640cf16e8d9013d1ba047ffef0e8646f7f568fe3dc1d068bd1e9dd7a3f17af45d8fb6ebd1753d9aae47cff568b91e1dd7a3e17af45b8f76ebd16d3d9aad47aff568b51e9dd6a3d17af4f9a1606874598f26ebd1633d5aac4787f568b01efd7d38181addd5a3b97af4568fd6ead1593d1aab475ff568ab1e5dd5a3a97af4548f96ead1513d1aaa473f3fabe4734a3eafe40b4abea8e44b4abeace42b4abeaae46b4abeaee41b4abea9e45b4abeade43bc1504e7e57c9f7947c5fc90f94fc50c98f94fc58c94f94fc54c9cf94fc5cc92f94fc52c9af94fc5ac96f943ca6e4b74a7ea7e4f74a1e57f207257f54f284922795fc49c99f95fc45c9534afeaae46f4a9e56f27725ff50f24f25cf04c3b324d871d498de8646ecf70c0ef61f3a32d83838d078e8da8383078e1cbcb1f1fa038357360e5cd77f74ffc181ebf1cb5f375fa6e98835478feeb9b1f1c0e1befe1b1a07ae1d6c1cd8dfb877e0dac37dc7f04b4f982fcd7baec53d7d7dd1c6fef38590fe779946ab4d3f48133d9be37dabad2e232075e57c295f5d9e437973a5a1d9f97387ee701b8f1d1c186ccc371e56ffee39a8bed3dfb7bc11ff764c05f9d860e3b1c13d47071bf71f1d38d4d8b21c8f3ba5ae0c27663694f1a5b50d23f73cf87f8198955c01d50300", "isInternal": false } ], - "packedBytecode": "0x000000028df71de50000002a171f8b08000000000000ffed9d097c1d55f5c7dfcb4bd2bcbcecfbd2242f4dd3360d69f3d28d5ad4b8518a0b1444aaa2a55bb0d8a6d8262c0a8a8ab8af7545140515dc57dc1744511064535054dc4041f6b52c65f99f3bef1ef2cbcdf425f3e7de97137ae7f339c99d7367eef99e73efdcb96fe6ceccb5b1582c1ecb2e0992fad8c485f307f5fffea7b7642c96d5ef92333e43380b66086762867016ce10cea219c2593c433867cd10ce9219c2999c219ca5338433354338cb660867f90ce1ac98219c953384b36a867056cf10ce9a19c2593b4338eb2c72b60027ffb66bd0ff1bf5ff26fdbf59ffe77d5af5ffd9fa7f9bf6b550afb7937490a4493a751e07660e4917c95c926e927924f3491690f4902c24e9253980a48f6411c962bdbffa813840b2846429c93292e5242b480e245949f22c92552407913c9be43924cfd5717b1ec9f3495e40f2429217911c4cb29ae4109235248792bc98e425242f257919c961248793acd5bea4b52f47901c49f27292a3485e417234c93a925792bc8ae4d524c790bc86e4b524eb498e25d940b2916413c966922d244324c791bc8e642bc9f124af27d946b29d64986407c909246f3062be936417c908c9a8c17922c9492427939c42f2469237919c4a721ac99b49de42723ac95b49de46f276923348de417226c93b49de45f26e92f790bc97e47d24ef27f900c907493e44f261928f90ec26f928c9c762e3ebffe3249f20f924c9a748ce22f934c9d9249f21f92cc939249f23f93cc9b924e7917c81e48b245f22399fe402922f937c85e4ab245f23f93ac93748be49f22d926f937c87e4bb24df23b990e4fb243f20f921c98f487e4cf213929f92fc8ce4e724bf20b988e497241793fc8ae4d72497685f0ab42fbf21f9ada1bb94e4329dfe9dfe7fb9fe7f85feff7bfdff4afdff2afdff6afdff1afdff5ac55f9d4dab31b3790d46e9f8988d838e8fdf02d0f1b19c001d1fd785a0e363bc08747cbc17838e8ffd59a06bd3e912d0b5439aff77e87429e8d23a9d025da74e97816e8e4e9783ae4ba72b403757a72b41d7add355a09ba7d3d5a09bafd335a05ba0d3b5a0ebd1e93afd9fe3a39641fdbfff692eaa4ccbe7917ec5ce6da31efce1b6d1003a6e1b8da0e3b6d1043af6bd1974dc365a40c76da31574dc3666838edb461be8b86d609be2b6d1013a6e1b69d071dbe8041db78d39a0e3b6d1053a6e1b7341c76da31b74dc36e6818edbc67cd071cc17808e63ce6d4ac5f810c8e7058f69bc3ecb3acec7633a0165b28ef3f198e67c3ca6391f8f69cce7ff9c8fc734e7e331cdf978fc723e1eab5caf785cf23e780c72bd623be672b0cd72bd62fbe4b2b12d72bd625b647bd816b95eb12d3203b645aed734e8980bdb221f4bd8169915fbb762286b50ffef7f7a4b06fb645ee2c6fa20a4d3fa7f31f86089a53f052c9d60a7cbae9d25782e998acf5dc0d26dd9673c5f4d85a51b58e6d96509aec9ceb75b6650a71c6bec43d9ce1cf06781657fe26087cbe575b695021df6e70b42f87aecf20dc4c10e97cbeb3dc0c7ba79ee62d58f7d1397adce131bc066dab24de53f1fe77cdf8219d85602b639b27a8c6b8bd695423e8e2d797fec53bb0d9d8b63280e76b85c5e9f077cdca774e7976f60aa7c730d3e077d5f10abb9064b985dcbc75d681d711bea716cd7ec8fba0cbbf8bb84975ce783f9c06bbbff54652eb45b6670ccf702f320d8c0f3ec010e62df0bf18c830dd627207d466c6c3900d269fd9f99d5b1d213b21da6e719fba420bfc7b1cf0b816310d6d996ea4b4f0106cb6d3ea8ef1e8381d7bb40bf30245e780ee4fc06d0717fdf0dba394619f85b1dfb55cbed3a93cb4fac77d6e16fc285217cbd76f90672b5855ee063dd02c7b1dad7b867e17e6cd7f6b187e5abe39c8f13b69380fc8e82b1edce0626cbbfbd06a2fedec17342da2a4ba63feaefc034b058feed1b9c6b3bec96d9efba4dc5207ecc8e7d089edb5c1c531d463df13af27956cfea593dab67f5ac9ed5b37ad6fd9b55b1cc3538f11ed85c017c61f7c06cff36c0fb8e5cb6faed7727d89c63d56626b81664fe9e33ef7d26609b2781eb5e9d2e857cbc9fd469e8ecff5eccd61fdbe172793d0d7cec0bd69feddf8bf1d8f8dfae83cf68bb039bec1f03997e35cf00e71099c75d5affc7b951ac536d724ec198bf768f95ec7d79bc3eaa965cd726e6388b7df61e6e97111bfbf531d08ff3160b62e3fb870eb06be99a468613786d94e3c71c61d7ca4a754594dbe5798a6b2af7855ddd9bc16bd8e9d8d83543b685d7ab795bf39e4e3a36f13e09de5ba9d1f153c7d085f1b1fd2cb7db81a8d7f7b06ddbadd3817e9ce7381516ac67cbe77e27f7f51cdcb308ae35e6baf786f7d1b0fd4dc77d34cfea593dab67f5ac9ed5b37a56cfea593dab67f5ac9ed5b37a56cfea593dab679d49ac389f3eadffef6bbefa74f1b10eef0fd9beb68dcfe372d9eadec57970ef226dd5e6c0b867e3b8fc66a32ef0d9b81be19ecaf93a5d0af961731db0fe5cdcc3dad75c07b6550abe60fdd9bedf81f715b9dc67aeddecbd72bbc7c0c053f7cab93d99c71d3eab633ed386f7f9707e04cedf481bbae9aa0f3c66d2a0e334ce5fb11be38c8b7b68c17b750f807a60dff09937cebf08fa908be3637563f6172aff9a907c5ee2c6fa20a4f13efb22bbbe067de662287f106ca0dd7ebb763368371e1bffce23d627207d3504085f1ac6f16566d5eefa42b6c37487b14f0af2fb1cfbbc083806619d6da9767209b4a96be07c69fb7c83fe625c9a202e9c9f86b8d83ede948be6f88e19f039bbb906278eabb00fec73c0b7af71551ff099733c70be20f627385f306d9575fc18c89c0f9406bb96ce13e3e603e1fc8bced8c4770c24609b9b74bb56f381cc714f1af66d8632f33187c93c37e31ca65b81d9cf610a9fc364cecdc5394cf740bfd65a904def6bbc2de5f9631cc7a0df3dfbf01bdfc1e0a29f64ae228303c726bccda3d05ed5827dec3cfd1fc770e66f45fbe38d8160bcb6d86a99d9f3189e3fd33a8de308ce8f178c6d97d0e924f8dc09e5d484e4f3926bbcb608e23760d7d7e0585d02e50f820db4bbd4aedd0cdae5f11adb607d02d2d50563f1583a967c2abeccacda5d26643b4c1f60ec9382fc8c639f07806310d6d9966a27c5d0a6b8cdb81887a0bf189766880be7e3b5b139c6f6aa3de3fb6599d7f67189637a2ed71ce3878dbdf1fc607f8c34f19984746ce27522bc7e857d025ebf72f17c09cf99c7e74be6388cc5fff75d76f8cc0d1feaaee6f47746e09b037cbc5f02f8e63ae08bf2ccc15ce0e3fdf0dd92f31cf07547e09b077cbc5f11f0d97e5f12bed76e2a7c61efa02b86ffb6c78838169d0a1ff6bbbcdf2ce0b37dcd5ff1f546e0c3fb00bc5f09f059bebe14f0f545e0c36b32bc5f12f86c5f9351652f8ec0d70f7cbc5f29f0591eef057c99087c3846ca409af96c8f9114df92087c4b8189f72b03bee50ef89645e05b0e7cbc5f39f01de8806f4504be03818ff7ab00be6739e05b1981ef59c0c7fb5502df410ef85645e03b08f878bf2ae07b8e03be6747e07b0ef0f17ed5c037e880efb911f806818ff7ab01bee73be07b5e04bee7031fef570b7c2f74c0f782087c2f043ede0fdf877fb003be1745e03b18f8783f3cff1ee2806f7504be43808ff76b01be43edf205cf43ae89c07728b0bcd42ecb52c5f2e2082c2f059697d865099e877c99dd32836b8387592e53957138c484e3c7ec29c83f0ce275b8e578c5c12697cbebc8e759f76f56c5b2c6e04cc2766b04f0b1ee250e5992068b5a72f575617c589747d8e50bce0b6b23f01d012c47596559125c373c3202cb51c0f272ab2cd9f3c22bec9619f4e147033ffbca7652908f757eb465dfe26093cbe575e4f3ac9ed5b37a56cfea593dab67f5ac9ed5b37a56cfea593dab67f5ac9ed5b37a56cfea593dab67f5ac9ed5b37a56cfea593dab7d56c5b2d6e04cc2766b05f0b1eee50e5992068b5a72cd1309e3c3ba7ca55dbe604ecdba087caf049663acb264bf3df1aa082cc700cbabadb264e7d4bcc66e99c19c9ad7023ffbca7652908f75fe5acbbec5c12697cbebc8e7593dab67f5ac9ed5b37a56cfea593dab67f5ac9ed5b37a56cfea593dab67f5ac338555b1ac333893b0dd3a017cac7bb54396a4c1a2965cd7d9c3f8b02e8fb5cb17dc93581f81ef5860d964972578ffc386082c9b8065a35d96e09ec466bb6506f724b6003ffbca7652908f75bec5b26f71b0c9e5f23af279d6fd9b55b1ac373893b0dd7a017cacdbe8902569b0a82557bf14c68775799c5dbea00f1f8ac0771cb01c6f95257b5ff97511588e0796ad5659b27df8ebed9619f4e1db809f7d653b29c8c73adf66d9b738d8e472797d9b3bbb81ffdb27f17f7b08c7f63cfa8f7c53653d6c06b1fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab8fab84e9d55b10c199c49d86e48001febb63a64491a2c6ac975ed3e8c0fdbdd0ebb7cc17d8ee1087c3b8065a75596ec3ba94f88c0b21358de6095257b9f6397dd3283ebfc23c0cfbeb29d14e4639d8f58f62d0e36b95c5e47be6722ebb619c4eadb801b56df063cab6f039ed5b701cfeadb8067f56dc0b3fa36e0597d1bf0acbe0d7856df063cab6f039ed5b701cfeadb8067f56dc0b3fa36e059a7bb0d289661833309db0d0be063dd1b1cb2240d16b5e49a2712c687edee44bb7cc19c9ad1087c2702cb290e584e8ac0720ab09c6c97259853f346bb65f6ab32de04fcec2bdb49413ed6f99b2cfb16079b5c2eaf23df4c61552ca3066712b61b15c0c7ba931db2240d16b5e43a7ec2f8b02e4fb3cb171cdfa746e03b0d584e77c0f2e6082ca703cb5becb2047dcd5bed9619f4356f037ef695eda4201febfc6d967d8b834d2e97d7916fa6b02a96530dce246c77aa003ed6bdc5214bd260514baee3278c0febf20c077c6f8fc07706f0bd3d84ef4c077cef88c07726f0f17ea5c0f72e077cef8cc0f72ee07b27a499ef3d0ef8de1d81ef3dc0c4fb9501dffb1cf0bd3702dffb808ff72b07be0f38e07b7f04be0f001fef57017c1f72c0f7c1087c1f023edeaf12f83ee280efc311f83e027cbc5f15f07dd401dfee087c1f053ede0ffbbf8f3be0fb5804be8f03dfc742f83ee980ef1311f83e097c9f08e13bcb01dfa722f09d057c9f0ae13bdb01dfa723f09d0d7cbc1f5ec3faac03becf44e0fb2cb09c6397a53f052ce7809dcf3bf0f973b1a9fbccf653b01ff29de780efdc087ce701dfb9217c5f74c0f785087c5f043ede0fdbf4f90ef8be1481ef7ce0e3fdb04ff8b203be0b22f07d19f82e08e1fbaa03beaf44e0fb2af07d2584efeb0ef8be1681efebc0f7b510be6f3ae0fb4604be6f02df3742f8beed80ef5b11f8be0d7cdf0ae1fbae03beef44e0fb2ef07d2784ef42077cdf8bc07721f07d2f84ef070ef8be1f81ef07c0f7fd10be1f39e0fb6104be1f01df0f43f87ee280efc711f87e027c3f0ee1fb9903be9f46e0fb19f0fd3484ef170ef87e1e81ef17c0f7f310be5f3ae0bb2802df2f81efa210be5f39e0bb3802dfaf80efe210be4b1cf0fd3a02df25c0c7fbe1f8efb70ef87e1381efb7c0c7fb61fc2eb3cb17dc73b93402df65c072855d96e05b03bf8bc07205b05c6e9725b8fff37bbb6506f77fae047ef695eda4201febfc4acbbec5c12697cbebc8e759f76f56c572a9c19984ed2e15c0c7bacb1db2240d16b5e4ea97c2f8b02eafb6cb17f4e15745e0bb1a58fe60956569f00e9e6b22b0fc0158aeb5ca92edc3ff68b7cca00fbf0ef8d957b693827cacf3eb2cfb16079b5c2eaf23df5459b7cd20561f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571f571fd7a9b32a96ab0cce246c7795003ed65deb902569b0a825d73ce7303e6c777fb2cb17cc09bf3e02df9f80e52f5659068239e17f8ec0f21760b9c12a4b764ef85fed9619cc09ff1bf0b3af6c2705f958e77fb3ec5b1c6c72b9bc8e7c5365dd3683587d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c7d5c9f9971552cd71b9c49d8ee7a017cacbbc1214bd260514baeebec617cd8eefe6e972fb827716304bebf03cbbfacb22c09ee49fc2302cbbf80e59f5659b2f724fe6db7cce09ec44dc0cfbeb29d14e4639ddf64d9b738d8e472791df99e89acdb6610ab6f036e587d1bf0acbe0d7856df063cab6f039ed5b701cfeadb8067f56dc0b3fa36e0597d1bf0acbe0d7856df063cab6f039ed5b701cfeadb80679dee36a0586e343893b0dd8d02f858f74f872c4983452db9e68984f161bbfb8f5dbe604ecdcd11f8fe032cb7da6509bedff7df082cb702cb2d7659823935ffb35b6630a7e636e0675fd94e0af2b1ce6fb3ec5b1c6c72b9bc8e7c9e75ff66552c371b9c49d8ee66017cacbbc5214bd260514bae7e298c0febf20ebb7c411f7e7b04be3b80e56ebb2c411f7e670496bb81e52ebb2c411f7e8fdd32833efc5ee0675fd94e0af2b1ceefb5ec5b1c6c72b9bc8e7c9e75ff66552cb71b9c49d8ee76017cacbbcb214bd260514bae7e298c0febf27ebb7c411f7e5f04befb81658f03960722b0ec019607edb2047df84376cb0cfaf087819f7d653b29c8c73a7fd8b26f71b0c9e5f23af2cd1456c5729fc19984edee13c0c7ba071db2240d16b5e43a7ec2f8b02e1f75c0f74804be4781ef9110bec71cf0ed8dc0f718f0ed0de17bc201dfe311f89e00bec743f878679b7c4fc6a6cec79929d80ff90a1cf0c5e353e72b003ede0ff90a1df02522f015025f2284afd8015f5104be62e02b0ae14bdae50bc60fb322f0b17dc552623956aacc52bb65f6ab32539663a6ca28832071fc4aa1ee383f05f12ab31caf38d8e472791df9a6ca5a1f9b5e56077607ca62d971cd2cc316df7341a6729d2e043d1f7b6ab542eb8af43a6f7f8ede2601dbac4bea32758c79e98218573888312e8390ae80fae6a54910cb6e412cad82584605b1ac17c4b24610cb0a412c6d8258ea05b1f40a62490862e910c4d22d8825238865b6209661412ca571392ced82e2b24e10cb4a412c4b04b1340862e913c4325f104bb320964e412c438258d60a62592d88a55110cb2a412ccb04b12c16c4d22388253ecd2cc9d8c46be049c82f85ed0a8c7dd5b5c10f568fe557697d019453ad758990b2aba0ec4a9dae8e4fdc176354e52046686710d6d956293054c7a79fa54710cb62412ccb04b1ac12c4d2288865b52096b582588604b1740a626916c4325f104b9f209606412c4b04b1ac14c4b24e104bbb20161edf4a6019161497d98258328258ba05b1740862490862e915c4522f88a54d10cb0a412c6b04b1ac17c4322a88a55510cb6e412c4d8258baf2c4c2d70ab9dc4a83653aedd6d8b51b3c13540b76f9da690dc49dedd70247bd5d8e60ee3472a8c5581d777db91e58ea2cd7852ab3c1729c55998d9663a6ca68822071fc983d05f98d10af26076db7c168bbbc8e7c5365c5b96ed3c1eaaafe9b2dd73fcfc7e658361b31c578b7e87421e86bc0dfd996fd55c5b5ea32798e3733b0ad046cf38ad2ecff726dbf15d8b9ffc1791e1d96db858a635b84fea70362d7eea0ff493be8e73bc121f6350dc71fe7b7826f9d0e8ebfb471fcf17a27b0f08273fcd30e58701984743a84a54910cb6e412cd85ea69d45505c4605b1ac17c4d224a8bdac111497158258da04b1d40b62e915c49210c4d22188a55b104b4610cb6c412cc38258da05b1ac13c4b25210cb12412c7d8258e60b626916c4d22988654810cb5a412cab05b1340a6259258865992096c582587a04b1c4a799655f73fc39bf09b6e36b7c6da09ba3d3eda02b08b1c1bf773a4157a8755c86bad67c56f5c4b231462eae69a29d4158675b38c77f4e7cfa597a04b12c16c4b24c10cb2a412c8d8258560b62592b886548104ba7209666412cf305b1f4096259228865a52096758258da05b10c0b62992d88252388a55b104b8720968420965e412cf58258da04b1ac10c4b246100b5f5790c0b25e505c4605b1b44a6211d45e760b8a4b932096ae1016cbd73407f03a242fc66ae8754ec5d26d9725f86e545704966e60996bb98e5499f3ec9619cc7b9e6fb94c55c6020812c78fd953903f1fe2b5c0419b9e171f5f4fbc8e7c9e75ff66c5b9d5cc9984ed3a05f0b16e2eb0d8ee0b94cf3c1ee0b2d5fd9b8da9319b96e7f52f55c561ff3d080c6c2b01db9c5935c635a4b94a211fef3db587d45f9b83fa6b37ea8fd7dbe0bcc9beb4034bbb03960e8345925ddbb1c73ae6c5581d776e6e0316dbcfd3a4806536d86971e0736b049f5b80c5f2f34d9914b034831dcbcf8405fd125fc36b827ee9d494b3fa0cfaa536a35f62067c3e8ab719867ee974e897da428e8356cbf18903935ad260b715fac3d690f669fb993765a72542fbc47663f799be4cd06e9a22b034008be56741330e9ec9ed77f06ced84e78d9f7ae613c6229c5f07f1aa75704ea937ce29bc8e7c9ed5b37a56cfea593dab67f5ac9e75ff66552cfcfb03e735f3762d02f85887ef7cb1fddb20785f466c7c3da9dfa6d7c16f66bbbfd333c1ef50fc3d970606b695806d8ea81ce3ba017e33371b7595845861fd3538a8bf46a3fe789d6de17d6dacbf46072c4d06cb33d7eec026fbc740a69fdfbfd36cf457669d2adb96dfdb155ca7ab8338aac5581d77eda1c661bfa4caacb6dcbfa832aac021f6b51afa39cec7f703b87c371d976bbe9b0e9fc52900966a072cb80c42ba3a8465b7209651412cad8258d60b62592388252388a55e104bb720964a412c49412c09412c3806996e96d982e2d22e886589209606412cf305b15409626916c4522a88a55010cb902096b58258960962e911c4522d88252588a548104baba0b15493a0b8ac10c4d22688a557104b8d20960e412c6582588a05b10c0b6259278865a520963e412cb582583a05b1940b6299258865b5209646412cab04b12c16c4522788a54b104b85209612412c2d8258e2d3ccb2aff733727e1d6c677eeb0bdfc588e5f13d0ede5efd4e3fb77a62d905b1896563399cc618553a8811da198475b685ef67ac8e4f3f4b8b209612412c158258ba04b1d40962592c886595209646412cab05b1cc12c4522e88a553104bad20963e412c2b05b1ac13c4322c88a558104b9920960e412c3582587a05b1b40962592188a549100bdf1796c05224282e29412cd582587a04b12c13c4b25610cb90209642412ca582589a05b1540962992f88a54110cb12412ced8258660b62691034964a088a4b52104ba520966e412cf58258328258d60862592f88a55510cba82096dd8258cc7bdf98afc6e57cbee27bdb09c83f54df4c50fff6f58cb80bbf70198c4de4ded733e2d3cd322a88a55510cb7a412c6b04b16404b1740b62a914c49214c49210c4d2e0f8dc168565b6a0b8b40b62592288a54110cb7c412c5582589a05b1940a622914c432248865ad20966582587a04b1540b624909622912c4d22a682cd524282e2b04b1b40962e915c4522388a543104b99209662412cc38258d60962592988a54f104bad20964e412ce58258660962592d88a55110cb2a412c8b05b1d40962e912c4522188a544104b8b2096f834b3ecebb96cce4f80ae42ebf07b7be53add00ba82101b5c4e05e8f89a1c97a17ecf5f503d91a10018ca42b8787fb4c776cae213f7751d73b43308eb784f9f19ca1c5f37980a4b8b209612412c158258ba04b1d40962592c886595209646412cab05b1cc12c4522e88a553104bad20963e412c2b05b1ac13c4322c88a558104b9920960e412c3582587a05b1b40962592188a549100bfff696c05224282e29412cd582587a04b12c13c4b25610cb90209642412ca582589a05b1540962992f88a54110cb12412ced8258660b62691034964a088a4b52104ba520966e412c19412c6b04b1ac17c4d22a88655410cb6e412c05064b29e4f335abe0f7a5d67582ae54ebba4097d4ba6ed09568dd7cd0cdd2ba1ed0156b5d2fe88ab4ae0f74855ab7187409adcb80ae40eb96802eae75cb40c737a35780ee499d5e09ba27747a15e81ed7e9d5a07b4ca7b95f50e793470d9daaf347747a50ffef7f7a4b50e76c87cbe5f547806faf4e3f0a3a4eaf05e6870d9d627ec801f3c30633af3f047cccff30e838bd0e98f7183ac5fca003e63d0633af3f087cccbf07749c5e0fcc0f183ac57cbf03e6070c665ebf1ff898ff01d0717a0898ef33748af95e07ccf719ccbc7e2ff031ff7da0e3f43030df63e814f3dd0e98ef319879fd6ee063fe7b40c7e95160becbd029e63b1d30df6530f3fa9dc0c7fc77818ed3bb1df3ed35f8f61a7caeec3e62d87d244f761f32ec3e9427bb0f1a761fcc93ddfb0dbbf7e7c9eebd86dd7bf364f76ec3eedd79b2bbbfb5e7e9ea37f6b7f63c5dfdc6741d47fe7c941fbbfe7c941fbb53398e6eb76b772009e5f31237d607217d3bb0dc613906aaccdbec96d9afcafc9fe5325519b7424c387ecc9e82fcff41bc6eb51caf38d8e472791df9660a6b1274f81c05e7a740778bd69582eebf5c0ee8fea37525a0bb59eb6681ee26f61d74ffd6ba22d0fd4beb1e07e67feaf463a0fb874eef05dddf75fa51d0dda8d38f80ee6f3afd30e8feaad30f81ee2f3abd077437e8f483a0fbb34e3f00ba3fe9f4fda0bb5ea7ef03dd753a7d2fe8fea8d3f780ee0f3a7d37e8aed5e93b41778d4edf01baab75fa7fa0bb4aa70b21f6576a5d0274bfd7ba02d05da17571d05d1e63e598ee775af524d8bd4ca79f00dda53a7d17e8f89aed6da0e3fb67d89e792ec32da0e3394bff051dcfd9fc0fe8789ef8cda0e367536e021ddf2bfb37e878dec2bf40c7f393fe093a9e9ff90fd095ebf4df41c7cfa1dc083abe2ff637d0f1bc80bf828ee722fd05743cfff106d0f19ceb3f838e9ff3f813e8f8fdc2d7838eefbb5f073a7efee08fa0e379747f001dcfabb81674fc3cd235a0e37b2957838eef255f053a9ec37825e8f8fef7ef41c7d7f6af005d5aa72f075da74eff0e747374fa32d0f13d006eafaafda876d564f9be4610336390906bccd004f7581aedb2f4a780a511ecd45bb533d0af8ae37bf5ead84fc7c6eab91eecd6d9b19be1842aae16caef040eb695806d5ea30fca72bd7dade578c7c16e918e03f3d4020f6fb341f3a87eb0b0ca593b08c6b14d11da64a3fd3a6394fe24c4642a2c75ceda6d764c6dbb0da8326b2c97a9caa88620996d2a05f93510af6a07f76c6be3e3eb89d791cfb37a56cfea593dab67f5ac9ed5b37a56cfea593dab67f5ac9ed5b37a56cfea59670aab62e1ebe7f81e45deae49001febf07e8bed6bdb78af8ecb56f72eeeab1cb3d960d566f6de12de8f480303db4ac03607548d71edd15ca590df04f5571f527f750eeaafdea83f5e675bf8ac2bd65fbd03960683e5996b776093fd6360a05fcd0908ee9f1bfd9559a778efb50e8e15becf17bcb746eb5ba04d3618bae9aa0f3c661a42da69b3b37e26e3e21e5af0d85d35d443a3716e49407e25f421d555637563f6172a3f1d92cf8bb13aeebe26deb7b6fc6c65d0675640f9836003ed963b68576c37ae856d54409c39ddc11362603b8cefb8776ac4276e87e97a639f14e45739f6b9d238962a0d56d54eeaa04da5e15ebfedf30dfa8b71e1f91829c8c7ef4bd638880b8eefd2c0500375d462f43b38aec23eb02a8fe3aaaa9071551df0b11fd89f5c971a6375390632e7d734d83f4f8c9b5f83f32f3a81a31e8e67de6640b76b35bfc61cf7a4615ffc7e673ee60499e7669c13b40298f33527a8dee88b3186aba09f381ec60a61e3d73a43e7803f83fc5c6e9dc18fe3026c2fb67f0b61dfc08bb13aee1c5bedb07f73d02705f37cf05c12d61f713ecff374307e08eabccaa8f32ae3fc1a33b6a90d193fd6859c7f2b2cf78d2ecee9aa8c32e8db1b8cf37902f20f87e3f508180bb2cf8d50ce86907c5e72b5631ccb953ae89f92c658b1343ed16e8983369634c68a4f3d870071e6f4b130562c8160717c4ba1ddf1b310b85d4948bb2d85e38af3538e7d2e358eab528355b593a3a04d6d80b1a2ede31cfdc5b8f0f93905f9f8bbb6c938aef1db1d782e7231d62e33e257661c9ba9d8c4f7c8e0b9d4fef82ccbd5688c75cc6b5478ed0cfb04bc7636dbc1f9b22d423f331beaaed92ecb52555c0b1cef836003bf2ddfe8a06e9a0cbb2d46df9c823835858c69da216838164a87ec638e35719c86e7463e5fb642793c4629884d1c63a925ec7a39fe9662ce6ab05365d8b17e0ece8c1fb71480cd0a606b358e49c551e6a0aecb8dfec17c9f213e9782bfcf4f4d8dc58cebb5138f5d43a7f8db1cf0b71bfcbcde0675da61b4cb6288af1d96ec3cfd287d07b62fdbfd982ab3c56e99fdf6fbb8951b5519f89c05c7af25e4dc89d74f9b1cb4a316a31db5849c9fedda1dd8acca689cc4ffc6108ec63cfadfe8cceef24daa8c8649fc6f08e168c8a3ff0dceec2e1f5265d44fe27f7d08477d1efd7777bf6945701eac9bc4ffba108eba3cfa5fb78fb14c2ed6866966b56f7769d057d74ee27f6d08476d1efdaf756637b35c95513389ff35211c3579f4bfc699dd0383d766564fe27fbee69feccbff6a6776335b54195593f85f15c2519547ffab9cd95d19b4ffca49fcaf0ce1a8cca3ff95ceecaedca0caa898c4ff8a108e8a3cfa5fe1cceec6e0f5bae593f85f1ec2519e47ffcb9dd9dd70a02aa36c12ffcb4238caf2e87f9933bb0341fda726f13f15c291caa3ff2967763707e39fd249fc2f0de128cda3ffa5eeec06e7bfe424fe2743389279f43fe9cceee6e0b75ac924fe97847094e4d1ff1267763706f53f6b12ff678570cccaa3ffb39cd91d0aaed5144fe27f710847711efd2f7666777950ff4593f85f14c2519447ff8b9cd95d129cff0a27f1bf3084a3308ffe173ab3bb65a92a233189ff89108e441efd4f38b3bb2138fe0b26f1bf2084a3208ffe1738b33b10fcfe8f4fe27f3c84239e47ffe3ceec2edf983590dbff5808472c8ffec7dcd90dfc7f3296dbffa7f281e3c958fefc675bf6ed6e0efaff2762b9fde77ce478228ffe3fe1ce6ed0ff3d1ecbed3fe723c7e379f4ff7167765706fddf63b1dcfe733e723c9647ff1f736677e30655c6de49fce77ce4d89b47fff73ab3bb3418ff3e3a89ff9c8f1c8fe6d17fe46b093957f13b47836f681afc8ad5f2f7ab96aa321fb6ecbf2a83df5bace6a1f0dc0eb69380fce5d563db1da8d349f099e7ada8fcd521f9bc18abe3e67170cc94af96bf4b15cc357d00ca1f041b68d7e5b7a5e25ad806eb13903e985fca1b1bff9e7d8e2f7e436b4fc876986e31f64941fe1ec73eefebdb046c4bb59355d0a6b8cdb838ced15f8c4b2bc485f3715e93ede34d156d7e2b82191e06964ea33f51c711b7d14ee0dbe3806f5fdfd0d8037cacc3f7a5b31fd89f6c84796d9d5a8fdf4d4cebf41c28a7dbd0293fe739f093ed70b9bc3e0ff8f8bdcdddf9e51b982adf5c834fb12cb01cab24d8e425571fbe0058e65b665165f6d82d339837b310f8d957b693827c7cee65a165dfe26093cbe575e4eb0961e5f7a9e377887b80d572cc02d6b906ebdc10bb7d798811f72b7d8eedf61a76bb0cbbea38c17a524baee3a417780fb0ccabca5c64b7cc60fcb4189807c14617e8fb1dc47e31c4330e36589f80f469307eea1f4b3e75ae616675acf4856c87e985c63e29c8ef73ecf322e0188475b6a5ceaf3b61cc64b9cd07f5dd6730f07a17e81785c4ab0fe2c5f9dda0e33100f6b1738c3292500e9e6b2db7eb4c2e3fb1de59d70b7c8b42f816dbe51bc8d51616031feb0e001617fda0c9c2e71eec071b8df805cf920157c23257b12ed76699f88d185e72f5e7c5f0bfc8328bfab68c1e4ac7768decd8b9e1b82d476cd9b019af54171a88058086690e3d7ec6a61074fc199b22d0f1feb340c7e594409e0bd7d1372eb7d0602c06365b76f17340bce4aafe59c062bb29aa18f3e78074f51fbd73ebc816acff228331acfe555ec2d88eebadd03233dae272799d6d29bff89346276cd8f4fae7ed3c6e74fb96e1915d1868b361c70d87d48295858d99b72b329cb5dc58964a6b2cfc0da74d1bb66d3b7c74e3b6ad9b0e1e1dde34b275c7705893e1886175857519b8edbeba8a2478c63a2eab0474d80d7144cc88590b493d94c9cd27a19d298a8d358992d8d827ba822988b16cfb549fd8524fcaaaa778d5884b85577d12ab0ecafdb9feaf6ca94f5ea953a0faa495fa8495fa6495ba3ca21efd53af4e518fe2aa21503a96fdf9a2860f6a48a57e42a96192fa59a77e3aab9fd26a88a486446ad8a14eedea34ab4eabead4af8682eadad600c9121235af40dd5b53f38b5790a87996ea5ecbb34856911c44f26c92e7903c57c7f77924cf277901c90b495e447230c96a924348d6901c4af262929790bc94e4652487911c4eb296e4089223495e4e7214c92b488e265947f24a925791bc9ae41892d790bc96643dc9b1b1ecb040dd0f55cf2fa9fb62eadec010c97124af23d94a723cc9eb49b6916c8f653f51bf83e404923790ec24d9453212cb7e0afe449293484e263985e48d246f223995e434923793bc85e47492b792bc8de4ed246790bc83e44c927792bc8be4dd24ef21792fc9fb48de4ff201920f927c88e4c3241f89653ff1fe51928f917c9ce413249f24f914c959249f26399be433249f253987e473249f273997e43c922f907c91e44b24e7935c40f26592af907c95e46b245f27f906c93749be45f26d92ef907c97e47b2417927c9fe407243f24f911c98f497e42f253929fc5b26df517241791fc92e462925f91fc9ae41292df90fc3696fd5cd965b1ece7cd2e8f653f87a63e93a63e9fa63eaba63eb7a63ec3a63ecfc607321ec43c758f7fa26f1819d9b2fd8491f4c88ef4f6d16d235b4fd8764afaa4ad23af4bef3871cbcea16d3b4ec29dfffd7476be45afcc9eb8f386cd9bf7bddf237a853f78b76678f39693d33b4647d23b86d21b778c0e6f1e776e3a5a7b7d905e3f327b724eefdab66324dd9f1ea6bfd403ef3869cbe64569ccdb452eec1a49ef1ad9b073243db473c7f6746611967b54a99b728fa97c1a31cd543d8d9d97574dbd42fe0f6b585bbcfe1603009b2d6c6f0000001c481f8b08000000000000ffed9d077815c7b5c7efd54582ab2b01a6096424ad2aa24b028c316084e9cd0df70a06516c40188471efbdf7de7bc1bdf7827b27cf7e71123f3bcdce4b9ec94b5e122771e2e49dd93b07fd19966bedc70cda0b67bfefcfee9edd9df39b3367677767579775b1582c1e4b4f09528fd8a6136f6fd4f3ba2d9bea2d9655e792339e259c3959c299c812ce0e59c2999b259c7959c2d9314b383b650967324b38f3b3843395259c0559c25998259c9db384b34b967076cd12ce1db284b35b967076b7c8590c9cfcccd453cf7be979919ef7d6f33e7acec7eea8e77d755d3be8f5125229a98ce4e96d1c98725205a9925445aa26d590fa916a49fd4903480349834883494348437519eae1ab81348c349c3482b41369246967d228d22ea4d1a431a4b1a45d49e374ecc69376234d204d244d224d264d214d254d234d27cd20cd24cd22ed4eda83b4a7ae8ba7ebb217696fd26cd23ea47d49fb91f6271d403a907410e960d221a4434987910e27cd21cd251d419a479a4f6a222d202d242d222d261d493a8ab484b494b48cd44c5a6ec4fc68d20ad24a528bc1b98a740c6935e958d271a4e34927904e249d443a99740ae954d269a4d3496790ce249d453a9b740ee95cd279a4f34917902e245d44ba987409e952d265a4cb495790ae8c6ddcfe5791ae265d43ba96741de97ad20da41b4937916e26dd42ba95741be976d21da43b497791ee26dd43ba97741fe97ed203a435a407490f911e263d427a94f418e971d213a427494f919e263d437a96f41ce979d20ba417492f915e26bd427a95f41a692de9755d971c5d9737486f1ab6b7486febe577f4fc5d3d7f4fcfdfd7f30ff4fc433dff48cf3fd6f375aabcc2f4b2ba1735c736948dcfd938d8f8fccd011b9fcb09b0f179dd016c7c8ee7828dcff73cb0f1b9df116c7df57227b095c032cf4bf5723ed8caf4720a6c9e5e2e005bb95e2e045b855eee0cb64abddc056c557ab92bd8aaf5f20e60abd1cbddc0d64f2f77d7738e859a1af5bc6e0b2755a6e56b469d62e73ce801f5e13ce80936ce835e60e33c28021bd7bd37d8380ffa808df3a0186c9c073b828df3a02fd8380f307f380f4ac1c679500636ce030f6c9c07e560e33ca8001be74125d8380faac0c679500d368e6f0dd838be9c3f2a9e93613b4f78aee27826db783b9eab0928936dbc1dcf55de8ee72a6fc77315b7f39cb7e3b9cadbf15ce5ed785ef2763c07b90df17ce363ba838ddb10f393cbc15ce436c4bce3b231c7b80d31c7d81fe618b721e61833608ef139e2818db930c7f81cc11c6356ce3155d73ce06dd4f3ba2d9beab1efe6296eac37c232fb572c7dedb2d4a580a52ff829b5eb67185e73da52e75260f12cd719af6b6d61f180a5dc2e8b3f865961b74cbf4d39d6786eb09f12a84fa5e5fac4c10f97cbebec2b05360ff82a03f8aaecf235c4c10f97cbeb55c0c7b67277b1aac3fe8acb56d789c3c1a7e5bea74ed59fcf731ee76706f695807d9614b672cdd3b67cd85e0c363e1efb6dcfb0b93887f0998acbe5f572e0e33ec5dbba7c0d6de52b33f81cf47d7eacca0c16f16bbdcdebb07c75eef0f9c27e12b0fdbb78eb7eab81a9d82e5343d86b303e5fdabd46d5d7e1b9d716960a6071710db6ddb73bb876f939550d31f1f41cafabbcbd0ae2556d395e99aea1c827acc22aacc22aacc22aacc22aacdb372b8e4b797abeb9719ff6e2db5ae33e3c268de33e6f834fcfaacf7a7fdca7d828bfc8688b04ecf353e0e2f7a238ee83633cc586cdc1f8713df273b9bc8eef2d790c0aeb6af939da67d9d160d976fd36cc536596592db3be4ebd6fc277d365463df03d4f1fc3a672f2fb786b7d3dab6ce1dfcf78b15616dbe348f87ec65d9fd45087e3f639b18dfb874af06b694ca39e1794df6a237eccc1be12b0cf577a5e6897670357a6f14287d74f3f0e55e0d78bb59e1bf82edbbc96abe36a80cb83f85543fc789ff57aaecea14be11cb23de61d767c0f73db6e9b36d4e1bbafb6b0603bdb7e3fe6227754993596cb5465f4839898399582ed987ffd2cc70bfb072e97d7914f5885555885555885555885555885555885555885555885555885555885355b58158b6770e2f8bf17013eb6e1fb21db63dbf8b75a5cb67a777132bcbba8b0ea33fd2e0cdf4778b14dff5e2c01fb3c03df6f9fae97f361bba7e7f8ad8307e5bb7887f5437fe3921fdbf4ef725cbcefc0f78a5ceeb6eb37fdaedcee39d0b0e15d39e79379dee1df2d151b367ccfa7dadcd376fc7ea3c2b0b5577be0395301365ec66f1cecc6b8dec53b34fff708fb413b70ddd84f02b6df007dc84df1d6b631fb0bb57d4dc0769ee2c67a232ce37bf6fe76ebeaf79903a0fc46f0817e07daf55b8f7ee35aec83ed09587e000234b07571437c9959e55d6dc07eb85c691c9382edb58eebdc1f381a619d7da93cb915726a0d5c2f6d5f6fb0be189722880b6faf80b8d83edf5415f1fece03861a60293138f1be0afbc05a077c9bbbafaa053ef31b0ffc5e10fb13fc5ed0e53d508e114b6c434bd7898dbe07c2ef2fca81837d25609f97745eabef81ccfb1e0f8eed0d656e8d6f98cc6b337ec3b41698e51ba6e06f98cc6f73f11ba6f7a05ffb16ee6d2ac02ffbaa326c0eea5d6fd6bb11d6d917dedb60bdab36536ffc2d0617fd2473e51a1c786fc2fb7c0af9aa26ec63f9fb53bc87339f15eddf6f34f8f76b03ac9699be8ee1f593db0bef2378fbe790835fc0fd18d7b902ca591fb09da74cf76bfd217e83edd6d53f578740f98de003fd0eb5ebb71efdf2fd1afb607b0296bf81000d6d5ddc105f6656793728603f5cee671c9382ed831cd779307034c23afb5279f20bc8a9f570bf66fb3e04eb8b71e90d71e1ed3836e619fbab7ce6f3c183f8d93e2ff19e9ecb35eff183eebdf1fa60ff1e29cd550e5c5e2cf87785d8560e5c387e65f9ef04eaf09bf962f089dfcc47e5378d70cc2227d6ca57e280af6f08be12e0e3e312c067f7ef21d27ca521f8f077f9f0ef2298afdc019f1782af1cf8f8b85ce0b33dbe14f61befa0df22ca83b9ed7b44bc176d0b1ff6bb7c5c47e0b33de68fbfafd8163e7c0fc0c775023ecbe34b3e5f6d083e1c93e1e392c0677b4c46953d2004df40e0e3e3f281cff2fd9ecf3728041fde230d8265e6b37d8fa4f88684e01b0a4c7c5c01f0d53be0ab8bb59daf1ef8f8b842e01be680af2104df30e0e3e33a03df08077cc343f08d003e3eae0bf08d74c0b75308be91c0c7c77505be510ef8760ec1370af8f8b81d806fb403be5d42f08d063e3eae1bf08d75c0372604df58e0e3e3f03786c739e0db3504df38e0e3e37a00df78077c8d21f8c6031fdbf1fa3bc101df6e21f826001f1fd707f826d9e5f3ff1e726208be49c032d52ecb70c5323904cb5460996297c5ff7bc86976cbf4c706a75b2e5395310362c2f163f6146c9f0ef19a61395e71f0c9e5f23af209ebf6cdaa58261a9c49d86f6204f8d836c5214bd2605153a6be2e880fdb72965d3effba303304df2c60d9d32acb307fdc70f7102c7b02cb1e5659d2d785bdec96e9f7e17b033fd795fda4603bb6f9de96eb16079f5c2eaf239fb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb00aabb0da67552c330dce24ec3733027c6cdbc3214bd2605153a6ef4482f8b02df7b1cbe77f53333b04df3ec0b2bf5596f4ff3db16f0896fd81653fab2ce96f6a0eb05ba6ff4dcd81c0cf75653f29d88e6d7ea0e5bac5c12797cbebc827acc22aacc22aacc22aacc22aacc22aacc22aacc22aacc22aacc22aacc29a2dac8a65b6c19984fd6647808f6dfb3964491a2c6aca34ce1ec4876d79b05d3eff9dc44121f80e0696c3ecb2f8bfff70480896c380e550bb2cfe3b89c3ed96e9bf939803fc5c57f69382edd8e6732cd72d0e3eb95c5e9f037661ddbe5915cb41066712f63b28027c6c3bd4214bd2605153a67e694e001fb6e51176f9fc3e7c6e08be2380a5c92a4bfabdf2bc102c4dc032df2a4bba0f5f60b74cbf0f5f08fc5c57f69382edd8e60b2dd72d0e3eb95c5e5fe8ceaf5fff453f50ff45011c8bb662fd91afadacd3b38855e22a7195b84a5c25ae125789abc455e22a7195b84a5c25ae125789abc455e22a7195b8b69d55b1cc353893b0dfdc08f0b16dbe4396a4c1a2a64c63f7417c987747dae5f3df732c0ec17724b02cb5ca92fe4deaa342b02c0596255659d2ef3996d92dd31fe76f067eae2bfb49c1766cf366cb758b834f2e97d7916f5b645d9845ac92036e5825078455724058250784557240582507845572405825078455724058250784557240582507845572405825078455724058db3b0714cb62833309fb2d8e001fdb963864491a2c6acaf49d48101fe6ddd176f9fc6f6a9687e03b1a585a1cb0ac08c1d2022c2bedb2f8dfd4acb25ba6ff4dcd31c0cf75653f29d88e6d7e8ce5bac5c12797cbebc8972dac8a65b9c19984fd9647808f6d2b1db2240d1635653a7f82f8b02d8fb5cbe79fdfab43f01d0b2c273860392e04cb09c072bc5d16bfaf39d16e997e5f7312f0735dd94f0ab6639b9f64b96e71f0c9e5f23af2650bab62596d702661bfd511e063dbf10e5992068b9a329d3f417cd896a738e03b3904df29c0777200df690ef84e0dc1771af0f171f9c0778603bed343f09d017ca7c332f39de580efcc107c6701131f57007ce738e03b3b04df39c0c7c71502df790ef8ce0dc1771ef0f1719d81ef02077ce787e0bb00f8f8b82ec0779103be0b43f05d047c7c5c57e0bbc401dfc521f82e013e3e0efbbfcb1cf05d1a82ef32e0bb3480ef0a077c9787e0bb02f82e0fe0bbca01df9521f8ae02be2b03f8ae71c0777508be6b808f8fc331aceb1cf05d1b82ef3a60b9de2e4b5d0a58ae073f373aa8f30db1b6d799fda7e038e4bbd901df4d21f86e06be9b02f86e75c0774b08be5b818f8fc39cbedd01df6d21f86e073e3e0efb843b1df0dd1182ef4ee0bb2380ef6e077c7785e0bb1bf8ee0ae0bbd701df3d21f8ee05be7b02f8ee77c0775f08befb81efbe00be350ef81e08c1b706f81e08e07bc801df8321f81e02be0703f81e71c0f77008be4780efe100bec71cf03d1a82ef31e07b3480ef09077c8f87e07b02f81e0fe07bca01df9321f89e02be2703f89e71c0f77408be6780efe900bee71cf03d1b82ef39e07b3680ef05077ccf87e07b01f89e0fe07bc901df8b21f85e02be1703f85e71c0f77208be57808f8fc3fbbfd71cf0bd1a82ef35e0e3e3307eafdbe5f3dfb9ac0dc1f73ab0bc6597c5ffbf06de08c1f216b0bc6997c57ffff3b6dd32fdf73fef003fd795fda4603bb6f93b96eb16079f5c2eaf239fb06edfac8a65adc19984fdd646808f6d6f3a64491a2c6acad42f05f1615bbe6797cfefc3df0dc1f71eb07c689565b8ff1b3cef8760f910583eb0ca92eec33fb25ba6df877f0cfc5c57f69382edd8e61f5bae5b1c7c72b9bc8e7c6d655d9845ac125789abc455e22a7195b84a5c25ae125789abc455e22a7195b84a5c25ae125789abc455e22a7195b84a5c25ae125789abc455e22a7195b84a5c25ae125789abc455e22a7195b84a5c25ae12d7b6b32a96770dce24ecf76e04f8d8f6814396a4c1a2a64cdf3907f161defdc82e9fff4df8ba107c3f02964fadb234f8df84ff4708964f81e513ab2ce96fc2ffd36e9975aa8c1f033fd795fda4603bb6f98f2dd72d0e3eb95c5e47beb6b22ecc225689abc455e22a7195b84a5c25ae125789abc455e22a7195b84a5c25ae125789abc455e2ba6dc655b1ac333893b0dfba08f0b1ed13872c4983454d99c6d983f830ef7e6297cf7f27f15908be9f00cbe7565986f9ef247e1a82e57360f9995596f43b89ffb25ba6ff4ee20be0e7bab29f146cc736ffc272dde2e093cbe575e4db1659176611abe4801b56c90161951c1056c90161951c1056c90161951c1056c90161951c1056c90161951c1056c90161951c1056c90161951c10d6f6ce01c5f299c19984fd3e8b001fdb7ee6902569b0a829d37722417c98773fb7cbe77f53f36508be9f03cbafecb2f8ff7fdf2f42b0fc0a587e6997c5ffa6e6d776cbf4bfa9f90af8b9aeec2705dbb1cdbfb25cb738f8e472791df98475fb66552c5f1a9c49d8efcb08f0b1ed970e5992068b9a32f54b417cd896bfb1cbe7f7e15f87e0fb0db0fcce2e8bdf87ff770896df01cb6fedb2f87df8ffd82dd3efc3bf017eae2bfb49c1766cf36f2cd72d0e3eb95c5e473e61ddbe5915cbd7066712f6fb3a027c6cfbad4396a4c1a2a64cfd52101fb6e5efedf2f97df8fa107cbf07963f3a60f9df102c7f04963fd865f1fbf0ffb35ba6df87ff09f8b9aeec2705dbb1cdff64b96e71f0c9e5f23af2650bab62596f702661bff511e063db1f1cb2240d1635653a7f82f8b02dffe280efcf21f8fe027c7f0ee0fbab03be6f43f0fd15f8be0de0fbbb03bebf85e0fb3bf0fd2d80ef1f0ef8be0bc1f70fe0fb2e80ef7b077cff0cc1f73df0fd3380efdf0ef8fe1582efdfc0f7af00be78dc3e9f0994898ffda76047e4eb6097cfbf7fc809c1c7fe154bc272ac5499b976cbac5365e6598e992aa3230489e3970b6dc7dbf3205e1d2dc72b0e3eb95c5e47beb6b2f68cb52fab03bf0d05b1f47d4d8ee18bdfb9205327bddc01ec7ceea9d524c74eaff3fed7eb7d12b0cfb0647a5ea863cc530ec438e920c63835c27212fb153df589104b518458ba4488a520422cc908b1e44588251121965e1162e91a2196c208b1e44788a56384583a4488a577845872e3d161e91ca1b8a422c4d229422cb9116289b7334b32b6e9f36c12b6e7c27e39c6b12a8ef716b66e4f697b0e9453a06d8980b2535076be5e2e886f7a2cc628e52046e8a711d6d9573e3014c4db9f2537422c9d22c4928a104be708b1e4c6a3c3d23b4271e91021968e1162c98f104b618458ba4688a5578458121162c98b104b32422c051162e9122196a208b1f489104bce5662e1fb7e2e37df60694fbf8576fdfadfea7406bffc1c54087167ff9d81a3b35d8e119b7bdfd2c5419c716a8465f6b5b9f72dedcd52142116ccc9f666e912a1b814448825192196bc08b12422c4d22b422c5d23c452182196fc08b1748c104b8708b1f48e104be708b1a422c4d229422cb9116289b733cbe6deb7f0767c4fd2d5781650b61d8ce7147c2f833eb89cae60e33e84cb50edf278e1a60cf8fea65b00171f8ffed84fb7f8a6c7ba8e7937e379b69bc187ef6fba39be976e0b4b6e84583a458825152196ce1162e91d21960e1162e9182196fc08b1144688a56b84587a458825112196bc08b12423c4521021962e1162e17bcf28b01445282e7d22c49213c0d2c32ecb707c66e0c958dde819a807b074b71c1755664fbb65fa7f1bd5cb7299aa8c220812c78fd953b0bd17c4abc8411ef58c6fdc4ebc8e7cc2ba7db32abfbdadfa4dff7f833d43f41bbd1dc64095d9c7c1395e0c15e2baf681f62d0e68df6207eddbc7685f5e473e61155661155661155661155661155661155661155661155661155661155661155661155661155661155661155661b5cfaafcee68d56f83ffcd05fa5593b1bac1570cfcbb88812ab3afdd32fd6f2e4aa0425cd7bed0be2501ed5be2a07dfb1aedcbebc827acc22aacc22aacc22aacc22aacc22aacc22aacc22aacc22aacc22aacc29a2dacca6fa95dbffedf17a35f3519ab1b8d59973a8c812ab3cc6e99fe98b50715e2ba9641fb7a01edeb3968df32a37d791df98475fb66557ecbadfa4dbf972a0b718e973b8c812ab3c2c1395e0915e2ba5640fb5606b46fa583f6ad30da97d72bddf9f5eb5ff503f5af0ae0a8da8af547beb6b2f6ca225689abc455e22a7195b84a5c25ae125789abc455e22a7195b84a5c25ae125789abc455e2da7656e5b7daaadff46f62a25f3519ab1b8d83573b8c812ab3c66e99fe38703fa810d7b506dab75f402ef673d0be3546fbf23af26d8bac9512d7ed9e55724058250784557240582507845572405825078455724058250784557240582507845572405825078455724058250784b5bd7340f9adb5ebb72169f85593b1bac1570cfcbb88812ab3bfdd32fd6f2e064085b8aefda17d0704e4e20007eddbdf685f5e47be6c61557e073ac8c5fe217271a0c318a8320739c8c5c15021aeeb2068dfc101ed3bd841fb0e32da97d7912f5b589360cb89b5da787b026c43b4ad03d8866a5b2ed8eaa04e6cabd7b68e606bd0b64e601b065c3c1fae6d7dc03642dbbac0fe3be9e5ee601ba9977b826d67bd5c04b651ec036cbbe8e562b08dd6cb7dc136462f97806dac5e2e03dbae7ad903db38bd5c01b646bd5c05b6f1c6b555d97633ae71ca36c1e8f7946da2d1ff28db2423ff946db25ece8fb5daa640ceb26daab615806d9ab615826dbab67506db0c6e37b0cdd4b6ae609b15c0c7f939086c9c9f98cf9c9f43c0c6f939146c9c9f7560e3fcac071be76703d8383f315f396ec3c1c6711b01368edb4e60e3b88d041bc76d67b071dc46818de3b60bd876d0b6d160eba66d63c0d65ddbc682ad87b6ed0ab69eda360e6cbdb4ad116c45da361e6cbdb56d37b0f1b93c016cc5da36116c3b6adb24b0f5d5b6c9602bd1b629602bd5b6a9602bd3b66960f3b46d3ad8cab56d06d82ab46d26d82ab56d16f46ff9c0c875ca87ba302bfa665b1ef86ed4f3ba2d9bfc54663f5c2eaf97031fc7cbdbba7c0d6de52b33f8fcdf9bb0cb528f6dcf53dc586f84e54a60a9b0cce27f9b6db74cff3eaa1af8b9aeec2705db7b42ddaa2dd72d0e3eb95c5e47beaa0056ee77544e78c67e0e6296fe6d1b83b52cc06fed568811f72bb58efdd6187e4b0dbfea3cc1765253a6f3a40678fb59e6f59f7ded96e9df120c00e646f0510af68196eb827ee35aec83ed0958be9a6f1c603f35f1b58699d5b9521bb01f2e571bc7a4607bade33af7078e4658675fea9eee82c25606cb39efb777adc1c0eba560ef1f10af5a88176ff7c0c6f700d8c796186524a11cbcd65aceebfa4cf5c476675b0df0f50fe01b6097af21532e0c003eb6f5031617fda0c9c2d71eec077b19f153b97a3870252c73e5c55a9f5d6c9589cf4d3c65eacff3609e6b99453d6ff173d3ca96e615731736eddd34777e1cb03a1888398086cb387cc18f76387cc18f76387cc1c7e3500597d309b6a9657ea46a5abab865df654dcbe6ad386e794bd3fc99cd0b3178b906cde628912e0fbc35ea79dd964d0df8d0cb53a646ee042c1dedb2f8499cb45ba67f739b0ffc3800a5a6146ccf857df22dd72d0e3eb95c5ecf77e7b78eeb98a9fea9008ed456ac3f0e24250338793b9e7d3830c9f384519edadfcc656b15ea0165c635900250276b6eacf504e9146b1d0952606aa447ddb4a8911c3572a3466ad4c88cea36ba43992fe9b9f2a39ebad415458da4a891133552a2ee20d41d9dbafb57575f7547a29e40bc58faa9483d79aa27517587a1ee28d4555b5d19d5554a5d95d49553dd490d220d260d210d557121d5931a48c348c34923483b91469276268d22ed421a4d1a431a4bda95344ec7773c6937d204d244d224d264d214d254d234d274d20cd24cd22cd2eea43d487b92f622ed4d9a4dda87b42f693fd2fea4034807920e221d4c3a847428e9b058fa0a3b8734977404691e693ea989b480b490b488b4987424e928d212d252d23252336939e968d20ad24a520b6915e918d26ad2b1a4e348c7934e209d483a897432e914d2a9a4d348a793ce209d493a8b7436e91cd2b9a4f348e7932e205d48ba887431e912d2a5a4cb489793ae205d49ba8a7435e91ad2b5a4eb48d7936e20dd48ba897433e916d2ada4db48b793ee20dd49ba8b7437e91ed2bda4fb48f7931e20ad213d487a88f430e911d2a3a4c7488f939e203d497a8af434e919d2b3a4e748cf935e20bd184be7ebcba45748af925e23ad25bd4e7a83f426e92dd2dba47748ef92de23bd4ffa80f421e923d2c7a475b1d6ce184fe05feb393ff5cf6d69695ababcc56b69f696ae5ad2b278f992e3bcd58b5b1679cdc734ad58b0a479351efc627c0b0e7e8dc7f8373d78eefcf99b3fee13bdc267f6b465f39b8ef59a57b578cd0bbc239a572d9bbf12776fd0ddd918bd3e3b7dabe3ad5cd2dce2d579cbe8dfb94bc845d3fc211e6e5b495558d9e2ad6c99bba2c55bb0a279a9573fe4ff01285f3937f75f0200", + "packedBytecode": "0x000000028df71de50000003e021f8b08000000000000ffed9d0774154796f75b4280f0d3b3088e045b3860c004e9492449c023679325030e801019e3210c382272c618b0c946e0999d4db339cfe69c739cd9303bb333bb3b3b73ce37bb5ffecef1f9aafad51dfd55543ff4e4aec77dd2ed734aaffaaabaefaffe7dab3a55777f270882a22033f550e9e9e0ee89fe9f36bf959f6eaa8a715d953e398b0a84b3b840387b140867498170f62c10ce5e05c2d9bb40384b0b84b34f8c9c9aad38683fc5cdfb80075de3664c1498a66505a069b2c0347db000342d0f0aa38fea5b209cfd0a84b37f81700e2810ce870a84f3e102e17ca440381f2d10cec70a84f3f102e11c58209c830a84737081700e2910ce270a84f3c902e1ac2810cea105c2f95481703e5d209ccf1408e7b331728e00ce61e6f739f33bdcfc529991e6f779f33bcafc8e36752c31f363541aabd954aab2fe9752a95aa51a95c659ff1bafd2049526aa34c9fcafc2fcaf56a53a95ea559aacd21495a61a1da6a9345da5192acd5469964ab3559aa3d25c95e6a9345fa5052a2d5469914a2fa8b458a5252a2d5569994acb555aa1d24a951a546a54e9459556592cab555aa3d24b2abdacd22b2abdaad25a95d6a9b45ea5269536a8d4acd2469536a9b459a52d2a6d55699b4adb55daa1d26b2aed54e975953ea3d22e9576abb447a5bd2a7d56a57d2aed57e90d4bb337557a4ba5b7557ac7e27c57a5032ab5a87450a5432a1d56e9884a47553aa6d271954ea87452a5532a9d56e98c4a67553aa7d27b2a9d57e97d952ea87451a54b2a7da0d2872a5d56e98a4a5755baa6d275956ea874d3b05043f848a55b2ab5aa745ba53b2a7dacd2e754fabc4adfa7d21754fa7e957e40a51f54e98754fa6195bea8d28fa8f4a32afd984a3faed24fa8f4932afd944a3fadd2cfa8f4b32afd9c4a3fafd22fa8f425957e51a55f52e99755fa15957e55a55f53e9d755fa0d957e53a5df52e9b755fa1d957e57a5df53e9f755fa0395fe50a53fb234ff6395fe44a53f55e9cfccffe83ad89fabf41726ff97e6f7afccef5f9bdfbfb196f95b95feceb27d59a5af58b6bf57e91f4cfe1fcdef3f99dfaf9adf7f36bf5f33bf5f37bfff627ebf617ebf697effd5fcfe9bf9fd77f3fb2df3fb1fe6f7dbe6f73b2add1c9cc997066d533a88a94faa696ed6f75048ec6141fb496bd1c3fc8f7e2b8cbdc4ccd32f69d7d3ccf7b4ecbdcc7c2f6b3da566bed4b2f733f3fd2cfb00333fc0b23f6ce61fb6ec8f9af947c19e08e05aaab16b5b0f632a021bc56131d87a06ed35d1b65eb43ab0f50eda6ba16db41d7b81ad8fb1f506db03c6560ab684b1f521cd542a33b67410574c54aed3eb4dc6bd5e737fe9c1f8799bf47acb3df1f68d9fb759afb79f075e1d1ffdcdbafa42dc0c30b67e607bc8d8fa83ed61631b00b6478ced21b03d6a6c0f83ed31637b046c8f1bdba3601b686c8f816d90b13d0e36d3ed0503c136c4d80681ed09631b0cb6278d6d08d82a8ced09b00d35b627c1f694b155808dc6ae0c05db33c6f614d89e35b6a7c1467dea3360a363be678d4df7133d8b601963a73e2a5c86fa61b00da73e186c23a8ff05db48ea7bc1f63cf826db28e857c836dad8a88fd2ff9b68f2e920ae36910adbc4a4b8d7abd6acd75b17ff7ac3fb71f5419bae69f03309b49a6cf2318ef9a942df4526911fb297407e2e94a572a407ed67885def4f6a4d7e7296e5265acb25a14cada3fee920defad7593c7516734fc8fb89d9ea94c46c87a79c63b601cadab147c73c5d316617008787981d2f31dbe129e798dd0065edd8a3e3deae18b3ab80c343ccaef313b3a94a89d9ccf5af2070c71e9dfb74c598dd041cf1c7ec3889d98e4f39c76c0b94b5638fce7fbb62ccee058ef86376c23a3936e8f09473cc9e83b276ecd1b598ae18b38781c343cc364b3fdbe129e798bd0165edd8a3eb825d3166df078ef8637692a798ad96980d32f73283c01d7b748dba2bc6ec2de0883f669be4fa6cc7a79c63f6e7a0ac1d7b74bfa42bc6ec178123fe98dde0ebfa6c4a623633862308dcb147f7eeba62cc7ec9e4f5bdb1bf34f7c69e00db5f19db9360fb6b187b40b6bf31b6a1502f0f6d60a2b4810e4f39b781bf85b2762c3f65f25db10dfc11707888d97512b31d9e728ed96f42593bf6684c43578cd9af008787986d9298edf09473ccfe77286bc71e8dafe98a314be343f5f1c23f9ae385e160fb27631b01b6af1adb48b0fdb3b13d0fb6af19db28b07dddd84683ed5f8c6d0cd8be616c63c1f64d63ab04dbbf1a5b15d8fecdd85260fb7763ab06dbb78cad066cff616ce3c0f66d631b0fb6ef18db0463d3f7b1684cd5ef1a5b2970a583f8b66d0234a0a9c89a4f43beca2f4f651278d05775fcbeaa75dd5341c7eb5e0d3c351eea9e001f1de1a9019e71f1f384e349c7c7bfde701ba72c4d13e02b05f59ae0a15e45e08bd64df3e42f09366cd3131c8cb1ef9fd57eb4087cd1ba697e2230920dfb18ea73a9fde8be7948511baf87b614ee9fd15f1a38c85f09941937b8adec50c35606ffc7fe769c65f31497615c902f5a37cd93bf32a8cfb8fc33a63aca586331faea238ac017addbf65d06f94abffa64e519cfc477ad27df769f469ad7e6c1f744cb77b5e51bfb4e9ab2eddb2602b387f394aafb719e82c70f1cce536616b595b5cf37a81fcef53c6582b51cc7f39449b02ff4d01ec218a8b53868be1ab4ab8bd0ae16b4a332cf8176befaf149160fcd8f031eeabfb13fabcc334f2503df780c4bdb0dcfa5f038c0d7f6aab41869deb5bd2602a3eb58c5c3f94cd663951a60241b5ec74979d22c6abba698f8f6102b617f443ee8d89cda2ff92b81320b7ab4955d0b7da58f18c178a4a9a3e7bcf16fa754780e5e93030f6e3b0fe755559ee2b112afdf7c12c41b6b76bf54636915758dc7575f9eb278689efc09b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300b337f66bc9f84e3b6a8dc38268cf6f8375fd7f9c377ec9975e13da0ef7a1d0f96aac4b130340e628455e71228535edcc6f63f603c983d96286a5bfa181b9b6d5b923f1c0f968f7b88d5168fedbbcca10fde9746cd7c8d81b2fb0c9ac7f169a45f25f0f86a8f55168fed1bfb8c1453cda2fa595f630ba2e2cc359eb02236dfa9265ff775f5fbccf43b41edfdd7384bd3f05da3964df7492ff468abb78ffbbcb9de77c6fd06e5e3bc8f9b041ef4157f3f9b6a373ea13868bfafc058f735568bda158d8da8b57c97409921c56ddba60efe9f0eeede3760195a37cd8f8065ebac7597fbab6fd67128b5c04df95e56ddc6033795790af6dd7f66f29ef681a95c9f91c07d72fcfb97cc7891540e3cb8bff371cce2693f5a89f118f778117b1ca4eb7899cae018520fe377b3ee8bc99f300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330f367d63cf63d74bcf75bcd84314f636cc2fb19f42e36bc2ff693c56d7e7ddf03a47b4e23ad3ae333ca013ca3fcb3860dc73ee07ba55cdbd2d7bdb5a86d49feb88d7d2873e8a335ab736856ef89d1ee3368be1e1849bf3ae0f1d51ea3dedde1ea332a996a16d5cffa18bb902dce5ce3142a62f39d192fe2e3be2e8d17b1f75ff67b8d709c04d9f03e78d4fbc2aa2cdbfdee035ce3da288fef5c88bfdf4cb5bb076c8f15247f384ee22b465b1a27117f3f90aaf4b98fa0364a6342528eba5299af16b795fd9ac9e358a16a58d7771dffa729db9804ec53a7c45fe770fb4e35eba2ed3bc5e13b0dac31f9ae42df45d6bac95e02f9ff567c3703e9415a13bb6e23f81eaba8e56aace5925066b2a3fee998eb3fc5e2c16dac271d3bdf8038fb2e1cebf9ea93264768340234a2329edf03eb1ce76b8f55c67eb4b7558696c5f75bfe1fe8a3a2c6a4bbf601be8e17a2f60178bc60ef173a3276bcbb8f07ec63ce437c8c07a4759707edc7e405d6fa47c2fa89ab7710bd6ff9deb938acdfe798f57bbdf7ca75ee47bc38de90caf48773bf99269fcbb9dffd3a8f779dfbe1725175c77e21ee7d23c623b2e0fb22a9cc602b1eeb22b8273a967d326259d2ca7ef7219e97e23142fcef8dccf43753acba509b9a0c75a132cf5aed26fe63a6ccf1a7af7764d2b10ef541558eba529991d0d646997c02b613ee17ea1cffa729dbf127e9a7eb3c2dfe3a87db77ba59176ddf690edf33803526df55e89b8e3fc90fd94b205f0bfb132a477a90d6c45e069cc86e2f576b2d9784326947fdd331d77f9ac533cd62d6b13316e2ac0e9eb5f0d557a703b7462341a3eff9039bebbdc6ae7d8cafe7d1a2f63155c068f79bb89fcce7b372f6f55bd7f10995c163682a330ffad984a3ac7d5d9a968b737c3a3e0f84c785f83c90af73a464d05ecfa4c5e1d377b9e5bb3c8fbefb59befbe5d1b7682e9a73d29cd3377f70df520c8c3ece1bf1fa484718f17d04b45c0f60f4f5cc662a07c66a60c4fd1d317a78bf725567bf2984c73a3d81d1c7f3c6b95eafc6f79be33b0688d1c733dab9bea71a9fdba6e57a03a38fef1ae137943ac2e8fad65129fc7af8ae515567bf0382df3aea038c3ebe0d9208da7fcfe45e8c938091967b00187ddc474a04edafabdd8b11ef57d27209cf8cd9f6ed9ec7fea472bd06918f710551c71ae8dbc3f5ff148e4de88816f57e79b21efba06f0fd7bf422dea838e6b81f7e73cdc1b0ddbf1e41c78f01e222dd71f18a77a629c9203e35460a4e5060063da13e3d41c18d3c048cb3d048c1eae43868ce91c18f17a1dd91f06c6e99e18a7e5c0381d1869b94780d1c735c504f8ed08e30c60a4e51e05c6999e1867e4c038131869b9c780719627c6993930ce02465aee71609ced8971560e8cb38191961b088c733c31cece81710e30d272838071ae27c6393930ce05465a6e3030cef3c4383707c679c048cb0d01c6f99e18e7e5c0381f1869b92780718127c6f939302e00465aee49605ce88971410e8c0b819196ab2800c6a105c0f85401303e5d008ccf1400e3b305c0585a008ccf03e3a2f819c3f3d48539302e029e17e2e709355b9403cf0b7e79c2f7132e72f85a1cbfaf54ae755f0c3c4be2e709b7c5e21c78882109cbbde09731d55946cdb3347e9e50b32539f02c05cd963834f3c098ea2ca3e659163f4fa8d9d21c789681664b1d9a79604c759651f32c8f9f27d46c590e3ccb41b3650ecd3c30a63acba87956c4cf136ab63c079e15a0d97287661e18539d65d43c2be3e709355b9103cf4ad06c8543330f8ca9ce326a9e86f87942cd56e6c0d3009aad7468e68131d55946cdd3183f4fa859430e3c8da0598343330f8ca9ce326a9e17e3e709356bcc81e745d0acd1a1192746e489fb7de38d0e5fab18d49d1890b14f01303e50008c3806c147ff956d0c42a35f7d529dd5c7d7f6ca3606017daff6a4c5aaa0e35aacf6cb93750c02fa5ee3498bd541c7b558033c2f79d022013e3ac2430c4958ae7f01300e2800c6870a80f1e102607ca400181f2d00c6c70a80f1f102601c58008c830a80717001300e2900c6270a80f1c902607cd13363b6f39797bab8efa87395aeee3beabca4abfb96389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389734ebe5ff6e03b013e68ca768d9f1892b0dc8bc2d8a51991a7223e9e4aac3bfa7a8541dd5f71f01479aa3bfa7a9541dd89a1d0185f2e00c6170b805174cc8c41ec0ca3e659eb89e7d51c78d602cf3a4f3c6b73e059073cebe3e709636a5d0e3cc49084e55e2c00c6970b805174141d39318a8edd47476114466114c6fbc158087db8ec6732e72e9d61d43c4df1f3849aadcf81a70934a3e55ef0cb98ea2ca3e6d9103f4fa859530e3c1b40b32687661e18539d65d43ccdf1f3849a6dc881a71934dbe0d0cc0363aab38c9a6763fc3ca166cd39f06c04cd9a1d9a79604c759651f36c8a9f27d46c630e3c9b40b38d0ecd3c30a63acba87936c7cf136ab629079ecda0d92687661e18539d65d43c5be2e70935db9c03cf16d06cb343330f8ca9ce326a9eadf1f3849a6dc981672b68b6c5a19907c654671935cfb6f87942cdb6e6c0b30d34dbead08c2be38b05c0f87201307ad631d55946cdb3dd13cfb61c78b603cf0e4f3cdb73e0d9013cafc5cf13c6d48e1c78882109cbbd58008c2f1700a3e8283a7262141dbb8f8ec2288cc2981be32b05c028db5a18b9327a38bfcafa7cca8e2eee3beaf994aeee3beaf994aeee5be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25ce39f9de19bfef54aecfb0ee041e1fcfd47aaa67a55eefeb665d9fc4a89fd6ea3396563b2cad9250e675d0ef331ef42b02bfb46e9a277fb9320f63c0ecc977ea41b58e3e507ff2f1b2a587f6bfcb53dda3fafa5d5ddc77545fdfd57d47f5f55dddb7c4b9c47977f02d712e71de1d7c4b9c4b9c73f18df992a0edb89ddeafa4d7b1dbe47b9a792aff0a2c4765e6f5cefc9607d2867cf8963624fb8aeee05be25ce2bc3bf896389738ef0ebe25cef9c539c6c3bc3cf004164f9085271ff70f72e119c38c6706339ec9cc782630e3a962c6339219cf66663ccdcc78d633e3e9c18c673e339e99cc785e62c6338519cf44663c29663c5b99f1ac64c6b38c19cf68663c8b99f1bcca8c6716339ea9cc78d630e399c48ca79a19cf36663c5b98f10c63c6b391194f13339e05cc78d632e399cd8c27cd8ca79619cf70663c35cc78b633e3798e194f23339e06663ccb99f12c61c653c68c27c98c6721339e39cc78a631e3a963c6338e19cf2a663c9b98f16c60c6b38e19cf08663c0f32e32967c6339619cf5c663cd399f1d433e319cf8ca79219cf6a663c2b98f12c65c6d397194f3f663c8b98f18c62c653c4802711dcfd8e9304fc7f27d88aad65f563616f0e6efbff1e632f8665f69a7c0fc7baf7808d9e35dbeb581675da0375499b7ce5a79b429dd0571ae6c95f1970ec65c2338a19cf22663cfd98f1f465c6b39419cf0a663cab99f15432e319cf8ca79e19cf74663c7399f18c65c653ce8ce741663c2398f1ac63c6b38119cf26663cab98f18c63c653c78c671a339e39cc781632e34932e32963c6b38419cf72663c0dcc781a99f13cc78c673b339e1a663cc399f1d432e34933e399cd8c672d339e05cc789a98f16c64c6338c19cf16663cdb98f15433e399c48c670d339ea9cc786631e3799519cf62663ca399f12c63c6b39219cf56663c29663c1399f14c61c6f312339e99cc78e633e3e9c18c673d339e66663c9b99f18c64c653c58c6702339ec9cc786630e319c38c6727339e790e1e0fdfcf0b7968bc2aad9be67732f1ed613b84df0dfcaca73aed33ebea65d64bfce4af04ca2cea93f9d5e3757059e2b2c71763acee038d767baa4bd43b99777771df51ef64eeeabea3dec9dcd57d4b9c4b9c73f2bd2f7edf297c3685a6226b3e0d79dcbff878a6c7533ddbeddbe3fe26f07e4babdd96564928f359d06fbf07fd5cc70b344ffe72651ec68019e3a22288372ede88bf4edffbd630e9fa86a52fd6eb4d4f9a46ed43deece2bea3f6215ddd77d43ea4abfb96389738ef0ebe25ce25cebb836f897389734ebedf32f918cf1b2bd187bef64be7036f81df774cbe2846bf7a5d6f9b75d1b79189e31de0a1323f02d7a2a5cd4b9b8fcbb7ecdb24cebb836fce716ee7e91e22beb7dbd73ddea858ccc7fde5fbe93b2a16bbbaefa858eceabe25ce25ce39f97e377edfe13dc49d41fb29db3dc47781e76d0f5a78aa6778ee74c0aad34eab4e492883e772073cd4b308fcd2ba69fe006c874263d63c34961ddfcf48e55e62c248b6b7fdf284edeba5a0fd94ad7d1d001e0feda0ca533dc3f6d562d5e92587ee540663b5c5433d5d6d87e65b603bb41418b3e6a167e7883501e55e65c248b677fdf284edebd5a0fd94ad7db5008f8ffec7533dc3f675d0aad3ab0edda90cc6ea410ff574b51d9a277f85c8ac79d69a3cb126a0dc5a268c643be097a7260175a6295bfb3a083c2d1ef4f154cfb07d1db2eab436b85b772a83b17ac8433d5d6d87e60fc17610666176316b9e7526bfd6fc26a0dc3a268c646bf1ca535399803ad394ad1f3b043c3efa794fba87fdd861ab4eeb1cba53198cd5c31eeae96a3b347f18b6432eccfb0a905974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974ee1cb3e6596ff2c49a8072eb993092eda05f9ef0f99df541fba9c89a4f43fe30f01cf2a08fa77a86e3de8f58755aefd09dca60fb3ae2a19eaeb643f347603be4c2bcaf009945e7ce316b9e269327d604946b62c248b6437e79c27eac29683f65ebc78e008f8f7ede533dc37eeca855a72687ee5406dbd7510ff574b51d9a3f0adb419885d9c5ac7936983cb126a0dc06268c643bec9527153e87b821683f65ebc78e028f8f7ede93ee613f76ccaad30687ee540663f598877abada0ecd1f83ed900bf3be0264169d45e72866d159748e62169d45e72866d159748e62169d45e72866d159748e62169d45e72866d159748e62169d45e72866d1b9fbe8ac799a4d9e581350ae990923d98e78e5a90eef3b3407eda76cf71d8e018f8ffb329e740fef3b1cb7ead4ecd09dca60fb3aeea19eaeb643f3c7613b7475e67d05c82cb1911f66890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e628660eb1a179369a3cb126a0dc46268c643bea97277cefc1c6a0fd946ddcce71e039e6411f4ff50cc7ed9cb0eab4d1a13b95c1f675c2433d5d6d87e64fc07610666176316b9e4d264fac0928b7890923d98ef9e509fbb14d41fb295b3f7602787cf4f39eea19f66327ad3a6d72e84e6530564f7aa8a7abedd0fc49d80ec22ccc2e66cdb3d9e4893501e536336124db71bf3c613fb639683f65ebc74e028f8f7ede533dc37eec9455a7cd0edda90cc6ea290ff574b51d9a3f05db419885d9c5ac79b6983cb126a0dc16268c643be1972795803ad394ad1f3b053c3efa794ff50cfbb1d3569db63874a73218aba73dd4d3d57668fe346c874263d63c5b4d9e5813506e2b1346b29df4cb13b6afad41fb295bfb3a0d3c3efa1f4ff50cdbd719ab4e5b1dba53198cd5331eeae96a3b347f06b643a1316b9e6d264fac0928b78d0923d94ef9e509dbd7b6a0fd94ad7d9d011e1ffd8fa77a86edebac55a76d0edda90cc6ea590ff574b51d9a3f0bdba1d09835cf769327d60494dbce84916ca73df324a0ce34656b5f6781c747ffe3a99e61fb3a67d569bb43772af326d4f39c877abada0ecd9f031e9ae6018fafb80c2c9ec0a10f4d6398f1cc60c6339919cf04663c55cc784632e3e9c18c673e339e99cc78a630e399c88c27c58c6725339e65cc784633e3799319cf62663cb398f14c65c6b38619cf24663cd5cc788631e359c08c6736339e34339e5a663cc399f1d430e36964c6d3c08c6739339e25cc78ca98f12499f12c64c6338719cf34663c75cc78c631e359c58c6704339e0799f19433e319cb8c673f339eb9cc78a633e3a967c6339e194f25339ed5cc785630e359ca8ca72f339e7ecc781631e319c58ca788014f22b87b2c4d02febf1f6c34e6633bd8de33f933602b76f8a07bc5e7c05662f2b48ede2a1d1d7cf7ba51275fe35cd0571ae6c95f1970bcc7846714339e45cc78fa31e3e9cb8c6729339e15cc785633e3a964c6339e194f3d339ee9cc78e632e3d9cf8c672c339e72663c0f32e319c18c6715339e71cc78ea98f14c63c6338719cf42663c49663c65cc789630e359ce8ca781194f23339e1a663cc399f1d432e34933e399cd8c6701339e61cc78aa99f14c62c6b38619cf54663cb398f12c66c6f326339ed1cc789631e359c98c27c58c6722339e29cc786632e399cf8ca707339e91cc78aa98f14c60c6339919cf0c663c6398f1cc73f0ecf7c4633fe745f3fb19f8d6f3b5a08b9e12f07f7c0eec4d4f8cfb2d469a7f131891d7b766e5164fb9a5d9fdf4adeb4ff72a1e34bfb8bdf0b9070edbab3c0f9af5b378fa599add4fdf5a0bbaf74f636c707be138680edb0bc7697ae89f6b12168f9e8aacf934e4cf79d6c7533d2b71dce42731ae576b75ded26abfa55512ca9c05fdce7bd0af08fcd2ba699efc09b33047316b1eba97eb1acfbb900923d9f03d2aefc7cf5393b078f494ad7f7cdfb33e9eea19f6631702b7eeef83ee540663f582877a16815f5a37cd5f70f8ae08e2d5e26207b4b8e8e0b998672dc85faecc670b909983ce9a87c6ae136b02ca2d62c248b6f3c073297e9e9a84c5a3a76cfde325cffa78aa67d8277c10b875bf04ba53196c5f1f78a86711f8a575d3fc07b01d7261be5080cca273e79835cf629327d604945bcc84916c1781e7c3d8795295098b474fd9fab10f3debe3a79e997eec72e0d6fd43d09dca60fbbaeca19e45e097d64df397613b08b3300bb3300bb3300bb3300bb3300bb3300bb330eb32c22cccc22cccc22cccc2cc9759f3d0b3e7c49a80724b983092ed03e0b9123b4fe6be03f2e829db7d872b9ef5f153cfcc7d87ab815bf72ba03b95c158bdeaa19e45e097d64df357613b08b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300b336f66cd43dfb020d604945bca84916c9781e75afc3c35098b474fd9ee3b5cf3ac8fa77a86f71dae076eddaf81ee540663f5ba877a16815f5a37cd5f87ed20ccc2ec62d63cf42e44624d40b9654c18c97615786ec4ce93b97f8a3c7acad68fddf0ac8f9f7a66fab19b815bf71ba03b95c158bde9a19e45e097d64df337613be4c27ca100994567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974ee3e3a6b1efa4627b126a0dc72268c64bb0e3c1fc5ce535d99b078f494edbec3479ef5f153cfcc7d875b815bf78f40772a83edeb96877a16815f5a37cddf82edd0d5992f1420b3c4467e98253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a39839c486e65961f2c49a80722b983092ed26f0b4c6cf5393b078f4946ddc4eab677d3cd5331cb7733b70ebde0aba53196c5fb73dd4b308fcd2ba699efc09b33047316b9e95264fac0928b7920923d96e01cf9df87952098b474fd9fab13b9ef5f154cfb01ffb3870eb7e0774a73218ab1f7ba86711f8a575d3fcc7b01d0a8d59f334987cabf94d40b906268c64bb0d3c1ee22ee4495a3c347f87816f3ddf68f265e617b757233072d85ec93c68566ef1945b9add4fdfbafeab4cfe41f38bdb6b153072d85ee579d0ac9fc5d3cfd2ec7efad65aac36f9bee617b7d76a60e4b0bdfaf9e549252c1e3d653bdef818783e1f3f4f781ef7710e3c9f079ecfc5cf53e5a99e957abddf07ec71ad576bf5054bab8f2dad92500619bee041bf22f04beba679f227ccc21cc58c7d21b126a0dc1d268c64fb1cf0f8e83774dd479975d1fa7baaf450ff36bfadf1fbadc16b0bbdcc7a8983fc9540999707b5b13d66d8cae0ffb4dd747d6e59364fcfbc55b9aef3d23cf92b0bdce7fabeaea1b65a3cb6ef32873e5ab39b0ecd6e7862b49f69a5f91bc0e8baceebeb79d1a8ebcef8bce81d4b476e9ae173c01f018fafe3e2568ba7d5a1858f3697ebf1e5470e9e4fe2e3a9c4d8405f3e6215fbb68ed4ddd57662ac7b15dec3425f1eda40b89f1a6dd645ebd7fb82dafe5e35afc1fe81f653a3ad3a97409949b09f9a92653f551cdc7d5db8c2d8a90cfdff1363b7d75111dcdf6b4b6590af35bf18a36493fd6ffb7b98b5968edc34c376dd0a3cad9e78a2ae89913fdc86750ecdea1868866d211f7176c7e2b17d27419756a69a619ce17183affeec5ed7f2701bd63b34ab67a019c7feacded2919b66aefe0c755ce8e05ec8809b639fb2d0d2919b66ae3e05755ce4e05ec4809b63bb5e64e9c84db37bb5ebc50eeec50cb839b6ebc5968edc34bb57bb5ee2e05ec2809b63bb5e62e9c84db37bb5eba50eeea50cb839b6eba5968edc34bb57bb5ee6e05ec6809b63bb5e66e9c84db37bb5ebe50eeee50cb839b6ebe5968edc34bb57bb5ee1e05ec1809b63bb5e61e9c84db37bb5eb950eee950cb839b6eb95968edc34bb57bb6e70703730e0e6d8ae1b2c1db96996effb0051f79bc81f6ec34687668d0c34e3d8a7345a3a72d32cdff701ee35061bb7e12a8766ab1868c6b13f5b65e9c84db37cf76751f79bc81f6ec3d50ecd5633d08c637fb6dad2919b6651fd596bfc3c398fb76ff5aa4fe63bcbad39f0e098291f31e5290e2a3d8da90ac7dbdbdfaf68b5b44a06777fd3c2e7d8c3a8f191e44f98855998855998855998855998855998855998855998855998855998855998f933e3f3ccade617df857a870923d9f09e948febfcbaee63ccba68fdfad9de5b03dafcc67fdf225589f75ce9b9e331569d4ba0ccff7dbc8ded63c386f71769bb456dcbfbf56e057c1f05de0bba9ff73b3f726876c3a1d9754f8c769f41f3d781d17effc3fd7ef7c41d4b476e9a45f5b3773cf144c5d91d87ef8ad87ca79a7cddd7d5ef22ec13dcbdffbae3d0d4471ce6faee0b6c17ad1e787cbde742d7e9ba55a75b569d92506618d4f37eb62d9ae6018faffe28b07802873e341533e399c18c670c339ec9cc784a99f14c60c653c58c6724339e6798f13cc18ce731663cfd99f1f461c6d38319cf7c663c3399f14c61c63391194f8a19cfb3cc785632e3799219cf32663c8f33e359cc8c6700339e0798f18c66c653c28ce779663cb398f14c65c6b38619cf24663cd5cc78f2710f34179e61cc782a98f10c64c6f310339e05cc7812cc787a32e399cd8c27cd8ca79619cf70663c35cc781a99f13cc78ca78119cf50663ccb99f10c62c6b38419cfc3cc781632e32963c69364c6d38b19cf1c663cd398f1d431e319c78c6715339ea798f10c66c6f308339e11cc781e64c653ce8c672c339edecc78e632e399ce8ca79e19cf78663c95cc785633e3799a19cf0a663c4398f1dc66c6b39419cf22663c8f32e3e9cb8ca71f339e51cc788a18f02482bb9f5dc2e7e56e818d9eb169055bb1637d342e97caebe3ceb383ef5e77b163dd371c0ca8d335a84bdae42b3fddd4eeb9a222b35e9a277f65c0718309cf28663cfd98f1f465c6f328339e45cc789632e3b9cd8c6708339e15cc789e66c6b39a194f25339ef1cc78ea99f14c67c63397194f6f663c6399f19433e3799019cf08663c8f30e319cc8ce729663cab98f18c63c653c78c671a339e39cc787a31e34932e32963c6b39019cfc3cc789630e319c48c6739339ea1cc781a98f13cc78ca791194f0d339ee1cc786a99f1a499f1cc66c6d393194f8219cf02663c0f31e319c88ca78219cf30663c3799f15433e399c48c670d339ea9cc786631e3799e194f09339ed1cc781e60c6338019cf62663c8f33e359c68ce749663c2b99f13ccb8c27c58c6722339e29cc786632e399cf8ca707339e3ecc78fa33e3798c19cf13cc789e61c63392194f15339e09cc784a99f14c66c6338619cf0c663cc5cc78e6593cf87f7dad81ae2f5e071bfdff3fcdcdfb72538feb96bf18ea5119f56d1e5f9ae194766812f56d1e0e3c3398f18c61c63399194f29339e09cc78aa98f18c64c6f30c339e2798f13cc68ca73f339e3ecc787a30e399cf8c6726339e29cc782632e34931e3799619cf4a663c4f32e359c68ce771663c8b99f10c60c6f300339ed1cc784a98f13ccf8c6716339ea9cc78d630e399c48ca79a19cf4d663c15cc780632e3798819cf02663c09663c3d99f1cc66c69366c653cb8c6738339e1a663c8dcc789e63c6d3c08c6728339ee5cc780631e359c28ce761663c0b99f19431e34932e3e9c58c670e339e69cc78ea98f18c63c6b38a19cf53cc780633e3798419cf08663c0f32e32967c63396194f6f663c7399f14c67c653cf8c673c339e4a663cab99f13ccd8c6705339e21cc786e33e359ca8c6711339e4799f1f465c6d38f19cf28663c450c78a2be8543ffef01b6ab267f1b6c574cfe26d82e9bfc75b07de8b0153b58c8df55b0d138972b60a37b7597c146d78bc8973edebd38f86ed662479d7a3858af38ea74d5b12c6e475a261dc4bb1dd1571ae6c91f7eabe72a139e51cc78fa31e3e9cb8ce751663c8b98f12c65c6739b19cf10663c2b98f13ccd8c6735339e4a663ce399f1d433e399ce8c672e339edecc78c632e32967c6f320339e11cc781e61c6339819cf53cc785631e319c78ca78e19cf34663c7398f1f462c69364c653c68c6721339e8799f12c61c6338819cf72663c4399f13430e3798e194f23339e1a663cc399f1d432e34933e399cd8ca727339e04339e05cc781e62c63390194f05339e9bcc78aa99f14c62c6b38619cf54663cb398f13ccf8ca78419cf68663c0f30e319c08c6731339ec799f12c63c6f324339e95cc789e65c69362c6339119cf14663c3399f1cc67c6d383194f1f663cfd99f13cc68ce709663ccf30e319c98ca78a19cf04663ca5cc782633e319c38c6706339e62663cf32c1ebca6580936ca57818df229b051be1a6c94af011be5c7818df2e3c146f90960a3fc44b0517e12d8284ff78cf0f99e7cbc178e7cd1ba69fe1a30de3679dc2694af03ee0f2c9be6bee489fb038b9be62f0123d5e103b051be1eb82f5a36cd7dc113f7458b9be62f0023d5e122d8283f196c949f0236ca4f05db54f04736ca4f031be5a7838df233c046f99960a3fc2cb0517e36d8283f076c949f0b36cacf031be5e7838df20bc046f985e6576fe3f72d9bdec6e74d3e1dc4bb8dc917ad9be6cf03236deff7c146f945c0fd9e65d3dce73c71bf6771d3fc3960a43abc0736ca2f06eeb3964d739ff1c47dd6e2a6f933c04875380b36ca2f01eed3964d739ff2c47ddae2a6f953c04875380d36ca2f05ee93964d739ff0c47dd2e2a6f913c04875380936ca2f03eee3964d731ff3c47ddce2a6f963c04875380e36ca2f07eea3964d731ff1c47dd4e2a6f923c04875380a36caaf00eec3964d731ff2c47dd8e2a6f943c04875380c36caaf04ee83964d73b778e23e6871d37c0b30521d0e828df2f83efa359e186f5b8cb72ddf781f178f2d0f5836cdf8ae27c6031623cdbf0b8c2d267f00780e78e269b1786cdf49d0650d53cd92606b019e5a4f3cd72c9e6b961638de0dcf05d658369fdb758dc548f30780b1c5e4f3d1365b2c1edb771274a965aa59126c2dc053e789e792c573c9d2029f73c173b75acbe673bbd65a8c765f8171867d85afb6d962f1d8be93a04b1d53cdb0cf6d019e7a4f3c172c9e0b96166590c7f3c73acbe673bbd6598c765f8171867d85afb6d962f1d8be93a04b3d53cdb0cf6d019e164f3ce72d9ef3966fdc8678bebfd0b2f9dcae0b2d469ac73ed76e0ba5908f9ba7dee2b17d27419716a69ab9da82cffeec9cc573cef28ddb10afcf2cb26c3eb7eb228b91e61702638bc9e3365ce489a7c5e2b17d2741977aa69ab9da4229b0c5cd73c6e239636981e3f6f07a5abd65f3b95da3fa8f45c0d862f2f9689b2d168fed3b09ba2c66aa191e43b6004f8b279e5316cf29cb376e43bcfeb9c4b2f9dcae4b2c469ac73ed76e0ba5908f9b67b1c563fb4e822e2d4c3573b5059ffdd9098be784e51bb7215eaf5e6ad97c6ed7a51623cd2f01c61693c76db8d4134f8bc563fb4e822e8b996ae66a0b3efbb36316cf31cb376e43bcbfb0ccb2f9dcaecb2c469a5f0a8c765b28857cdc3c51fd19f94b822e2d4c3573b58552608b9be788c573c4d2a20cf2783fa8c5b2f9dcae2d1623cd2f0346d2aa05785a3cf144c519f94b822ecb996a96045b3ef69b872c9e43966fdc8678ff6e8565f3b95d57588c34df028c765b28857cdc3ccb2d1edb77127459cc5433575b401d1b807ba565f3a9ed4a8b9be65700e362878e2b3df144f5292b41c7064b476e9ab9e211756c04ee06cbe653db068bbbc1d2d6158fa5908f9b27aa5d37808e8d968edc3473c56319b0ad02eec596cda7b651eda80118975bdafadcef456debc5a023e9d2c85433bcae89db9ad8560377a365f3a96da3c56db719dcd6d8661a3df1446deb46d0917459c55433ec7bf07cc8d7f947d4fdae7cf88eba07920fdf51d7c5f3e13bea5a693e7c47dd47cf87efa86b2af9f07daff36c9fbea3ae59e6c377d4795f3e7cdfb67cdfcea3efa8f16ff9f01d3526aaabb76fd99774af7dc9fdecd7baebbe44fa739efdf9eaf87da71241fb731a3d1559f369c8e3f9cb2a0f5a78aa67259e137e12e37a5de7d6cb2dadf0dc1acf517d9dffadb678689efc152233c645517cbe2bf13a0c7edf91ae8b54828dae8b55818dae8ba6c0d662f2d560a37b323560a3fb81e3c046f7a2e7838dc6412c001b8dc1b900361afff53ed868ece179b0d1b8d7f7c04663aecf818dc6fb9f051b3d6b72066cef98fc69b0bd6df2a7c0f696c99f04db9b267f026c6f98fc71b0ed37f96360db67f247c1f659933f02b6bd267f186c7b4cfe10d8769b3c5e7bdf65f2782de733268fd7f25e37f9f160db69f213c0f69ac94f04db0e939f04b6ed267f1b6cdb4cfe0ad8b69a3c7e5f748bc97f00b6cd267f096c9b4cfe22d8369afc64b0359bfc14b06d30f9a9606b32f934d8d69bfc34b0ad33f9e9605b6bf233c0f6aac9cf04db2b263f0b6c2f9bfc6cb0bd64f273c0f6a2c9cf05db0b263f0f6c1f9bfc41b07dcee4f13a68b1c9e3f57b7adf14def3a2775ee23d4f7aaf34de6fa76f7fb4808dbeaf85e38c4a4d1ec7b8d17ba5707c25bd4b12c7a9264c1ec79597993c3ed340dffdc06743e8db51f85c52b9c9e33371f4cdcf0360a3ef92be0b367af7d43b601b60f26f838ddee9fc16d8e83b176f828dbeddf406d8e87b9ffbc146ef98da07b6c74dfeb3601b68f27bc136c8e4f7808dbed1b41b6cf49dc85d60a377497d066cf47ec4d7c15661f23bc136d4e45f03db5326bf036cf4fdc5ed60a377466d031bbd77702bd88699fc16b0d1f70e36836db8c96f021b7dc76b23d8e8dd50cd607bdee437806d94c937816db4c9af071bbd9b671dd8c69afc5ab0d13efb55b0d13efb15b0d13efb65b0d13efb25b0d13efb45b0d13efb05b051dfff31d8a8efa7fe43b753dd7e6f99f97410df7194f6d71ab49fb21dcb1303f2c4796c9c041ef47533f6baa7c2e3f08fccba8acd7a295e6e82efebb1fbce9c03dc30ebea69d67bddf25d02654a07b66d9b6bf0ff34d48196c332b46e9a1f03cb5eb3d65d6eea7bc3537daf5b4cc47d0398a84cd9c0b6b25f32f952582646b6f07c96622d000d714a439e18fc68950acf2f3eca81e706f0c4df4e32e7d73e6202db56dce7d7f675193bd69250e63ae8e7ebbd58372c1e9a277fc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc2cc9f59f3d0fd04624d40b95b4c18c986f7ba7c5ce7c77bae78cfebe6c036bfbeefeff532eb1d6bd5b904ca7c6b601bdb6d932f83ffd3768bda961eee1366dd96dfbb5706f5c17b411eb665c873d3e2b17d9739f4d19a5d736876d513a3dd67d03c7ef385f4bb063cbedae3758bc7f68d7dc60da69a45f5b33ec625648b33d718848ad87ca79a7cddd7d563a1f4580e7bff75cbd214c740e03df32f419f44cbdc31bf09d0e70ee8733ffb007b5c02f653adc0187fbf996a770f98fafe3196a63806e2b78cb6340622fe7e2055e9731f416dd41e5b8175a532bf0ffbb93f34791c07740bd6f515c7ff69ca362601fbd4cbf1d739dcbe1f9a75d1f6bdecf0fd01b0c6e4bb0a7d1799447ec85e02f92f0f6c2b6b7f678ab42676fc1616b2dbcbb55acb25a1cc1547fdd341bcf5bf6cf15cb69875ecfc09c4d957e058cf579f742542a331a01195c1635e5ffbaf8f2c1ee2207fd88ff6b6cad0b22550e6ebd047e9ba503fdf6a7ea3f601be8e17a2f60178bc60ef17128e3aeaf8b835a08db7bb8ff5fb2fe82faec1ffd3c1a71febf75f1043aee3525aff58583f71f50ea2f72d54e67f59fb511fe793b82d6d3d712c2195f97fd00fa50665f2b99cd7ddaf73f4a8f33a1fdfcec4730d9ab2eddf711fe3a37ff154cf4ad7beeb9a55a724941906f5f4701ce3dc6fd1fc65f0edeb7ba9e4838ea1ae5b5a944099a4693bd47744e988d7256ee4a52e29e7f1e058475da8cc00a84b29d8e364f2b9ddf0384baff7a6a3ae54e6b1416d65079a7c02b613f6a5231cffa7295b7f40fae93a5f8cbfcee1f6a5e71669fb5e74f87e1f5863f2ddeefd1574bc4f7ec85e02f9e183dacadadfee24adf15bacf47c1db2dbcb5db7964b42994b8efaa78378eb1ff59d59f2a7636708c419c591cf7ef35284466341232a83f70aeceb2d51fb7d1f63e9b3edf76f02a3dd6fe2b18b4f36fb9cc5be5eee3a1ea43278ce426526403f9b7094f57f1f20736c83f5a27a04565d03abae9e8e5f6b8a2c3dd3e06734d8293e4967fa1f1ee3529969d6feccf7756ce2a67ae0fdbaab16f7354b57bc16351bb875dcdbe716789ceef99cb6068fc5ece3a1abc04e65165ac743f671dc6d475decfd747170f7b9e02756597c3629db7276fe236b19bc66e0ba268b7ddf1560499b7ce5a799aa2a2b91a9d8a185ebbea9ab4fa2768031675f47196dad07afa3acb1fa24bbacee936afbb7e943db11afb5dbd7df3d3d9b16b6b95b56fd6d8d3463abc9e336f4710fa33b3e9b561adb7a27ad2fc4f10ca5563e1edfa90db8afc8a6c555078faf6b9a515a5c75f88e4f8bf14daefd874b8b2b0e1e5fe798515a5c71f88e518b8dae6b0b2e2d2e3b787c9d6b446971d9e13b3e2d26b4bbae914d8b0f1d3cf15fd3c8ae05de13cb85f90a03e6522b1f8fef9af5ae7b772e2d3e70f0f8ba7717a5c5070edff1695135de75ceeed2e29283e7529eb5b8e4f01d9f161327b9aea9b8b4b8e8e0f1707d2dab16171dbe638c8b66bcbe964d8b0b0e9e0b79d6e282c3778cc787e3b35d33442dde77f0f8baf617a5c5fb0edf316ab14efb3edf012dce3b78cee7598bf30edff169b17e9cf6fd5e07b478cfc1f35e9eb578cfe13b3e2dd64dd4becf75408b730e9e7379d6e29cc3778ce750615c9ced8016671d3c67f3acc55987eff8b4d8101e6b9de98016671c3c67f2acc51987eff8b4a80cf7a9a73ba0c56907cfe93c6b71dae13bc6b808cf274f75408b530e9e5379d6e294c3778cfb91302e4e76408b930e9e9379d6e2a4c3777c5a6c0caf3f9de88016271c3c27f2acc50987ef18afb9847171bc035a1c77f01ccfb316c71dbee3d3a23adca71eeb8016c71c3cc7f2acc53187eff8b4680eef891ded8016471d3c47f3acc55187ef188f3bc3fee24807b438e2e03992672d8e387cc778dc195ebf38dc012d0e3b780ee7598bc30edf31f69de171e7a10e6871c8c17328cf5a1c72f88ef1b833d4e26007b438e8e03998672d0e3a7cc778dc19ee475a3aa0458b83a725cf5ab4387cc7181761df79a0035a1c70f01cc8b316071cbe63bcae15f69def76408b771d3cefe6598b771dbe633c1f09aff1bdd3012dde71f0bc93672dde71f88ef15e51780cfe7607b478dbc1f3769eb5781b7cfb1867825ad058ac5196162550e681c1995f1a8b15a523ad039fa1c5babc157b5d32e3cade8ca8cb5b50172ad317ea520af638993cd5358c19fa96028d4d6f75d495ca3c3cb8adeca3269f806d721bd635ccf17f9ab28d4122fd749df7c55fe73056e91b10b47df7397cef05d6987c57a16f1a9b4e7ec85e02f96707b795a572a407694decba8dd0373090dd5eee6d6bb92494d9efa87f3a88b7fefb2c9e7d1673f8dc03c419c5919fbe2bc3b43f42a351a01195c1317bad9e78ec3184c441fe7419dafebdad32b46c099419037d148e2ba57a2682bbc74deafabde1a97ee48bd64df3e42f09b61bc068d751c7c74330f693be0142df07d136fade077ebf6bbc65d3759de0a9aee48bd64df3138091be3f323eff8ca98e328eb31835cf240f9ae1375568cab6bf98043c133df078aa67b81faab5ea34c1aa5312cae0b38db51eea59047e69dd345f0bbe7d6c73d482f6c9c32d2d4aa0cc42ebf8314a475a878edff18ebaf8d2719cc533cee17bb2671d69ddd4274ece83ef3acb778de55bb76d8c313d656bdb75c05cef8159af774afceb0ddbf654b32e8a67f25303754a830671d5097d1759eb267b09e49b06dfcd407ad0be93d8753bc2d8895a6e92b55c12ca4c76d43f1d73fda7583cb88df5a48f1b5e84e34a0fed218c81c91607cdd780765322b49b0cda5119dcf75679d2aedee2a1f92ae0a1e3ab5ab0d1710a7ee392fe9fca03b7ddefd53ab8c986df3cac72308e8f9f313cceaab218697e3c3092ad1e78ea3c69666febe1963e784cd0db2a43cb964099fdb05f4e38ca86cf1d17b5d58bbea5f9498cf5d2ebede5412ffcce6700fa04968634114369d0f62dd038791e08dabef5b97bcfce5deb36352f6bcedcf624b4120b137f8b1cd528061be67b386c41d0fe93a62560a34f9af6045bb1250b7e4a95cad3a7137dc8857ad0ba4b2cce526089d3377e0e96a66ca1d31b787c84b20e1dfa24ac099dc65d5bf634637cf4b4383b133bfa7f3db2948b5a17c5418987ba2313ad9be6c99fd6873e8ffbfabaa66dd3766ddabba3f9b53dbb11d66e5c982fb244b07f5dcb60906063a2f5f4b4c4e913bf3835d8786dbe00fc05c012189ed2f879c240a56f0837addbbe7dc9def5dbb734cddefb5ad39e2d3b5f43457b5bca45a96d37793db9ba3a2c6b97efe5b0d9137eb1b937d8e88bcda56023ff7dc0461c0fc0ffec2de1a54d0c83f55318ebff95980af73215a210a4dd90ee4f749bd1af4dd5bb7ffd8968fd4968bdf9f4dbe2f4279ef5279df5279cf5279bf5279af52799f5db24f413defac8614890f984f29341e615b14383cc2790f5278f9f09da3e69aca7df055efd09637da8a13f51ac3f49fc7c90b954383ac8bc564dbfc6421fb2ea432b7d98a74f6bf421b83e2dd7875efa7281be74a40f63f421a23efcd1872cfa105c1f7a4f355a4f0b329f34d79f309f19643e51ae3f49ae3f413e37c87c627cbe4a0b82cca7b6170599cf07ebcf87ebcf76ebcf79ebcf7cebcfcfebcf82ebcf85ebcf88ebcfcceb4f0feb4fd0af0e329fda7e29c87cb6f89520f399e3b541e6b3c8eb83cc6794370499cf2eebcf31ebcf346f0e329f75d69f7bde16643e0fbd23c87c4e5a7f665a7f7e5a7f965a7fae5a7fc65a7fde5a5f72d7b71af425787d795b5f7ed5b740f4ad1f7d6958dfb2d4b770f52ded962033e4e150901912a38708e921537a08991e527722c80cb9d44350f5905c3d44590fd9d643d8f5907efd88837ee4433f02a31f09d28f48e947c6f42374fa3148fd58a17e4c563f36ac1fa3d6977df523e8fa56a0bedcdb1a642e09df09329f5ffe9c4a9f57e9fb54fa824adfafd20fa8f4832afd904a3facd21755fa11957e54a51f53e9c755fa09957e52a59f52e9a755fa19957e56a59f53e9e755fa0595bea4d22faaf44b2afdb24abfa2d2afaaf46b2afdba4abfa1d26faaf45b2afdb64abf1364e2f1f754fa7d95fe40a53f54e98f54fa6395fe44a53f55e9cf54fa7395fe42a5bf54e9af54fa6b95fe46a5bf55e9ef54fab24a5f51e9ef55fa0795fe51a57f52e9ab2afdb34a5f53e9eb2afd8b4adf50e99b2afdab4affa6d2bfabf42d95fe43a56fabf49da0ed33e5d8790c363dce5033bf6ecf9ee61dafefa9d8b3b362c7deed7bb6bcbefd8d8a7d5bf66caed8f9d9e65d1bb7efdc870b7fd92cfcb8999fb66bd7ba372ab6bcb6a1797fc5cebd7b2a766eac58bf73ef6b1bdaed2cffb75968f0dd1ed76dd810edacb4c7a7202debd139a783cc72f4a5fa79d9ebf6448f4e08f24c67169adbc90acd357b203a0d5b9e39e6abd8bd7de79e8aca8ad7d45fb573ddb9af79c3980afcdf6e25f2ee3d15bbf7acdbb5a762e3ae9d3b2aaac6e07a17f6e94425bed8c70f4c6ff35ea24e85ca6f0eec444dbe36b0739be33f3f0de9ffeca4d3b2419da861ffce2c347e50e708d3832265d9bd77fd9e5deb9af6442f3cebd32cbca033d55cddc96af619dc0967e59d5968f4e0ce112ee88cb37d39380bfe3f4095c818d45505009b2d6c6f00000027451f8b08000000000000ffed9d69741cc5b5c77b24595e46832d5bde37b1056fb246a3dd968d8cf70dcc8e018317c960b02d638b7d271b092121fb4202bcac2421fbbeef09d9f7852424908484247c7839efbdf3ce791f38afaa5537fa4f51dd6886be72b5e6f639d7537d55d3f7776fdfaaeea9aa6e3f1304412618daaa959c143c77a3bff79acffc0bdb5a123c569e93339312ceaa947056a784b326259ce352c2599b12cef129e19c9012ce8909726ab6aaa0784b9a7712435c9366cca62ca6752988692e65313d2105319d1ca4a38f9a9212cefa94704e4d09e7b4947036a484737a4a3867a48473664a3867a58473764a38e7a484736e4a38e7a584737e4a3817a48473614a381b53c279624a384f4a09e7c929e13c2541cec5c079aaf97c91f93ccd7c2e329f547789f95c6a3e97191f6bcc7e9392e54a9a359ff5373dd15050d2aaa4cdfa5bbb920e259d4abaccdf1acddfba95ac50b252498f92554a562b39ddc4628d923394ac55b24ec97a251b946c54b249c966255b946c55b24dc97625672a394bc90e25672b3947c9b94ace5372be920b945ca8e4228b65a7928b955ca2e45225bb945ca6e47225bb95ec51b257c93e257d4afa95ec577285922b951c50729592ab951c547248c96125034a8e28b946c95125c7940c2ab956c9754aae57728315b31b95dca4e46625b7589cb72ab94dc9ed4aee5072a792bb94bc58c94b94bc54c9cb94bc5cc9dd4a5ea1e4954aee51f22a25f72a79b592d728b94fc96b95bc4ec9eb95bc41c91b95bc49c99b95bc45c95b95bc4dc9fd4ade6e58a821bc43c9034a1e54f29092ff50f24e25ef52f26e25ef51f25e25ef53f2b092f72bf980920f2a7944c987947c58c947947c54c9c7947c5cc927947c52c9a7947c5ac967947c56c9e7947c5ec917947c51c997947c59c957947c55c9d7947c5dc937947c53c9b7947c5bc977943caae4bb4abea7e4fb4a7e60c5fc874a7ea4e4c74a7e62fe46e34b3f55f23353feb9f9fc85f9fca5f9fc95f59d5f2bf98da57b4cc96f2dddef94fcde941f379f7f309f7f349f4f98cf27cde79fcce79fcde75fcce753e6f3afe6f36fe6f369f3f977f3f90ff3f94ff3f98c92fe86a1f2846078eb0d12ea93dafafbf4dc0405fbd4a078d3b1a8367fa3cf46a3af31fbf449b11b67f6c759fa5ab35f6b1d6782d99f60e9ebcd7ebda59f66f6a759fae9667fbaa59f69f667823e1bc018a5d16b5db551654047795805ba7141714cb4ae960e07baf141712cb48ece632de8261add78d04d32ba09a0cb1add448a99923aa3eb0d92ca89fc1e7ddc5cd2c735f3362724cfbb4f1f773213ef94e479fbf571eb1978757e4c35c79a027933cde8ea4167ba95602ae8a61bdd34d0cd30ba06d0cd34bae9a09b6574334037dbe866826e8ed1cd02dd5ca39b0dba7946370774f38d6e2ee81618dd3cd02d34baf9a06b34ba05a03bd1e81682ee24a36b04ddc9467722e84e31ba934047fde7c9a0a3fbbb538c4ef7093519f88ed1537f147e87fa5cd09d46fd2de816515f0bbac5d4cf826e09d826dd52e84348b7cce8a83fd27feb32e5de20a9fc2ff4e9e376277d5c75647ddc95c91f379cd3ea0986e3da0b76ba2156ab4c39c175332d683b6384ec90be06ca1ba12ed5a378d03585d8f5b5638529af8af95e97f5bd1cd459e1f0bf3748d6ff9516cf4a8b791cf8cf93b3ad2d92b323de4aced9f3a1ae9d7b747f331673760b7030e46cbbe4ec88b79273761fd4b5738fee71c762ce5e041c0c39dbcd93b385bce4ecd0585710b8738f7ee78cc59cdd0f1cc9e76cbbe4ecc8b79273f676a86be71efdd61d8b393b081cc9e76c67b7dc1b8c782b3967ef85ba76eed1b8cb58ccd9bb80832167fba49f1df15672cede0f75eddca331c0b198b3f70147f239dbcd94b3ad92b3c1d0bc6510b8738fc6a3c762ce3e001cc9e7ec3e199f1df95672ce7e06eadab94773236331671f018ee473b68f6b7cb620393bb45e2308dcb947f3746331673f6fca7a6eece7666e6c01e87e61740b41f74b586740ba5f19dd89e017431be8943630e2ade436f06ba86be7f249a63c16dbc00f80832167bb256747bc959cb34f415d3bf768fdc258ccd9df020743ceee959c1df15672cefe17d4b5738fd6d28cc59c7dda94f5fdc2e3e67e6111e8fe60748b41f747a35b02ba278c6e29e89e34ba65a0fb93d13581eecf46b71c747f31ba66d03d657479d0fdd5e85a40f737a32b80ee69a36b05dddf8dae0d74ff30ba76d0fdd3e83a40f78cd1751a9d9ec7a235558f1add04f0bd3748eedc86eba882e22d63edf74279192f4f3e17143f2740b696276fab55fbde148cdcf7e5c0d3cce07b166c8c84a71978f2c9f384bf475b923f6e788e9bac9866c15613f85560f02b03b6e8d8b44ff672a0c37ea3e0606c4d9eb190015b746cda6f0546d2613f46cfe150fbd17df3bccc302f435b0aafcf68af1738c85e0dd4c9340cd76d346c75f077ea03eaa08cfd7cded231e56a982bf870562fecb70023f9981f7dc6c248199b2d46ae7e2303b6e8d8b6ed3a477c74cc5a1d316b63626cb51869bf0d18297eada3cf581829a3dd2f30f5492d23ed93282ef9d18fd988ce6b0e7478afd7e6606c4f9e313caf6d1623edb70323e90ac0c3753d8c6aafbed8e6b80fc17ca66b165d7fc85e0dd469ad1eaebb09aea70c7d68a1d47b53ecd3933f4f853c5ecf46c2c37cee5a98f2318f7de7b341b2b966b7f9bc152b6cf3d89773f593517d39d91366611666611666611666611666611666611666611666611666611666611666ff99a3e6e55ceb198e2723e95a8087639c3f7cf7943916ce013d06f33ac9cf5b14f238574feb1817593ed7409dffcd0cb33dee58278173e7cb2d1dd33aa5f05ce23aa55ed8277bb86e03d74d31ac3d0979965a3cb6ed3a477c7c5c47e2d31a8da8755a3ec52c073a5c0fd7c4c41395674d0edb8d89d92eece3693b85bc7ecf8f7e571ef527761bc1b56f4b2c9dee933aaa87fde6c88152e79df1ba41e524e77131dfd056f2eb6d0a45eb13aa82e26b05de5330ac51299aafa6b511ed96ed1aac5315fcfbdc74c0df7b83e7ae11c23a746cda5f04dfedb08e3d99cfdfd8feb01db8a95c6bf9b60cb8a9cea4aa611f3f67ca4cf733055c3f1b006f60f9441baecf48fe7e6f68bd48a1049e36e0e158bbc6745f9bc77c4c7abd4887152bd7fd32d56987f87530c42f6ecd1ad91366611666611666611666611666611666611666611666611666611666611666ff99f1fd17c48acf48b778c2384a6b6cc2f90c7a6f11ce8bdd5f356c977b0e90e69c165b3ee333ca4f570db33d68caf88e00d7f3ee782eb9e6d6a2ce25d9ab0b9efb9c3ed3b91cf1bb1fda1c31eb70c4ac9389d1ee3368bf1318297e1dc0c3d51edb2d1edb36f6196d9ec62caa9fe55abf129567ae750a8d89d91e5a2fc231af4beb45eceb578b15535c27413a9c07c777abe07a2cdfdeff62af5dc07e0ad76825df6f168ae680edb582640fd7497cc3c496d64924df0f14f29cd7086aa3b426a4e0f095ea3c0ad7b9ef9932ae156a81633de6f83b6d716b12b04f65785766787ee9dd8d747ebb1db657026b42b65bd076c608d9217d0d947f53355cd77e1724c59ad8751bb1df57e9fa5edefa5e0eea7439fcef0d92f5bfdbe2e9b69875eefc10f2ec31b8d7e3ea93ba02778c16418ca80edef332ac2972f691f69a695d87ceff78ab0ede9f529d27a18f8a5a93ee7a0f20d7fd42d47b00f17ec1754f63fb68af1daff4f580ff82fea203fede1bbcf0f580ff821c72dd97d2f117c3f1896b7c107d6da13aff635d47b9dad6f3bdf7caf5db8f7871bd21d5f93fe8ab969975b951bf635ccf5970fd6e887aee83ece13d5529be63bf90f4b511f31159c81ee6638d8935e5634704f772c777c7477c976245ebcbf177b21d3f1d87c4df116efa9b6ecb176a535de0cbbfafdfe00bcf3dd3d0fd67f2be16df0f511fd4eaf095ea4c8577c135987216ce13f695273bfe4e5bdcfd27bed7bc27799fc3f34befefa6f3dbe3b0bd1a5813b2dd82b6e9fe93ec90be06ca27550fd7a57a140f8a35b1eb3642f770c86e7fafddfa5e0eeaac74f8df1b24eb7f8fc5d36331ebdc99097976323c6bc1d557af8c88d1628811d5c1671deddffff85b1eaf31c7ebb73cbef313fbf66510d3d17a67aa3d7eebba3f596cc518ef4f5aa09fcd3aeadae3d2740d49727d3a3e0fb414ece2f3404b99e2990b8ae399b338386d4fb66c4f1e45dbf596edfa51b42d319798fb14739ffe2f0cfc3f2baa52c0589d02c69a14308e4b01636d0a18c7a78071420a1827a68071520a18b3c0783cafed0cf12978f6ff3dc5de6ba06d86f73984b158168c3c164dbc3cb1f73e689be11d2a25ff7f03ccff17564bb9ff17560ebe3735058cd352c0d89002c6e929609c9102c69929609c9502c6d929609c9302c6b929609c9702c6f929605c9002c68529606c4c01e38929603c29058c27a780f19414309e9a02c60929605cc2cb58289751f370bc47331b14afe37a3e1ee6f77a86ef2774bd4394e3ff9d2dd577e677fab694fb0e3c5cbfc0fbff28beb0f7f471ac4f28f53d7d71fff7341363a15c46aef526b8b665243cae3528795ec642b98c5ccf77e0f38623e171fd3fb8bccfdb0cc5ac1c46aef558a5ae17c4e7f0da1d3163602c94cbc8b5a61f9f371c098febb9c03c2f63a15c46aeb5af59b031129e2e8859a723660c8c857219999edd0a63d655020f3ee3d4e588190363a15c46cdb3822966dd25f0ac8098753b62e61323f224fdbef16e872d8e67e24af59d189071620a1827a58011d72070f45f716b10ba79e35328373e5ce72b6e0d02da667806238c05aeb97fbe58f4f0f2c4ae4140dbab986281cf443c5f2c56010fc7331a59b031121e62c8c1f7a6a680715a0a181b52c0383d058c3352c03833058cb352c0383b058c7352c03837058cf352c0383f058c0b52c0b830058cf85b95e15e31f6f7cbaa316e3beab7ca58b71df5bb64acdb963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf7db29d86317e611c7b8cc8d3981c4f1e7d475ba77be0fbe90e9e0c93ef68abd703dfa99c36c6d529605c91024689e3d01ac4721835cf1a269ede1278d600cf194c3c6b4ae0390378d626cf13e6d41925f010430ebeb722058cab53c028719438fac42871ac9c380aa3300aa3301e0fc634f4e1729d19faed520ea3e659973c4f18b3b525f0ac8398d1f7f2bc8c85721935cffae479c298ad2b81673dc46c9d23660c8c85721935cf86e479c298ad2f816703c46cbd23660c8c85721935cfc6e479c2986d28816723c46c8323660c8c85721935cfa6e479c2986d2c816713c46ca323660c8c85721935cfe6e479c2986d2a816733c46c9323660c8c85721935cf96e479c2986d2e81670bc46cb323660c8c85721935cfd6e479c2986d2981672bc46c8b23660c8c85721935cfb6e479c2986d2d81671bc46cab2366be32ae4801e3ea143032c7b1502ea3e6d9cec4b3ad049eedc0732613cff61278ce049eb392e70973eacc1278882107df5b9102c6d5296094384a1c7d629438564e1c85511885b134c6d353c028e75a187d6564f87d15fb7cca9963dc76d4f32963dd76d4f32963ddb6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e73ed9de91bced42a9cfb0ee009eb31862c1e4675e1ff76c73ac67138c9f8ed53956acceb46295833a6743fcce61885f06ecd2b1699fec95cafc220f98996c174e50c79808fe938dd5563cb4fd73997c8feaebcf1de3b6a3fafab16e3baaaf1febb625cf25cf2bc1b6e4b9e47925d8963c973cf7c536966b82e1fb767abf923ec679a63cceec53fdd3e17b54a765fcd0e7e440da10876d694372ada804db92e792e795605bf25cf2bc126c4b9efb99e7e7276f3b9c1bc3df177a8b9b1b3b1f78ce638805939f79edd305964fe75a3ee5a00ebeb3f602063f3360978e4dfb17c079481bb3e65965cac49a857aab3c6124dd79bc3c61fb5a15146f71edeb02e06168072d4c7e86edeb42cba7558eb8531dccd50b19fc74b51ddabf10ce43da9873608f58b341f139f5819174e7f3f284edab3728dee2dad785c0c3d1ff30f919b6af8b2c9f7a1d71a73a98ab1731f8e96a3bb47f119c87b4316b9e35f077bd65a1de1a4f184977012f4f5b167ca62dae7d5d043c1cfd0f939f61fbda69f9b4c61177aa83b9ba93c14f57dba1fd9d701e8459985dcc9ae70c5326d62cd43bc31346d25dc8cad396cf82cfb4c5f5633b8187a39f678a7bd88f5d6cf9748623ee540773f562063f5d6d87f62f86f3500af3ea14324b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9ccb63d63c6b4d9958b3506fad278ca4bb8897277c7e676d50bc65acfd5e285f0c3c3b19e2c3e467b8eefd12cba7b58eb8531d6c5f9730f8e96a3bb47f099c87529857a79059e25c1eb3e65967cac49a857aeb3c6124dd4e5e9eb01f5b17146f71fdd825c0c3d1cf33f919f663975a3ead73c49dea60fbba94c14f57dba1fd4be13c08b330bb9835cf7a5326d62cd45bef0923e92e66e52984cf21ae0f8ab7b87eec52e0e1e8e799e21ef663bb2c9fd63be24e7530577731f8e96a3bb4bf0bce4329ccab53c82c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c2b27ce9a678329136b16ea6df084917497b0f2b486f30e1b82e22d6ede6117f070cccb30c53d9c77b8ccf2698323ee5407dbd7650c7ebada0eed5f06e761ac33af4e21b3e4c6e8304b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e486304731fb901b9a67a329136b16ea6df484917497f2f284ef3dd818146f71eb762e039e5d0cf161f2335cb773b9e5d34647dca90eb6afcb19fc74b51ddabf1cce83300bb38b59f36c326562cd42bd4d9e30926e172f4fd88f6d0a8ab7b87eec72e0e1e8e799fc0cfbb1dd964f9b1c71a73a98abbb19fc74b51ddadf0de761b7300bb38359f36c366562cd42bdcd9e3092ee325e9eb01fdb1c146f71fdd86ee0e1e8e799fc0cfbb13d964f9b1d71a73a98ab7b18fc74b51dda277bc22ccc51cc9a678b29136b16ea6df184917497f3f214b2e0336d71fdd81ee0d9cd101f263fc37e6cafe5d31647dca90ee6ea5e063f5d6d87f6f7c279481bb3e6d96acac49a857a5b3d6124dd6e5e9eb07d6d0d8ab7b8f6b5177838fa1f263fc3f6b5cff269ab23ee540773751f839faeb643fbfbe03ca48d59f36c336562cd42bd6d9e30926e0f2f4fd8beb605c55b5cfbda073c1cfd0f939f61fbeab37cdae6883bd5c15ced63f0d3d57668bf0fce43da9835cf765326d62cd4dbee0923e9b09fa2ad0a18b7333106166360c507791678c633cb339ea99ef14cf48ca7da339ea59ef1747bc6d3e519cf42cf78167bc633db339e82673cd33ce359ee19cf24cf78da3de3a9f18c6799673ca779c6b3d2339e399ef13478c6b3c4339eac673ce33ce369f28ca7c7339e0ecf78e67ac6d3ea19cf74cf789a3de3a9f38c27e7194fad673c3b3ce399e719cf0ccf784ef08c67b2673ce33de3e9f48c67be673c6d9ef1ccf48ca7c5339e299ef1d47bc633c1339e459ef1643ce0c906cf5d379085bfef005d95f55d7d7dd9d030fc779aa7ad82eff49b72b5e3d87da0a379dd7ec777314e5c73cf68ab17f6c95e1d70f47bc2b3c8339e099ef1d47bc633c5339e16cf78667ac6d3e619cf7ccf783a3de319ef19cf64cf784ef08c6786673cf33ce3d9e1194fad673c39cf78ea3ce369f68c67ba673cad9ef1ccf58ca7c3339e1ecf789a3ce319e7194fd6339e259ef13478c633c7339e959ef19ce619cf32cf786a3ce369f78c6792673ccb3de399e6194fc1339ed99ef12cf68c67a1673c5d9ef1747bc6b3d4339e6acf78267ac633d5339e599ef12cf08ca7cac1b3838927ead9dd1d9ed866380f797ddcfd4c3e5d618e556b8e4bfc64af06ead49b81473ddf80df252e7bbe1dc796af801871bd372167f1d0febe316e7bb2657b7285d8aeb76cd757886dc973c9f34ab02d792e795e09b625cf25cf7db4fd6c72b6db31cfaac0960feba3e5fd49f13cf2fea4789e6acf78e4fd49f13cf2fea4781e797f523c8fbc3f299e47de9f14cf23ef4f8ae7f1edf978799f533c8fbccf299e47dee714cf23ef738ae769f28c47dee714cf23ef738ae791f739c5f3d479c693f38cc7b7f739c9fb93e279e4fd49f13cf2fea4781e797f523c8fbc3f299e47de9f14cf33c1339e459ef1643ce079bef727e17b8f68ade53ed0d17aceb8f72c65e13857808ec607e918fa7a7576c37319aae03b573ab8f63bec919d2b1ddf1d8db8a3ad5ed8277bf83ea62b3de159e419cf04cf78ea3de399e2194f8b673c333de369f38c67be673c9d9ef18cf78c67b2673c2778c633c3339e799ef1d47ac693f38ca7ce339e66cf78a67bc6d3ea19cf5ccf783a3ce3e9f18ca7c9339e719ef1643de359e2194f83673c733ce359e919cf699ef12cf38c6787673c359ef1b47bc633c9339ee59ef14cf38ca7e019cf6ccf78167bc6b3d0339e2ecf78ba3de359ea194fb5673c133de399ea19cf2ccf781678c653e5e0e17a27522e18de7a617f34dec7f47cb6f5fe52888bdeb2f0f7d1784e7287c548fbb8ce0079896729134fd473ef4b3db0adfda7df5a34679185bfe373385c39b5d462a47d574ee13ac2654c3c51cfeb2ff3c0b68e459329d31c7716fede048c5c39b5cc62a47d574ed5f3f2b465c167dae2d6f6609be338874c7ee6b1fd25f88e88bc8ed5762b564d56ac725067349e138cea0fc89e300b7314b3e6a1b11662c5ebd9683c273d1246d7f5958127ec1f9707c55b5cffb81d7838ae1f4c7e86fdd801cba7e58eb8531dccd5030c7ebada0eed1f70d86e0c928dc5552388c5550e9eab46391664af54e61d2964f621ce9a87d64e102bae276ef68491744b7979c2feb13928dee2fac7ab8087e3fac1e467d8275c6df9d4ec883bd5c1f67535839faeb643fb57c3792885f9400a9925cee5316b1e5a534dac59a8d7e20923e9b6b3f214f259f099b6b87eec6ae0e1e8e799e21ef663072d9f5a1c71a73ad8be0e32f8e96a3bb47f10ce83300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbcdac79e8591562cd42bd82278ca4bb8a956768dea110146f71f30e078187635e8629eee1bcc321cba78223ee540773f510839faeb643fb87e03c08b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3dfcc9a87dee94aac59a8d7ea0923e9aee6e5099fdb6a0d8ab7b8798743c0c3312fc3e46738ef70d8f2a9d51177aa83b97a98c14f57dba1fdc3701e8459985dcc9a87feaf0762cd42bd364f18497790956768feb42d28dee2fab1c3c0c3d1cf33c53decc7062c9fda1c71a73a98ab030c7ebada0eed0fc0792885f9400a9925ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e728668973e5c459f3d0ff5145ac59a8d7ee0923e90eb1f2b486f30eed41f11637ef30003c1cf3324c710fe71d8e583eb53be24e75b07d1d61f0d3d57668ff089c87b1ce7c2085cc921ba3c32cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc5ec436e689e0e5326d62cd4ebf0849174877979c2f71e7404c55bdcba9d23c033c0101f263fc3753bd7583e7538e24e75b07d5dc3e0a7abedd0fe35701e8459985dcc9aa7d39489350bf53a3d6124dd002f4f210b3ed316d78f5d033c1cfd3c939f613f76d4f2a9d31177aa83b97a94c14f57dba1fda3701ed2c6ac79ba4c9958b350afcb1346d2e175b98b892767f1e41cb1385eb6f57eb729d799cf2cfcbd1b18b9fac32e8b91f631c7919778ba9978265b3c931db1385eb6b5ff2b4df904f39985bfaf0446ae9ceab61869df955393816725134fbdc553ef88c5f1b2ad63d163ca53cc6716fede038c5c39b5d262a47d574ed5034f0f134f549fd4330ab6a3dad768d88eca95d1b02d318f8e3943bb0bc7077a82e22deebe1aaf2d1c7d15939f79d7f5bbc7f209afdf788f7abcae4fc22ccc51cc4cf7b96d59cb36c527b07868bb863916a3f93bbbdbf2290dbfb3e3980fa49059e25c1eb3b67d2c79db6d59cb36c527b078683bc61c0b263fc3fe603070c798ece5a00ee6e920839f19b04bc7a6fd41380fa5301f4821b3c4b93c666dfbdac46d0fbd7f186d537c028b87b66b9963c1e3e7507f705de08e31d9cb411dccd3eb18fccc805d3a36ed5f07e74198855998855998855998855998855998855998855998855998855998855998fd66d6b6af4fdcf6d0f83ddaa6f804160f6dd733c782c7cfa1f1fb1b02778cc95e0eeae039bf81c1cf0cd8a563d3fe0d701e84599885599885599885599885599885599885599885599885599885599885d96f666dfbc6e46d87cfe3a06d8a4f60f1d07623732c98fc0cc7ef6f0adc31267b39a883e7fc26063f3360978e4dfb37c17910666176316bdb37276e7b683e0f6d537c028b87b69b9963c1e3e7507f704be08e31d9cb411d3ce7b730f89901bb746cdabf05ce4329cc0752c82c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c2b27cedaf6ad89db6e0dc7efd136c527b07868bb9539163c7e0e8ddfdf16b8634cf6725007f3f436063f3360978e4dfbb7c17918ebcc0752c82cb9313acc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc3ee486b67d7bf2b6c3e7d9d136c527b07868bb9d39164c7e86eb5fee08dc31267b39a883797a07839f19b04bc7a6fd3be03cdc21ccc2ec60d6b6ef4cde76216bd9a6f804160f6d7732c782c9cfb03fb82b70c798ece5a00e9ef3bb18fccc805d3a36eddf05e7216dcc78fe32c9d90ed76d928d2af3a9752f36e56ad0bdc4946b40f752531e07ba9799722de85e6ecae3417737f846ba5798f212d0bdd2947b40778f29af04ddab4cb91b74f79a7217e85e6dcad780ee35a67c1474f799f231d0bdd6940741f73a53be1674af37e5eb40f70653be1e746f34e51b40f72653be11746f36e59b40f71653be19746f35e55b40f73653be1574f79bf26da07bbb29df0eba7798f21da07bc0947780ee41539e08ba874c7912e8fe03caf4f94e53ae03ddbb4c3907ba779bf209a07b8f294f06dd7b4d790ae8de67caf5a07bd894a782eefda63c0d741f30e506d07dd094a783ee11539e01ba0f99f24cd07dd8946781ee23a63c1b741f35e539a0fb9829cf05ddc74d791ee83e61caf341f749535e00ba4f99f242d07dda94f1fc7ec694ef041df51777818efa8b17838efa8b97808efa8b97828efa8b97818efa8b97838efa8bbb414779f70ad051debd12749477f7808ef2ee55a0a3bcbb17749477af061de5dd6b404779771fe828ef5e0b3acabbd7818ef2eef5a0a3bc7b03e828efde083acabb37818ef2eecda0a3bc7b0be828efde0a3acabbb7818ef2ee7ed051debd1d749477ef001de5dd03a0a3bc7b10748da6fc10e84e3465ec3f4e32e57782ee64537e17e84e31e57783ee54537e0fe85e64caef05dd69a6fc3ed02d32e58741b7d894df0f3aba867d00744b4df983a05b66ca8f80aec9943f04bae5a6fc61d0359bf247409737e58f82aec5943f06ba82297f1c74ada6fc09d0b599f22741d76eca9f025d87297f1a749da64cfd876ea7babd91cf148f3af0afc9c14dba09c0dd1b247b0f46b6e8d8b45f00468a77cbe8331646ca98b718354f1b43cc3087688bfb8dd3063cad0c3c4c7e86bf71da2d9f0a964f39a8f322f0b39dc1cf0cd8a563d37e3bd8e638e7188b5a73dcd3ac58d4409d59e6e2a5af937171a463e8fc6d71f8c215c7bcc59377d8ee628e231d9bfac4ae51b0dd61d96eb66c63bf4f5b5cdbee00e64e06667ddceee48f1bb6ed15e65894cf64a7197c5a093148ca27b49d314276485f03e5e686e1ba548fe241d74e62d7ed88ce25b2dbdf6bb3be97833a5d0eff7b8364fdefb678ba2d66fd3be19486610e86f610e64097c541fbcd10bbee88d87541eca80e5e7bf34cb1ebb478683f0f3c747fd50e3aba4f217ebc9f6b1a056ebbdf6b777093ae0318f30ec6e6e4190b71d7856660245d27f07430c5cc3ed7a759f1c17b82f1561dfa6e0dd45907d7e5aca3ae6e77f332c37ed1effa678364fbf45a8678e1984300f109ac18d2460c1382e1718924792605c3e30ec706078eeeb9a2ff9cfe3d7d1940abb130f133e370a30a7458ae76e882a0787805876f697805876fabacb0e0b00ed5d73fe3b45b3484d17fe8c0e0f987fb0fef3b7ae391c1febe6d035720f5388b1e49a33c4052d4d13621181e08ea0d929db8a9b56cc525cf04f81c9f3c4f0b939fe1456fa2e553ade5530eea8c83bf4d64f0330376e9d8b43fd1613bc18e288cc5a411c462928367d228c70207d349872d95fe8e132d55962fd8a2d1273bcf1375880c9e0ac7cf1838fd37ddd8c71967c607c3279b7a4f7d47ab4f821e85d5572d3dcaaa47557517a4474df5054d8f8aea51503deaa94739f5a8a61ec5d4a3967a94528f4aea51483dead8180c8d2aea51443d6a780a703d0aacfad7bcbe3aea513f3dcaa747f5f45d95feb5a6ef44f49db7be2bd07703faae4fffa2d5a31bfa4aabef62f4155a5f55f55da2be3bd477f3faee56cf66ad52b25ac9e926d66b949ca164ad92754ad62bd9a064a3924d4a362bd9a264ab926d4ab62b3953c959c1d068fdd94ace5172ae92f3949cafe40225172ab948c94e25172bb944c9a54a7629b94cc9e54a762bd9a364af927d4afa94f42bd9afe40a255706432b78ae5272b592834a0e2939ac6440c9916068464dcfa0e919333d43a667c4f40c989ef1d2335c7a464bcf60e9192b3d43a567a4f40c949e71ba23189a5dd0b3097af640cf16e8d9013d1ba047ffef0e8646f7f568fe3dc1d068bd1e9dd7a3f17af45d8fb6ebd1753d9aae47cff568b91e1dd7a3e17af45b8f76ebd16d3d9aad47aff568b51e9dd6a3d17af4f9a1606874598f26ebd1633d5aac4787f568b01efd7d38181addd5a3b97af4568fd6ead1593d1aab475ff568ab1e5dd5a3a97af4548f96ead1513d1aaa473f3fabe4734a3eafe40b4abea8e44b4abeace42b4abeaae46b4abeaee41b4abea9e45b4abeade43bc1504e7e57c9f7947c5fc90f94fc50c98f94fc58c94f94fc54c9cf94fc5cc92f94fc52c9af94fc5ac96f943ca6e4b74a7ea7e4f74a1e57f207257f54f284922795fc49c99f95fc45c9534afeaae46f4a9e56f27725ff50f24f25cf04c3b324d871d498de8646ecf70c0ef61f3a32d83838d078e8da8383078e1cbcb1f1fa038357360e5cd77f74ffc181ebf1cb5f375fa6e98835478feeb9b1f1c0e1befe1b1a07ae1d6c1cd8dfb877e0dac37dc7f04b4f982fcd7baec53d7d7dd1c6fef38590fe779946ab4d3f48133d9be37dabad2e232075e57c295f5d9e437973a5a1d9f97387ee701b8f1d1c186ccc371e56ffee39a8bed3dfb7bc11ff764c05f9d860e3b1c13d47071bf71f1d38d4d8b21c8f3ba5ae0c27663694f1a5b50d23f73cf87f8198955c01d50300", "privateFunctions": [ { "selector": { @@ -44,8 +44,8 @@ exports[`ContractClass creates a contract class from a contract compilation arti "isInternal": false } ], - "id": "0x09ad0dad993129857629f13ec2f3463d0c15615bd35266d0fb26c8793c6ee050", + "id": "0x193b0f08a5af3b2286bff06aaddcf074dd2e467e6fb1e412d747d2b64648866f", "privateFunctionsRoot": "0x05fa82a96814b6294d557d507151f7ccc12f70522ec4d9d0395a90e87e8087c6", - "publicBytecodeCommitment": "0x05a06c2ee54a742daa2fa43a111c03335df68ff89fd8e7ba938ca2efb225c885" + "publicBytecodeCommitment": "0x0de7228dd1c2821b5dcb66dc4e0de48e1f6a88e2830be489ad6c7006fcd868b8" }" `; diff --git a/yarn-project/circuits.js/src/contract/artifact_hash.test.ts b/yarn-project/circuits.js/src/contract/artifact_hash.test.ts index c3b04e7feaa..84c3517fc4b 100644 --- a/yarn-project/circuits.js/src/contract/artifact_hash.test.ts +++ b/yarn-project/circuits.js/src/contract/artifact_hash.test.ts @@ -5,7 +5,7 @@ describe('ArtifactHash', () => { it('calculates the artifact hash', () => { const artifact = getSampleContractArtifact(); expect(computeArtifactHash(artifact).toString()).toMatchInlineSnapshot( - `"0x242a46b1aa0ed341fe71f1068a1289cdbb01fbef14e2250783333cc0607db940"`, + `"0x2136048d7b91f63060c3dc03417c0b2835eac99ab393a87fc6e4ccfb3d65e5bc"`, ); }); }); diff --git a/yarn-project/circuits.js/src/contract/contract_address.test.ts b/yarn-project/circuits.js/src/contract/contract_address.test.ts index c32dab63f59..961636cfadf 100644 --- a/yarn-project/circuits.js/src/contract/contract_address.test.ts +++ b/yarn-project/circuits.js/src/contract/contract_address.test.ts @@ -1,5 +1,6 @@ import { ABIParameterVisibility, FunctionAbi, FunctionType } from '@aztec/foundation/abi'; import { Fr, Point } from '@aztec/foundation/fields'; +import { setupCustomSnapshotSerializers } from '@aztec/foundation/testing'; import { EthAddress } from '../index.js'; import { @@ -12,6 +13,7 @@ import { } from './contract_address.js'; describe('ContractAddress', () => { + setupCustomSnapshotSerializers(expect); it('computePartialAddress', () => { const mockInstance = { contractClassId: new Fr(1), diff --git a/yarn-project/circuits.js/src/contract/contract_class.test.ts b/yarn-project/circuits.js/src/contract/contract_class.test.ts index 450814fe3f1..2f8d7123092 100644 --- a/yarn-project/circuits.js/src/contract/contract_class.test.ts +++ b/yarn-project/circuits.js/src/contract/contract_class.test.ts @@ -1,10 +1,12 @@ import { Fr } from '@aztec/foundation/fields'; import { toFriendlyJSON } from '@aztec/foundation/serialize'; +import { setupCustomSnapshotSerializers } from '@aztec/foundation/testing'; import { getSampleContractArtifact } from '../tests/fixtures.js'; import { getContractClassFromArtifact } from './contract_class.js'; describe('ContractClass', () => { + setupCustomSnapshotSerializers(expect); it('creates a contract class from a contract compilation artifact', () => { const contractClass = getContractClassFromArtifact({ ...getSampleContractArtifact(), diff --git a/yarn-project/circuits.js/src/contract/private_function.test.ts b/yarn-project/circuits.js/src/contract/private_function.test.ts index 3d5d085ecd9..1d4487b744b 100644 --- a/yarn-project/circuits.js/src/contract/private_function.test.ts +++ b/yarn-project/circuits.js/src/contract/private_function.test.ts @@ -1,10 +1,12 @@ import { Fr } from '@aztec/foundation/fields'; +import { setupCustomSnapshotSerializers } from '@aztec/foundation/testing'; import { PrivateFunction } from '@aztec/types/contracts'; import { fr, makeSelector } from '../tests/factories.js'; import { computePrivateFunctionsRoot, computePrivateFunctionsTree } from './private_function.js'; describe('PrivateFunction', () => { + setupCustomSnapshotSerializers(expect); const privateFunctions: PrivateFunction[] = [ { selector: makeSelector(1), vkHash: fr(2), isInternal: false }, { selector: makeSelector(3), vkHash: fr(4), isInternal: false }, diff --git a/yarn-project/circuits.js/src/hash/__snapshots__/hash.test.ts.snap b/yarn-project/circuits.js/src/hash/__snapshots__/hash.test.ts.snap index d30610199d3..eb8173eec0c 100644 --- a/yarn-project/circuits.js/src/hash/__snapshots__/hash.test.ts.snap +++ b/yarn-project/circuits.js/src/hash/__snapshots__/hash.test.ts.snap @@ -4,601 +4,30 @@ exports[`hash Computes an empty nullifier hash 1`] = `"0x066e6cdc4a6ba5e4781ded exports[`hash Computes an empty sideeffect hash 1`] = `"0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed"`; -exports[`hash Var args hash matches noir 1`] = ` -Fr { - "asBigInt": 1557627899280963684159398665725097926236612957540256425197580046184563077271n, - "asBuffer": { - "data": [ - 3, - 113, - 150, - 13, - 216, - 78, - 211, - 68, - 90, - 176, - 153, - 172, - 76, - 26, - 245, - 186, - 144, - 224, - 199, - 19, - 181, - 147, - 224, - 202, - 82, - 238, - 83, - 32, - 135, - 199, - 240, - 151, - ], - "type": "Buffer", - }, -} -`; +exports[`hash Var args hash matches noir 1`] = `Fr<0x0371960dd84ed3445ab099ac4c1af5ba90e0c713b593e0ca52ee532087c7f097>`; -exports[`hash compute secret message hash 1`] = ` -Fr { - "asBigInt": 6220068662483113241527007349428551778669520744131373768997518428761948042030n, - "asBuffer": { - "data": [ - 13, - 192, - 111, - 33, - 103, - 226, - 205, - 25, - 173, - 247, - 56, - 209, - 243, - 132, - 105, - 215, - 248, - 191, - 241, - 226, - 107, - 2, - 152, - 22, - 232, - 35, - 11, - 205, - 106, - 182, - 51, - 46, - ], - "type": "Buffer", - }, -} -`; +exports[`hash compute secret message hash 1`] = `Fr<0x0dc06f2167e2cd19adf738d1f38469d7f8bff1e26b029816e8230bcd6ab6332e>`; -exports[`hash computes commitment nonce 1`] = ` -Fr { - "asBigInt": 7653394882992289714855533169019502055399179742531912347686813547951736946253n, - "asBuffer": { - "data": [ - 16, - 235, - 171, - 1, - 188, - 129, - 50, - 99, - 239, - 146, - 237, - 113, - 185, - 199, - 129, - 173, - 62, - 245, - 128, - 25, - 182, - 106, - 143, - 113, - 48, - 77, - 47, - 114, - 215, - 222, - 254, - 77, - ], - "type": "Buffer", - }, -} -`; +exports[`hash computes commitment nonce 1`] = `Fr<0x10ebab01bc813263ef92ed71b9c781ad3ef58019b66a8f71304d2f72d7defe4d>`; -exports[`hash computes function tree root 1`] = ` -Fr { - "asBigInt": 18902231782334398705464257251364974449663398212058621439366133672872128659209n, - "asBuffer": { - "data": [ - 41, - 202, - 72, - 183, - 227, - 53, - 212, - 51, - 133, - 173, - 223, - 25, - 183, - 14, - 155, - 5, - 105, - 58, - 143, - 86, - 204, - 9, - 239, - 140, - 187, - 195, - 116, - 164, - 13, - 173, - 191, - 9, - ], - "type": "Buffer", - }, -} -`; +exports[`hash computes function tree root 1`] = `Fr<0x29ca48b7e335d43385addf19b70e9b05693a8f56cc09ef8cbbc374a40dadbf09>`; -exports[`hash computes public data tree leaf slot 1`] = ` -Fr { - "asBigInt": 9076808949980998475110411569159266589807853958487763065147292518713994520820n, - "asBuffer": { - "data": [ - 20, - 17, - 74, - 179, - 219, - 221, - 10, - 28, - 204, - 92, - 79, - 230, - 141, - 213, - 118, - 243, - 198, - 205, - 121, - 112, - 135, - 112, - 224, - 106, - 180, - 8, - 99, - 152, - 205, - 216, - 40, - 244, - ], - "type": "Buffer", - }, -} -`; +exports[`hash computes public data tree leaf slot 1`] = `Fr<0x14114ab3dbdd0a1ccc5c4fe68dd576f3c6cd79708770e06ab4086398cdd828f4>`; -exports[`hash computes public data tree value 1`] = ` -Fr { - "asBigInt": 3n, - "asBuffer": { - "data": [ - 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, - 3, - ], - "type": "Buffer", - }, -} -`; +exports[`hash computes public data tree value 1`] = `Fr<0x0000000000000000000000000000000000000000000000000000000000000003>`; -exports[`hash computes siloed commitment 1`] = ` -Fr { - "asBigInt": 7262347077404413274044670947879391583109741657896097604752287127491776887739n, - "asBuffer": { - "data": [ - 16, - 14, - 87, - 192, - 122, - 182, - 219, - 134, - 244, - 174, - 67, - 245, - 167, - 212, - 53, - 92, - 87, - 197, - 161, - 226, - 82, - 55, - 70, - 224, - 251, - 22, - 172, - 41, - 240, - 220, - 59, - 187, - ], - "type": "Buffer", - }, -} -`; +exports[`hash computes siloed commitment 1`] = `Fr<0x100e57c07ab6db86f4ae43f5a7d4355c57c5a1e2523746e0fb16ac29f0dc3bbb>`; -exports[`hash computes siloed nullifier 1`] = ` -Fr { - "asBigInt": 10521714890263159342521589827909786073566333899903358017581007142888032736115n, - "asBuffer": { - "data": [ - 23, - 67, - 20, - 95, - 222, - 16, - 62, - 170, - 136, - 175, - 87, - 110, - 5, - 98, - 230, - 29, - 133, - 235, - 165, - 144, - 253, - 223, - 1, - 209, - 149, - 80, - 228, - 240, - 36, - 112, - 147, - 115, - ], - "type": "Buffer", - }, -} -`; +exports[`hash computes siloed nullifier 1`] = `Fr<0x1743145fde103eaa88af576e0562e61d85eba590fddf01d19550e4f024709373>`; -exports[`hash computes unique commitment 1`] = ` -Fr { - "asBigInt": 13000121189816960667906065043973697710794195579570622293955220571859166513128n, - "asBuffer": { - "data": [ - 28, - 189, - 206, - 206, - 196, - 254, - 146, - 246, - 99, - 142, - 182, - 168, - 218, - 222, - 150, - 202, - 53, - 142, - 203, - 164, - 149, - 76, - 245, - 151, - 195, - 99, - 25, - 159, - 174, - 61, - 71, - 232, - ], - "type": "Buffer", - }, -} -`; +exports[`hash computes unique commitment 1`] = `Fr<0x1cbdcecec4fe92f6638eb6a8dade96ca358ecba4954cf597c363199fae3d47e8>`; -exports[`hash hashes VK 1`] = ` -{ - "data": [ - 4, - 129, - 16, - 102, - 127, - 128, - 176, - 47, - 119, - 183, - 215, - 68, - 151, - 102, - 87, - 206, - 169, - 167, - 197, - 241, - 221, - 35, - 64, - 234, - 28, - 87, - 154, - 126, - 191, - 213, - 78, - 85, - ], - "type": "Buffer", -} -`; +exports[`hash hashes VK 1`] = `Buffer<0x048110667f80b02f77b7d744976657cea9a7c5f1dd2340ea1c579a7ebfd54e55>`; -exports[`hash hashes constructor info 1`] = ` -Fr { - "asBigInt": 8554563246648466207128694080427818093826588702256491720155365584899927973422n, - "asBuffer": { - "data": [ - 18, - 233, - 182, - 18, - 27, - 239, - 249, - 139, - 157, - 45, - 92, - 189, - 121, - 152, - 157, - 73, - 211, - 211, - 253, - 135, - 52, - 199, - 134, - 233, - 242, - 74, - 6, - 239, - 86, - 0, - 30, - 46, - ], - "type": "Buffer", - }, -} -`; +exports[`hash hashes constructor info 1`] = `Fr<0x12e9b6121beff98b9d2d5cbd79989d49d3d3fd8734c786e9f24a06ef56001e2e>`; -exports[`hash hashes empty function args 1`] = ` -Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, -} -`; +exports[`hash hashes empty function args 1`] = `Fr<0x0000000000000000000000000000000000000000000000000000000000000000>`; -exports[`hash hashes function args 1`] = ` -Fr { - "asBigInt": 13773950327711008256617416059663646210697922258755635023101062905870427579114n, - "asBuffer": { - "data": [ - 30, - 115, - 199, - 148, - 191, - 130, - 160, - 100, - 98, - 205, - 48, - 10, - 124, - 139, - 218, - 39, - 47, - 30, - 253, - 79, - 200, - 107, - 56, - 53, - 41, - 130, - 26, - 237, - 106, - 243, - 98, - 234, - ], - "type": "Buffer", - }, -} -`; +exports[`hash hashes function args 1`] = `Fr<0x1e73c794bf82a06462cd300a7c8bda272f1efd4fc86b383529821aed6af362ea>`; -exports[`hash hashes many function args 1`] = ` -Fr { - "asBigInt": 5019561503322397537490243039227402098195702132635946562396386724242519444026n, - "asBuffer": { - "data": [ - 11, - 24, - 248, - 156, - 4, - 206, - 67, - 253, - 74, - 84, - 242, - 151, - 150, - 30, - 97, - 225, - 13, - 209, - 17, - 48, - 60, - 254, - 13, - 43, - 30, - 121, - 227, - 133, - 97, - 87, - 74, - 58, - ], - "type": "Buffer", - }, -} -`; +exports[`hash hashes many function args 1`] = `Fr<0x0b18f89c04ce43fd4a54f297961e61e10dd111303cfe0d2b1e79e38561574a3a>`; diff --git a/yarn-project/circuits.js/src/hash/hash.test.ts b/yarn-project/circuits.js/src/hash/hash.test.ts index 3f56b4167e3..5e57311863d 100644 --- a/yarn-project/circuits.js/src/hash/hash.test.ts +++ b/yarn-project/circuits.js/src/hash/hash.test.ts @@ -1,4 +1,5 @@ import { times } from '@aztec/foundation/collection'; +import { setupCustomSnapshotSerializers } from '@aztec/foundation/testing'; import { AztecAddress, Fr, FunctionData, FunctionSelector, SideEffect, SideEffectLinkedToNoteHash } from '../index.js'; import { makeAztecAddress, makeVerificationKey } from '../tests/factories.js'; @@ -19,6 +20,7 @@ import { } from './hash.js'; describe('hash', () => { + setupCustomSnapshotSerializers(expect); it('hashes VK', () => { const vk = makeVerificationKey(); const res = hashVK(vk.toBuffer()); diff --git a/yarn-project/circuits.js/src/hints/build_hints.test.ts b/yarn-project/circuits.js/src/hints/build_hints.test.ts index 6cf3572bbf7..9db861afe55 100644 --- a/yarn-project/circuits.js/src/hints/build_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_hints.test.ts @@ -1,34 +1,35 @@ +import { makeTuple } from '@aztec/foundation/array'; +import { AztecAddress } from '@aztec/foundation/aztec-address'; +import { padArrayEnd } from '@aztec/foundation/collection'; +import { Fr } from '@aztec/foundation/fields'; +import { Tuple } from '@aztec/foundation/serialize'; + +import { MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX } from '../constants.gen.js'; +import { siloNullifier } from '../hash/index.js'; import { - AztecAddress, - Fr, - MAX_NEW_NULLIFIERS_PER_TX, - MAX_NULLIFIER_READ_REQUESTS_PER_TX, - NullifierReadRequestResetHints, - NullifierReadRequestResetHintsBuilder, + NullifierNonExistentReadRequestHintsBuilder, + NullifierReadRequestHints, + NullifierReadRequestHintsBuilder, PendingReadHint, ReadRequestContext, ReadRequestState, ReadRequestStatus, SettledReadHint, SideEffectLinkedToNoteHash, -} from '@aztec/circuits.js'; -import { siloNullifier } from '@aztec/circuits.js/hash'; -import { makeTuple } from '@aztec/foundation/array'; -import { Tuple } from '@aztec/foundation/serialize'; - -import { HintsBuildingDataOracle, buildNullifierReadRequestResetHints } from './build_hints.js'; +} from '../structs/index.js'; +import { buildNullifierNonExistentReadRequestHints, buildNullifierReadRequestHints } from './build_hints.js'; -describe('buildNullifierReadRequestResetHints', () => { +describe('buildNullifierReadRequestHints', () => { const contractAddress = AztecAddress.random(); const settledNullifierInnerValue = 99999; const settledNullifierValue = makeNullifier(settledNullifierInnerValue).value; - const oracle: HintsBuildingDataOracle = { - getNullifierMembershipWitness: value => + const oracle = { + getNullifierMembershipWitness: (value: Fr) => value.equals(settledNullifierValue) ? ({ membershipWitness: {}, leafPreimage: {} } as any) : undefined, }; let nullifierReadRequests: Tuple; let nullifiers: Tuple; - let expectedHints: NullifierReadRequestResetHints; + let expectedHints: NullifierReadRequestHints; let numReadRequests = 0; let numPendingReads = 0; let numSettledReads = 0; @@ -73,12 +74,12 @@ describe('buildNullifierReadRequestResetHints', () => { numSettledReads++; }; - const buildHints = () => buildNullifierReadRequestResetHints(oracle, nullifierReadRequests, nullifiers); + const buildHints = () => buildNullifierReadRequestHints(oracle, nullifierReadRequests, nullifiers); beforeEach(() => { nullifierReadRequests = makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ReadRequestContext.empty); nullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, i => makeNullifier(innerNullifier(i))); - expectedHints = NullifierReadRequestResetHintsBuilder.empty(); + expectedHints = NullifierReadRequestHintsBuilder.empty(); numReadRequests = 0; numPendingReads = 0; numSettledReads = 0; @@ -118,3 +119,125 @@ describe('buildNullifierReadRequestResetHints', () => { await expect(buildHints()).rejects.toThrow('Read request is reading an unknown nullifier value.'); }); }); + +describe('buildNullifierNonExistentReadRequestHints', () => { + const contractAddress = AztecAddress.random(); + const oracle = { + getLowNullifierMembershipWitness: () => ({ membershipWitness: {}, leafPreimage: {} } as any), + }; + const nonExistentReadRequests = makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ReadRequestContext.empty); + let nullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, SideEffectLinkedToNoteHash.empty); + + const innerNullifier = (index: number) => index + 1; + + const makeReadRequest = (value: number, counter = 2) => + new ReadRequestContext(new Fr(value), counter, contractAddress); + + const makeNullifier = (value: number, counter = 1) => { + const siloedValue = siloNullifier(contractAddress, new Fr(value)); + return new SideEffectLinkedToNoteHash(siloedValue, new Fr(0), new Fr(counter)); + }; + + interface TestNullifier { + value: number; + siloedValue: Fr; + } + + const populateNullifiers = (numNullifiers = MAX_NEW_NULLIFIERS_PER_TX) => { + nullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, i => + i < numNullifiers ? makeNullifier(innerNullifier(i)) : SideEffectLinkedToNoteHash.empty(), + ); + }; + + const generateSortedNullifiers = (numNullifiers: number) => { + const nullifiers: TestNullifier[] = []; + for (let i = 0; i < numNullifiers; ++i) { + const value = i; + nullifiers.push({ + value, + siloedValue: siloNullifier(contractAddress, new Fr(value)), + }); + } + return nullifiers.sort((a, b) => (b.siloedValue.lt(a.siloedValue) ? 1 : -1)); + }; + + const buildHints = () => buildNullifierNonExistentReadRequestHints(oracle, nonExistentReadRequests, nullifiers); + + it('builds empty hints', async () => { + const hints = await buildHints(); + const emptyHints = NullifierNonExistentReadRequestHintsBuilder.empty(); + expect(hints).toEqual(emptyHints); + }); + + it('builds hints for full sorted nullifiers', async () => { + populateNullifiers(); + + const hints = await buildHints(); + const { sortedPendingValues, sortedPendingValueHints } = hints; + for (let i = 0; i < sortedPendingValues.length - 1; ++i) { + expect(sortedPendingValues[i].value.lt(sortedPendingValues[i + 1].value)).toBe(true); + } + for (let i = 0; i < nullifiers.length; ++i) { + const index = sortedPendingValueHints[i]; + expect(nullifiers[i].value.equals(sortedPendingValues[index].value)).toBe(true); + } + }); + + it('builds hints for half-full sorted nullifiers', async () => { + const numNonEmptyNullifiers = MAX_NEW_NULLIFIERS_PER_TX / 2; + populateNullifiers(numNonEmptyNullifiers); + + const hints = await buildHints(); + const { sortedPendingValues, sortedPendingValueHints } = hints; + + // The first half contains sorted values. + for (let i = 0; i < numNonEmptyNullifiers - 1; ++i) { + expect(sortedPendingValues[i]).not.toEqual(SideEffectLinkedToNoteHash.empty()); + expect(sortedPendingValues[i].value.lt(sortedPendingValues[i + 1].value)).toBe(true); + } + for (let i = 0; i < numNonEmptyNullifiers; ++i) { + const index = sortedPendingValueHints[i]; + expect(nullifiers[i].value.equals(sortedPendingValues[index].value)).toBe(true); + } + + // The second half is empty. + for (let i = numNonEmptyNullifiers; i < sortedPendingValues.length; ++i) { + expect(sortedPendingValues[i]).toEqual(SideEffectLinkedToNoteHash.empty()); + } + for (let i = numNonEmptyNullifiers; i < sortedPendingValueHints.length; ++i) { + expect(sortedPendingValueHints[i]).toBe(0); + } + }); + + it('builds hints for read requests', async () => { + const numNonEmptyNullifiers = MAX_NEW_NULLIFIERS_PER_TX / 2; + expect(numNonEmptyNullifiers > 1).toBe(true); // Need at least 2 nullifiers to test a value in the middle. + + const sortedNullifiers = generateSortedNullifiers(numNonEmptyNullifiers + 3); + const minNullifier = sortedNullifiers.splice(0, 1)[0]; + const maxNullifier = sortedNullifiers.pop()!; + const midIndex = Math.floor(numNonEmptyNullifiers / 2); + const midNullifier = sortedNullifiers.splice(midIndex, 1)[0]; + + nonExistentReadRequests[0] = makeReadRequest(midNullifier.value); + nonExistentReadRequests[1] = makeReadRequest(maxNullifier.value); + nonExistentReadRequests[2] = makeReadRequest(minNullifier.value); + nullifiers = padArrayEnd( + sortedNullifiers.map(n => makeNullifier(n.value)), + SideEffectLinkedToNoteHash.empty(), + MAX_NEW_NULLIFIERS_PER_TX, + ); + + const hints = await buildHints(); + const { nextPendingValueIndices } = hints; + expect(nextPendingValueIndices.slice(0, 3)).toEqual([midIndex, numNonEmptyNullifiers, 0]); + }); + + it('throws if reading existing value', async () => { + populateNullifiers(); + + nonExistentReadRequests[0] = makeReadRequest(innerNullifier(2)); + + await expect(() => buildHints()).rejects.toThrow('Nullifier exists in the pending set.'); + }); +}); diff --git a/yarn-project/circuits.js/src/hints/build_hints.ts b/yarn-project/circuits.js/src/hints/build_hints.ts index d80f4bd5c37..c22df8b15fe 100644 --- a/yarn-project/circuits.js/src/hints/build_hints.ts +++ b/yarn-project/circuits.js/src/hints/build_hints.ts @@ -1,34 +1,35 @@ +import { padArrayEnd } from '@aztec/foundation/collection'; import { Fr } from '@aztec/foundation/fields'; import { Tuple } from '@aztec/foundation/serialize'; +import { IndexedTreeLeafPreimage } from '@aztec/foundation/trees'; import { MAX_NEW_NULLIFIERS_PER_TX, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT, } from '../constants.gen.js'; import { siloNullifier } from '../hash/index.js'; import { MembershipWitness } from '../structs/membership_witness.js'; +import { NullifierNonExistentReadRequestHintsBuilder } from '../structs/non_existent_read_request_hints.js'; import { ReadRequestContext } from '../structs/read_request.js'; -import { NullifierReadRequestResetHintsBuilder } from '../structs/read_request_reset_hints.js'; -import { NullifierLeafPreimage } from '../structs/rollup/nullifier_leaf/index.js'; +import { NullifierReadRequestHintsBuilder } from '../structs/read_request_hints.js'; import { SideEffectLinkedToNoteHash } from '../structs/side_effects.js'; import { countAccumulatedItems } from './utils.js'; export interface NullifierMembershipWitnessWithPreimage { membershipWitness: MembershipWitness; - leafPreimage: NullifierLeafPreimage; + leafPreimage: IndexedTreeLeafPreimage; } -export interface HintsBuildingDataOracle { - getNullifierMembershipWitness(nullifier: Fr): Promise; -} - -export async function buildNullifierReadRequestResetHints( - oracle: HintsBuildingDataOracle, +export async function buildNullifierReadRequestHints( + oracle: { + getNullifierMembershipWitness(nullifier: Fr): Promise; + }, nullifierReadRequests: Tuple, nullifiers: Tuple, ) { - const builder = new NullifierReadRequestResetHintsBuilder(); + const builder = new NullifierReadRequestHintsBuilder(); const numReadRequests = countAccumulatedItems(nullifierReadRequests); @@ -58,3 +59,64 @@ export async function buildNullifierReadRequestResetHints( } return builder.toHints(); } + +interface SortedResult { + sortedValues: Tuple; + sortedIndexHints: Tuple; +} + +function sortNullifiersByValues( + nullifiers: Tuple, +): SortedResult { + const numNullifiers = countAccumulatedItems(nullifiers); + const sorted = nullifiers + .slice(0, numNullifiers) + .map((nullifier, originalIndex) => ({ nullifier, originalIndex })) + .sort((a, b) => (b.nullifier.value.lt(a.nullifier.value) ? 1 : -1)); + + const sortedIndexHints: number[] = []; + for (let i = 0; i < numNullifiers; ++i) { + sortedIndexHints[sorted[i].originalIndex] = i; + } + + return { + sortedValues: padArrayEnd( + sorted.map(s => s.nullifier), + SideEffectLinkedToNoteHash.empty(), + MAX_NEW_NULLIFIERS_PER_TX, + ), + sortedIndexHints: padArrayEnd(sortedIndexHints, 0, MAX_NEW_NULLIFIERS_PER_TX), + }; +} + +export async function buildNullifierNonExistentReadRequestHints( + oracle: { + getLowNullifierMembershipWitness(nullifier: Fr): Promise; + }, + nullifierNonExistentReadRequests: Tuple, + pendingNullifiers: Tuple, +) { + const { sortedValues, sortedIndexHints } = sortNullifiersByValues(pendingNullifiers); + + const builder = new NullifierNonExistentReadRequestHintsBuilder(sortedValues, sortedIndexHints); + + const numPendingNullifiers = countAccumulatedItems(pendingNullifiers); + const numReadRequests = countAccumulatedItems(nullifierNonExistentReadRequests); + for (let i = 0; i < numReadRequests; ++i) { + const readRequest = nullifierNonExistentReadRequests[i]; + const siloedValue = siloNullifier(readRequest.contractAddress, readRequest.value); + + const { membershipWitness, leafPreimage } = await oracle.getLowNullifierMembershipWitness(siloedValue); + + let nextPendingValueIndex = sortedValues.findIndex(v => !v.value.lt(siloedValue)); + if (nextPendingValueIndex == -1) { + nextPendingValueIndex = numPendingNullifiers; + } else if (sortedValues[nextPendingValueIndex].value.equals(siloedValue)) { + throw new Error('Nullifier exists in the pending set.'); + } + + builder.addHint(membershipWitness, leafPreimage, nextPendingValueIndex); + } + + return builder.toHints(); +} diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/contract_deployment_data.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/contract_deployment_data.test.ts.snap deleted file mode 100644 index 11a6dffff27..00000000000 --- a/yarn-project/circuits.js/src/structs/__snapshots__/contract_deployment_data.test.ts.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ContractDeploymentData computes empty hash 1`] = ` -Fr { - "asBigInt": 6550888889575534006716962010714219565950255479539883359305705974567832585221n, - "asBuffer": { - "data": [ - 14, - 123, - 171, - 245, - 157, - 232, - 223, - 199, - 245, - 153, - 44, - 211, - 79, - 176, - 6, - 97, - 5, - 208, - 124, - 230, - 127, - 104, - 252, - 51, - 212, - 160, - 166, - 169, - 51, - 163, - 4, - 5, - ], - "type": "Buffer", - }, -} -`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/function_data.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/function_data.test.ts.snap index c33c05599b4..c7ba85df59c 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/function_data.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/function_data.test.ts.snap @@ -1,44 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`FunctionData computes empty inputs hash 1`] = ` -Fr { - "asBigInt": 14483571110897883400419490783710119837459619381345566311432831352122387488397n, - "asBuffer": { - "data": [ - 32, - 5, - 105, - 38, - 124, - 15, - 115, - 172, - 137, - 170, - 164, - 20, - 35, - 147, - 152, - 219, - 148, - 69, - 221, - 74, - 211, - 168, - 207, - 55, - 1, - 92, - 213, - 91, - 141, - 76, - 94, - 141, - ], - "type": "Buffer", - }, -} -`; +exports[`FunctionData computes empty inputs hash 1`] = `Fr<0x200569267c0f73ac89aaa414239398db9445dd4ad3a8cf37015cd55b8d4c5e8d>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/function_leaf_preimage.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/function_leaf_preimage.test.ts.snap index d20affc7cbc..d6d47cb4160 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/function_leaf_preimage.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/function_leaf_preimage.test.ts.snap @@ -1,44 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`FunctionLeafPreimage computes a function leaf 1`] = ` -Fr { - "asBigInt": 14103315440711420844377567457355366382339442623996583897989070814921979368695n, - "asBuffer": { - "data": [ - 31, - 46, - 49, - 147, - 199, - 24, - 115, - 71, - 160, - 153, - 238, - 124, - 181, - 214, - 172, - 7, - 125, - 166, - 177, - 135, - 6, - 254, - 85, - 8, - 230, - 88, - 163, - 208, - 160, - 84, - 148, - 247, - ], - "type": "Buffer", - }, -} -`; +exports[`FunctionLeafPreimage computes a function leaf 1`] = `Fr<0x1f2e3193c7187347a099ee7cb5d6ac077da6b18706fe5508e658a3d0a05494f7>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/header.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/header.test.ts.snap index 501bd971e54..9c3ca6a483b 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/header.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/header.test.ts.snap @@ -1,87 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Header computes empty hash 1`] = ` -Fr { - "asBigInt": 20794359902049712309840803989537372971066838126069955186305683313093334375790n, - "asBuffer": { - "data": [ - 45, - 249, - 48, - 204, - 123, - 159, - 199, - 99, - 232, - 42, - 222, - 114, - 247, - 196, - 97, - 136, - 52, - 105, - 43, - 42, - 61, - 9, - 54, - 175, - 248, - 215, - 187, - 251, - 39, - 245, - 157, - 110, - ], - "type": "Buffer", - }, -} -`; +exports[`Header computes empty hash 1`] = `Fr<0x124e8c40a6eca2e3ad10c04050b01a3fad00df3cea47b13592c7571b6914c7a7>`; -exports[`Header computes hash 1`] = ` -Fr { - "asBigInt": 17965313985247589544372198735324565090920557482351371957268170919526618141863n, - "asBuffer": { - "data": [ - 39, - 184, - 1, - 227, - 84, - 195, - 178, - 90, - 6, - 248, - 237, - 161, - 177, - 253, - 166, - 87, - 161, - 67, - 151, - 185, - 244, - 147, - 251, - 142, - 40, - 36, - 177, - 92, - 201, - 16, - 148, - 167, - ], - "type": "Buffer", - }, -} -`; +exports[`Header computes hash 1`] = `Fr<0x1d9b824f3561e706d9e85fde89a60a1e5c25dff839167cba7366ca8f6ee96890>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap index b33e985b0ed..ba1d123faee 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap @@ -1,87 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCallStackItem computes empty item hash 1`] = ` -Fr { - "asBigInt": 11728545222320447463870615847019406452447697153424151627800539679719144535960n, - "asBuffer": { - "data": [ - 25, - 238, - 31, - 16, - 197, - 192, - 80, - 138, - 141, - 114, - 125, - 160, - 12, - 151, - 184, - 25, - 133, - 34, - 215, - 161, - 127, - 171, - 115, - 235, - 128, - 79, - 36, - 24, - 49, - 119, - 183, - 152, - ], - "type": "Buffer", - }, -} -`; +exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x1c3b67cab2bc3dc2106cfeddd8ea68b8d445849f20ed3b9286ad684542aae25d>`; -exports[`PrivateCallStackItem computes hash 1`] = ` -Fr { - "asBigInt": 6461024313550232992012690944449959956801421547254954441618992574842987860340n, - "asBuffer": { - "data": [ - 14, - 72, - 207, - 103, - 60, - 81, - 67, - 141, - 102, - 164, - 56, - 11, - 55, - 163, - 108, - 206, - 136, - 68, - 246, - 140, - 171, - 112, - 139, - 222, - 67, - 9, - 45, - 31, - 20, - 79, - 209, - 116, - ], - "type": "Buffer", - }, -} -`; +exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x22029fc3a0b18b8f9fe4d5cdb237b9b5580c9dd2368299936d8deedf13d742c3>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap index 658eb5ad80c..1514ccd533d 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap @@ -1,87 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = ` -Fr { - "asBigInt": 8922874219514432875012773391923445472064121190200882885713359100997704012295n, - "asBuffer": { - "data": [ - 19, - 186, - 42, - 247, - 94, - 74, - 250, - 164, - 229, - 45, - 209, - 175, - 160, - 131, - 232, - 119, - 6, - 205, - 186, - 177, - 163, - 52, - 66, - 2, - 93, - 195, - 169, - 187, - 181, - 70, - 210, - 7, - ], - "type": "Buffer", - }, -} -`; +exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x2745ec62624afeb19b86af3d440db1f8c3432e1d17a074c75cb8f44999fd3fae>`; -exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = ` -Fr { - "asBigInt": 7066918351069413889843757132918099018108150218337345110167110186913735749525n, - "asBuffer": { - "data": [ - 15, - 159, - 187, - 234, - 36, - 85, - 47, - 1, - 117, - 177, - 232, - 159, - 46, - 23, - 164, - 203, - 100, - 106, - 64, - 164, - 198, - 12, - 59, - 118, - 51, - 144, - 90, - 35, - 200, - 25, - 175, - 149, - ], - "type": "Buffer", - }, -} -`; +exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x05eec129252f2229777f96446c2901e660c6e01e196000b57c99fb3aec43b160>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap index f0b947728b1..f48aceba2c8 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap @@ -1,48 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x182201ec06be2dc7eddaa8b828eb293eab9938c4d41cde1e2b1b766ee21d2a54"`; +exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x187836686ed01f12180ef08c419e4ac8514d9c60e6a38b4a56d893fa90c83a5d"`; -exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x10017014b5fd719261c575bd7acd1e604c0dd3e86d8c6af80294eadfc6d174a7"`; +exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x1a1194c14f229b72d31669b06e3984d6f0f5edd4d5204ceda0ff30f25e910e83"`; -exports[`PublicCallStackItem computes hash 1`] = ` -Fr { - "asBigInt": 45410678569143484234609653232067005723125960091308451781456680995218457503n, - "asBuffer": { - "data": [ - 0, - 25, - 179, - 151, - 174, - 187, - 246, - 36, - 171, - 201, - 108, - 111, - 243, - 253, - 214, - 195, - 214, - 206, - 229, - 122, - 245, - 52, - 105, - 87, - 65, - 44, - 87, - 45, - 27, - 159, - 3, - 159, - ], - "type": "Buffer", - }, -} -`; +exports[`PublicCallStackItem computes hash 1`] = `Fr<0x0ef0cbf32ad96d5f6c7577b023a3b4f9a9cd5d53a8c9eb268324183aaa1437ff>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap index 7a5dd3fc1f0..201d5c667eb 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap @@ -1,87 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCircuitPublicInputs computes empty item hash 1`] = ` -Fr { - "asBigInt": 899041383159782383308350091877472492566207915893045234143560027519589938411n, - "asBuffer": { - "data": [ - 1, - 252, - 214, - 226, - 72, - 9, - 9, - 213, - 95, - 3, - 244, - 238, - 135, - 146, - 76, - 186, - 187, - 11, - 71, - 6, - 203, - 116, - 44, - 112, - 66, - 46, - 66, - 59, - 45, - 181, - 244, - 235, - ], - "type": "Buffer", - }, -} -`; +exports[`PublicCircuitPublicInputs computes empty item hash 1`] = `Fr<0x1c9942cee14a4f84b3e606f553b2ab3151c395822ee7ffd51759d5822375d6c9>`; -exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = ` -Fr { - "asBigInt": 11132983907867837190629216452861649594433048836605582311662020710335671547249n, - "asBuffer": { - "data": [ - 24, - 157, - 11, - 171, - 221, - 156, - 218, - 207, - 106, - 253, - 198, - 99, - 204, - 123, - 221, - 188, - 0, - 191, - 126, - 172, - 98, - 53, - 110, - 180, - 142, - 8, - 253, - 250, - 103, - 217, - 181, - 113, - ], - "type": "Buffer", - }, -} -`; +exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x1135d901dacdffe956b9cd85c976a2c5fe311018164a3ec612ff8ed89f8d56cb>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap index 40d9eb511f0..981e17e3f15 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/tx_context.test.ts.snap @@ -1,44 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`TxContext computes empty hash 1`] = ` -Fr { - "asBigInt": 21032445753769195248650393789370064301738468736130164917667517476782805795195n, - "asBuffer": { - "data": [ - 46, - 127, - 241, - 67, - 137, - 238, - 243, - 220, - 81, - 89, - 117, - 41, - 20, - 158, - 1, - 180, - 156, - 179, - 56, - 41, - 247, - 8, - 148, - 56, - 200, - 193, - 69, - 200, - 243, - 82, - 193, - 123, - ], - "type": "Buffer", - }, -} -`; +exports[`TxContext computes empty hash 1`] = `Fr<0x200569267c0f73ac89aaa414239398db9445dd4ad3a8cf37015cd55b8d4c5e8d>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/tx_request.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/tx_request.test.ts.snap index fd6001beca6..4de712a3404 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/tx_request.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/tx_request.test.ts.snap @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`TxRequest compute hash 1`] = `"0x05e3f67a5e787faf63c85c28169a9d616b594c9799d9785b4f167d9cd7a71e9e"`; +exports[`TxRequest compute hash 1`] = `"0x0ab4eaebf540be2999b50051b3c272b5bf7be23d59233b6d453272a42c3c08e5"`; diff --git a/yarn-project/circuits.js/src/structs/call_context.ts b/yarn-project/circuits.js/src/structs/call_context.ts index 0e79e08f399..a7a1d328487 100644 --- a/yarn-project/circuits.js/src/structs/call_context.ts +++ b/yarn-project/circuits.js/src/structs/call_context.ts @@ -38,10 +38,6 @@ export class CallContext { * Determines whether the call is modifying state. */ public isStaticCall: boolean, - /** - * Determines whether the call is a contract deployment. - */ - public isContractDeployment: boolean, /** * The start side effect counter for this call context. */ @@ -60,7 +56,6 @@ export class CallContext { FunctionSelector.empty(), false, false, - false, 0, ); } @@ -87,7 +82,6 @@ export class CallContext { fields.functionSelector, fields.isDelegateCall, fields.isStaticCall, - fields.isContractDeployment, fields.startSideEffectCounter, ] as const; } @@ -124,7 +118,6 @@ export class CallContext { reader.readObject(FunctionSelector), reader.readBoolean(), reader.readBoolean(), - reader.readBoolean(), reader.readNumber(), ); } @@ -138,7 +131,6 @@ export class CallContext { reader.readObject(FunctionSelector), reader.readBoolean(), reader.readBoolean(), - reader.readBoolean(), reader.readU32(), ); } @@ -151,7 +143,6 @@ export class CallContext { callContext.functionSelector.equals(this.functionSelector) && callContext.isDelegateCall === this.isDelegateCall && callContext.isStaticCall === this.isStaticCall && - callContext.isContractDeployment === this.isContractDeployment && callContext.startSideEffectCounter === this.startSideEffectCounter ); } diff --git a/yarn-project/circuits.js/src/structs/contract_deployment_data.test.ts b/yarn-project/circuits.js/src/structs/contract_deployment_data.test.ts deleted file mode 100644 index 9bddc3a47cf..00000000000 --- a/yarn-project/circuits.js/src/structs/contract_deployment_data.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { CONTRACT_DEPLOYMENT_DATA_LENGTH } from '../constants.gen.js'; -import { makeContractDeploymentData } from '../tests/factories.js'; -import { ContractDeploymentData } from './contract_deployment_data.js'; - -describe('ContractDeploymentData', () => { - it(`serializes to buffer and deserializes it back`, () => { - const expected = makeContractDeploymentData(1); - const buffer = expected.toBuffer(); - const res = ContractDeploymentData.fromBuffer(buffer); - expect(res).toEqual(expected); - expect(res.isEmpty()).toBe(false); - }); - - it('number of fields matches constant', () => { - const target = makeContractDeploymentData(327); - const fields = target.toFields(); - expect(fields.length).toBe(CONTRACT_DEPLOYMENT_DATA_LENGTH); - }); - - it('computes empty hash', () => { - const cd = ContractDeploymentData.empty(); - expect(cd.isEmpty()).toBe(true); - - const hash = cd.hash(); - expect(hash).toMatchSnapshot(); - - // Value used in empty_hash test in contract_deployment_data.nr - // console.log("hash", hash.toString()); - }); -}); diff --git a/yarn-project/circuits.js/src/structs/contract_deployment_data.ts b/yarn-project/circuits.js/src/structs/contract_deployment_data.ts deleted file mode 100644 index e7fdb5d7e71..00000000000 --- a/yarn-project/circuits.js/src/structs/contract_deployment_data.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { pedersenHash } from '@aztec/foundation/crypto'; -import { EthAddress } from '@aztec/foundation/eth-address'; -import { Fr, Point } from '@aztec/foundation/fields'; -import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; -import { FieldsOf } from '@aztec/foundation/types'; - -import { CONTRACT_DEPLOYMENT_DATA_LENGTH, GeneratorIndex } from '../constants.gen.js'; -import { PublicKey } from '../types/public_key.js'; - -/** - * Contract deployment data in a TxContext - * Not to be confused with NewContractData. - */ -export class ContractDeploymentData { - constructor( - /** Public key of the contract. */ - public publicKey: PublicKey, - /** Hash of the initialization payload. */ - public initializationHash: Fr, - /** Contract class identifier. */ - public contractClassId: Fr, - /** Contract address salt (used when deriving a contract address). */ - public contractAddressSalt: Fr, - /** Ethereum address of the portal contract on L1. */ - public portalContractAddress: EthAddress, - ) {} - - static getFields(fields: FieldsOf) { - return [ - fields.publicKey, - fields.initializationHash, - fields.contractClassId, - fields.contractAddressSalt, - fields.portalContractAddress, - ] as const; - } - - toBuffer() { - return serializeToBuffer(...ContractDeploymentData.getFields(this)); - } - - toFields(): Fr[] { - const fields = serializeToFields(...ContractDeploymentData.getFields(this)); - if (fields.length !== CONTRACT_DEPLOYMENT_DATA_LENGTH) { - throw new Error( - `Invalid number of fields for ContractDeploymentData. Expected ${CONTRACT_DEPLOYMENT_DATA_LENGTH}, got ${fields.length}`, - ); - } - return fields; - } - - /** - * Returns an empty ContractDeploymentData. - * @returns The empty ContractDeploymentData. - */ - public static empty(): ContractDeploymentData { - return new ContractDeploymentData(Point.ZERO, Fr.ZERO, Fr.ZERO, Fr.ZERO, EthAddress.ZERO); - } - - isEmpty() { - return ContractDeploymentData.getFields(this).every(f => f.isZero()); - } - - /** - * Deserializes contract deployment data rom a buffer or reader. - * @param buffer - Buffer to read from. - * @returns The deserialized ContractDeploymentData. - */ - static fromBuffer(buffer: Buffer | BufferReader): ContractDeploymentData { - const reader = BufferReader.asReader(buffer); - return new ContractDeploymentData( - reader.readObject(Point), - Fr.fromBuffer(reader), - Fr.fromBuffer(reader), - Fr.fromBuffer(reader), - reader.readObject(EthAddress), - ); - } - - static fromFields(fields: Fr[] | FieldReader): ContractDeploymentData { - const reader = FieldReader.asReader(fields); - return new ContractDeploymentData( - reader.readObject(Point), - reader.readField(), - reader.readField(), - reader.readField(), - reader.readObject(EthAddress), - ); - } - - hash(): Fr { - return pedersenHash( - this.toFields().map(f => f.toBuffer()), - GeneratorIndex.CONTRACT_DEPLOYMENT_DATA, - ); - } -} diff --git a/yarn-project/circuits.js/src/structs/function_data.test.ts b/yarn-project/circuits.js/src/structs/function_data.test.ts index 85ddf5a6730..6ee66e3a16a 100644 --- a/yarn-project/circuits.js/src/structs/function_data.test.ts +++ b/yarn-project/circuits.js/src/structs/function_data.test.ts @@ -1,4 +1,5 @@ import { FunctionSelector } from '@aztec/foundation/abi'; +import { setupCustomSnapshotSerializers } from '@aztec/foundation/testing'; import { FUNCTION_DATA_LENGTH } from '../constants.gen.js'; import { FunctionData } from './function_data.js'; @@ -7,6 +8,7 @@ describe('FunctionData', () => { let functionData: FunctionData; beforeAll(() => { + setupCustomSnapshotSerializers(expect); functionData = new FunctionData(new FunctionSelector(123), false, true, true); }); diff --git a/yarn-project/circuits.js/src/structs/function_data.ts b/yarn-project/circuits.js/src/structs/function_data.ts index 310d03507aa..65a6cfee4bb 100644 --- a/yarn-project/circuits.js/src/structs/function_data.ts +++ b/yarn-project/circuits.js/src/structs/function_data.ts @@ -8,6 +8,7 @@ import { ContractFunctionDao } from '../types/contract_function_dao.js'; /** * Function description for circuit. + * TODO(palla/purge-old-contract-deploy): Remove constructor and possibly internal flags from this struct. */ export class FunctionData { constructor( diff --git a/yarn-project/circuits.js/src/structs/function_leaf_preimage.test.ts b/yarn-project/circuits.js/src/structs/function_leaf_preimage.test.ts index 9b23593f85f..1a41faa900e 100644 --- a/yarn-project/circuits.js/src/structs/function_leaf_preimage.test.ts +++ b/yarn-project/circuits.js/src/structs/function_leaf_preimage.test.ts @@ -1,5 +1,6 @@ import { FunctionSelector } from '@aztec/foundation/abi'; import { Fr } from '@aztec/foundation/fields'; +import { setupCustomSnapshotSerializers } from '@aztec/foundation/testing'; import { FUNCTION_LEAF_PREIMAGE_LENGTH } from '../constants.gen.js'; import { FunctionLeafPreimage } from './function_leaf_preimage.js'; @@ -8,6 +9,7 @@ describe('FunctionLeafPreimage', () => { let leaf: FunctionLeafPreimage; beforeAll(() => { + setupCustomSnapshotSerializers(expect); leaf = new FunctionLeafPreimage(new FunctionSelector(8972), false, true, Fr.ZERO, Fr.ZERO); }); diff --git a/yarn-project/circuits.js/src/structs/global_variables.ts b/yarn-project/circuits.js/src/structs/global_variables.ts index 3b117686064..05c90e8b0e3 100644 --- a/yarn-project/circuits.js/src/structs/global_variables.ts +++ b/yarn-project/circuits.js/src/structs/global_variables.ts @@ -1,9 +1,10 @@ +import { AztecAddress } from '@aztec/foundation/aztec-address'; +import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; import { FieldsOf } from '@aztec/foundation/types'; import { GLOBAL_VARIABLES_LENGTH } from '../constants.gen.js'; -import { AztecAddress, EthAddress } from './index.js'; /** * Global variables of the L2 block. diff --git a/yarn-project/circuits.js/src/structs/header.test.ts b/yarn-project/circuits.js/src/structs/header.test.ts index 0cdd77ea8c8..e087ba2cbe1 100644 --- a/yarn-project/circuits.js/src/structs/header.test.ts +++ b/yarn-project/circuits.js/src/structs/header.test.ts @@ -1,3 +1,5 @@ +import { setupCustomSnapshotSerializers, updateInlineTestData } from '@aztec/foundation/testing'; + import { HEADER_LENGTH } from '../constants.gen.js'; import { makeHeader } from '../tests/factories.js'; import { Header } from './header.js'; @@ -6,6 +8,7 @@ describe('Header', () => { let header: Header; beforeAll(() => { + setupCustomSnapshotSerializers(expect); const randomInt = Math.floor(Math.random() * 1000); header = makeHeader(randomInt, undefined); }); @@ -39,7 +42,11 @@ describe('Header', () => { const hash = header.hash(); expect(hash).toMatchSnapshot(); - // Value used in empty_hash test in header.nr - // console.log("hash", hash.toString()); + // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data + updateInlineTestData( + 'noir-projects/noir-protocol-circuits/crates/types/src/header.nr', + 'test_data_empty_hash', + hash.toString(), + ); }); }); diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index 5ec39a492e0..2a1b8079c16 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -4,7 +4,6 @@ export * from './call_context.js'; export * from './call_request.js'; export * from './complete_address.js'; export * from './content_commitment.js'; -export * from './contract_deployment_data.js'; export * from './contract_storage_read.js'; export * from './contract_storage_update_request.js'; export * from './function_data.js'; @@ -13,7 +12,6 @@ export * from './global_variables.js'; export * from './header.js'; export * from './kernel/combined_accumulated_data.js'; export * from './kernel/combined_constant_data.js'; -export * from './kernel/new_contract_data.js'; export * from './kernel/private_call_data.js'; export * from './kernel/private_kernel_init_circuit_private_inputs.js'; export * from './kernel/private_kernel_inner_circuit_private_inputs.js'; @@ -41,7 +39,8 @@ export * from './public_call_stack_item.js'; export * from './public_circuit_public_inputs.js'; export * from './read_request.js'; export * from './note_hash_read_request_membership_witness.js'; -export * from './read_request_reset_hints.js'; +export * from './read_request_hints.js'; +export * from './non_existent_read_request_hints.js'; export * from './rollup/append_only_tree_snapshot.js'; export * from './rollup/base_or_merge_rollup_public_inputs.js'; export * from './rollup/base_rollup.js'; diff --git a/yarn-project/circuits.js/src/structs/kernel/__snapshots__/new_contract_data.test.ts.snap b/yarn-project/circuits.js/src/structs/kernel/__snapshots__/new_contract_data.test.ts.snap deleted file mode 100644 index 1166a008d9e..00000000000 --- a/yarn-project/circuits.js/src/structs/kernel/__snapshots__/new_contract_data.test.ts.snap +++ /dev/null @@ -1,87 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`NewContractData computes contract leaf 1`] = ` -Fr { - "asBigInt": 1205669559362216690501113071754010899122564402260118295790326203728712063609n, - "asBuffer": { - "data": [ - 2, - 170, - 98, - 129, - 115, - 236, - 158, - 132, - 183, - 0, - 14, - 176, - 170, - 124, - 64, - 104, - 64, - 24, - 101, - 95, - 230, - 204, - 70, - 89, - 105, - 38, - 142, - 94, - 141, - 66, - 90, - 121, - ], - "type": "Buffer", - }, -} -`; - -exports[`NewContractData hash matches 1`] = ` -Fr { - "asBigInt": 15989124907542145791377884953407893320840303158499919884975910897341668572939n, - "asBuffer": { - "data": [ - 35, - 89, - 134, - 36, - 130, - 251, - 88, - 207, - 90, - 93, - 218, - 181, - 110, - 182, - 212, - 153, - 8, - 188, - 129, - 19, - 83, - 243, - 253, - 111, - 233, - 253, - 5, - 124, - 82, - 92, - 191, - 11, - ], - "type": "Buffer", - }, -} -`; diff --git a/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts index 65689c76f70..cc281831036 100644 --- a/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts @@ -7,7 +7,6 @@ import { BufferReader, Tuple, serializeToBuffer } from '@aztec/foundation/serial import { inspect } from 'util'; import { - MAX_NEW_CONTRACTS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, @@ -19,6 +18,7 @@ import { MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, @@ -35,7 +35,6 @@ import { CallRequest } from '../call_request.js'; import { NullifierKeyValidationRequestContext } from '../nullifier_key_validation_request.js'; import { ReadRequestContext } from '../read_request.js'; import { SideEffect, SideEffectLinkedToNoteHash } from '../side_effects.js'; -import { NewContractData } from './new_contract_data.js'; const log = createDebugOnlyLogger('aztec:combined_accumulated_data'); @@ -217,10 +216,6 @@ export class CombinedAccumulatedData { * Total accumulated length of the unencrypted log preimages emitted in all the previous kernel iterations */ public unencryptedLogPreimagesLength: Fr, - /** - * All the new contracts deployed in this transaction. - */ - public newContracts: Tuple, /** * All the public data update requests made in this transaction. */ @@ -245,7 +240,6 @@ export class CombinedAccumulatedData { this.unencryptedLogsHash, this.encryptedLogPreimagesLength, this.unencryptedLogPreimagesLength, - this.newContracts, this.publicDataUpdateRequests, this.publicDataReads, ); @@ -275,7 +269,6 @@ export class CombinedAccumulatedData { reader.readArray(2, Fr), Fr.fromBuffer(reader), Fr.fromBuffer(reader), - reader.readArray(MAX_NEW_CONTRACTS_PER_TX, NewContractData), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead), ); @@ -304,7 +297,6 @@ export class CombinedAccumulatedData { makeTuple(2, Fr.zero), Fr.zero(), Fr.zero(), - makeTuple(MAX_NEW_CONTRACTS_PER_TX, NewContractData.empty), makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest.empty), makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead.empty), ); @@ -383,7 +375,6 @@ export class CombinedAccumulatedData { revertible.unencryptedLogsHash, revertible.encryptedLogPreimagesLength, revertible.unencryptedLogPreimagesLength, - revertible.newContracts, publicDataUpdateRequests, publicDataReads, ); @@ -445,10 +436,6 @@ export class PublicAccumulatedRevertibleData { * Total accumulated length of the unencrypted log preimages emitted in all the previous kernel iterations */ public unencryptedLogPreimagesLength: Fr, - /** - * All the new contracts deployed in this transaction. - */ - public newContracts: Tuple, /** * All the public data update requests made in this transaction. */ @@ -475,7 +462,6 @@ export class PublicAccumulatedRevertibleData { this.unencryptedLogsHash, this.encryptedLogPreimagesLength, this.unencryptedLogPreimagesLength, - this.newContracts, this.publicDataUpdateRequests, this.publicDataReads, ); @@ -499,7 +485,6 @@ export class PublicAccumulatedRevertibleData { this.unencryptedLogsHash.every(x => x.isZero()) && this.encryptedLogPreimagesLength.isZero() && this.unencryptedLogPreimagesLength.isZero() && - this.newContracts.every(x => x.isEmpty()) && this.publicDataUpdateRequests.every(x => x.isEmpty()) && this.publicDataReads.every(x => x.isEmpty()) ); @@ -520,7 +505,6 @@ export class PublicAccumulatedRevertibleData { unencryptedLogsHash: [${this.unencryptedLogsHash.map(h => h.toString()).join(', ')}], encryptedLogPreimagesLength: ${this.encryptedLogPreimagesLength} unencryptedLogPreimagesLength: ${this.unencryptedLogPreimagesLength} - newContracts: [${this.newContracts.map(h => h.toString()).join(', ')}], publicDataUpdateRequests: [${this.publicDataUpdateRequests.map(h => h.toString()).join(', ')}], publicDataReads: [${this.publicDataReads.map(h => h.toString()).join(', ')}], }`; @@ -546,7 +530,6 @@ export class PublicAccumulatedRevertibleData { reader.readArray(2, Fr), Fr.fromBuffer(reader), Fr.fromBuffer(reader), - reader.readArray(MAX_NEW_CONTRACTS_PER_TX, NewContractData), reader.readArray(MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), reader.readArray(MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, PublicDataRead), ); @@ -566,7 +549,6 @@ export class PublicAccumulatedRevertibleData { finalData.unencryptedLogsHash, finalData.encryptedLogPreimagesLength, finalData.unencryptedLogPreimagesLength, - finalData.newContracts, makeTuple(MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest.empty), makeTuple(MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, PublicDataRead.empty), ); @@ -595,7 +577,6 @@ export class PublicAccumulatedRevertibleData { makeTuple(2, Fr.zero), Fr.zero(), Fr.zero(), - makeTuple(MAX_NEW_CONTRACTS_PER_TX, NewContractData.empty), makeTuple(MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest.empty), makeTuple(MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, PublicDataRead.empty), ); @@ -647,10 +628,6 @@ export class PrivateAccumulatedRevertibleData { * Total accumulated length of the unencrypted log preimages emitted in all the previous kernel iterations */ public unencryptedLogPreimagesLength: Fr, - /** - * All the new contracts deployed in this transaction. - */ - public newContracts: Tuple, ) {} toBuffer() { @@ -664,7 +641,6 @@ export class PrivateAccumulatedRevertibleData { this.unencryptedLogsHash, this.encryptedLogPreimagesLength, this.unencryptedLogPreimagesLength, - this.newContracts, ); } @@ -689,7 +665,6 @@ export class PrivateAccumulatedRevertibleData { reader.readArray(2, Fr), Fr.fromBuffer(reader), Fr.fromBuffer(reader), - reader.readArray(MAX_NEW_CONTRACTS_PER_TX, NewContractData), ); } @@ -713,7 +688,6 @@ export class PrivateAccumulatedRevertibleData { makeTuple(2, Fr.zero), Fr.zero(), Fr.zero(), - makeTuple(MAX_NEW_CONTRACTS_PER_TX, NewContractData.empty), ); } } @@ -770,6 +744,13 @@ export class PublicAccumulatedNonRevertibleData { * The nullifier read requests made in this transaction. */ public nullifierReadRequests: Tuple, + /** + * The nullifier read requests made in this transaction. + */ + public nullifierNonExistentReadRequests: Tuple< + ReadRequestContext, + typeof MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX + >, /** * The new non-revertible commitments made in this transaction. */ @@ -798,6 +779,7 @@ export class PublicAccumulatedNonRevertibleData { toBuffer() { return serializeToBuffer( this.nullifierReadRequests, + this.nullifierNonExistentReadRequests, this.newNoteHashes, this.newNullifiers, this.publicCallStack, @@ -810,6 +792,7 @@ export class PublicAccumulatedNonRevertibleData { const reader = BufferReader.asReader(buffer); return new this( reader.readArray(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ReadRequestContext), + reader.readArray(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ReadRequestContext), reader.readArray(MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX, SideEffect), reader.readArray(MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX, SideEffectLinkedToNoteHash), reader.readArray(MAX_NON_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, CallRequest), @@ -829,6 +812,7 @@ export class PublicAccumulatedNonRevertibleData { static empty() { return new this( makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ReadRequestContext.empty), + makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ReadRequestContext.empty), makeTuple(MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX, SideEffect.empty), makeTuple(MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX, SideEffectLinkedToNoteHash.empty), makeTuple(MAX_NON_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, CallRequest.empty), @@ -840,6 +824,7 @@ export class PublicAccumulatedNonRevertibleData { static fromPrivateAccumulatedNonRevertibleData(data: PrivateAccumulatedNonRevertibleData) { return new this( makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ReadRequestContext.empty), + makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ReadRequestContext.empty), data.newNoteHashes, data.newNullifiers, data.publicCallStack, diff --git a/yarn-project/circuits.js/src/structs/kernel/new_contract_data.test.ts b/yarn-project/circuits.js/src/structs/kernel/new_contract_data.test.ts deleted file mode 100644 index 73dc20f8e67..00000000000 --- a/yarn-project/circuits.js/src/structs/kernel/new_contract_data.test.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Fr } from '@aztec/foundation/fields'; - -import { NEW_CONTRACT_DATA_LENGTH } from '../../constants.gen.js'; -import { makeNewContractData } from '../../tests/factories.js'; -import { NewContractData } from './new_contract_data.js'; - -describe('NewContractData', () => { - let data: NewContractData; - - beforeAll(() => { - const randomInt = Math.floor(Math.random() * 1000); - data = makeNewContractData(randomInt); - }); - - it('serializes to buffer and deserializes it back', () => { - const buffer = data.toBuffer(); - const res = NewContractData.fromBuffer(buffer); - expect(res).toEqual(data); - }); - - it('number of fields matches constant', () => { - const fields = data.toFields(); - expect(fields.length).toBe(NEW_CONTRACT_DATA_LENGTH); - }); - - it('computes contract leaf', () => { - const cd = makeNewContractData(12); - const hash = cd.hash(); - expect(hash).toMatchSnapshot(); - }); - - it('empty "hash" is zero', () => { - const cd = NewContractData.empty(); - expect(cd.isEmpty()).toBe(true); - - const hash = cd.hash(); - expect(hash).toEqual(Fr.ZERO); - }); - - it('hash matches', () => { - const cd = makeNewContractData(5); - const hash = cd.hash(); - expect(hash).toMatchSnapshot(); - - // Value used in hash_matches test in new_contract_data.nr - // console.log("hash", hash.toString()); - }); -}); diff --git a/yarn-project/circuits.js/src/structs/kernel/new_contract_data.ts b/yarn-project/circuits.js/src/structs/kernel/new_contract_data.ts deleted file mode 100644 index 82921fc545f..00000000000 --- a/yarn-project/circuits.js/src/structs/kernel/new_contract_data.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { pedersenHash } from '@aztec/foundation/crypto'; -import { EthAddress } from '@aztec/foundation/eth-address'; -import { Fr } from '@aztec/foundation/fields'; -import { BufferReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; -import { FieldsOf } from '@aztec/foundation/types'; - -import { GeneratorIndex, NEW_CONTRACT_DATA_LENGTH } from '../../constants.gen.js'; - -/** - * The information assembled after the contract deployment was processed by the private kernel circuit. - * - * Note: Not to be confused with `ContractDeploymentData`. - */ -export class NewContractData { - constructor( - /** - * Aztec address of the contract. - */ - public contractAddress: AztecAddress, - /** - * Ethereum address of the portal contract on L1. - */ - public portalContractAddress: EthAddress, - /** - * Contract class id. - */ - public contractClassId: Fr, - ) {} - - static getFields(fields: FieldsOf) { - return [fields.contractAddress, fields.portalContractAddress, fields.contractClassId] as const; - } - - toBuffer() { - return serializeToBuffer(...NewContractData.getFields(this)); - } - - toFields() { - const fields = serializeToFields(...NewContractData.getFields(this)); - if (fields.length !== NEW_CONTRACT_DATA_LENGTH) { - throw new Error( - `Invalid number of fields for NewContractData. Expected ${NEW_CONTRACT_DATA_LENGTH}, got ${fields.length}`, - ); - } - return fields; - } - - /** - * Computes a hash of contract data which is a leaf in the contracts tree. - * @param cd - The contract data of the deployed contract. - * @returns The contract data hash/contract tree leaf. - */ - hash(): Fr { - if (this.isEmpty()) { - return new Fr(0); - } - return pedersenHash( - NewContractData.getFields(this).map(f => f.toBuffer()), - GeneratorIndex.CONTRACT_LEAF, - ); - } - - /** - * Deserializes from a buffer or reader, corresponding to a write in cpp. - * @param buffer - Buffer or reader to read from. - * @returns The deserialized `NewContractData`. - */ - static fromBuffer(buffer: Buffer | BufferReader): NewContractData { - const reader = BufferReader.asReader(buffer); - return new NewContractData(reader.readObject(AztecAddress), reader.readObject(EthAddress), Fr.fromBuffer(reader)); - } - - static empty() { - return new NewContractData(AztecAddress.ZERO, EthAddress.ZERO, Fr.ZERO); - } - - /** - * Checks if the data is empty. - * @returns True if the data operation is empty, false otherwise. - */ - isEmpty(): boolean { - return this.contractAddress.isZero() && this.portalContractAddress.isZero() && this.contractClassId.isZero(); - } -} diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts index da7f5cd14e1..2f90462d3bd 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts @@ -8,10 +8,7 @@ import { } from '../../constants.gen.js'; import { GrumpkinPrivateKey } from '../../index.js'; import { Fr, GrumpkinScalar } from '../index.js'; -import { - NullifierReadRequestResetHints, - nullifierReadRequestResetHintsFromBuffer, -} from '../read_request_reset_hints.js'; +import { NullifierReadRequestHints, nullifierReadRequestHintsFromBuffer } from '../read_request_hints.js'; import { SideEffect, SideEffectLinkedToNoteHash } from '../side_effects.js'; import { PrivateKernelInnerData } from './private_kernel_inner_data.js'; @@ -47,7 +44,7 @@ export class PrivateKernelTailCircuitPrivateInputs { /** * Contains hints for the nullifier read requests to locate corresponding pending or settled nullifiers. */ - public nullifierReadRequestResetHints: NullifierReadRequestResetHints, + public nullifierReadRequestHints: NullifierReadRequestHints, /** * Contains hints for the transient nullifiers to localize corresponding commitments. */ @@ -70,7 +67,7 @@ export class PrivateKernelTailCircuitPrivateInputs { this.readCommitmentHints, this.sortedNewNullifiers, this.sortedNewNullifiersIndexes, - this.nullifierReadRequestResetHints, + this.nullifierReadRequestHints, this.nullifierCommitmentHints, this.masterNullifierSecretKeys, ); @@ -90,7 +87,7 @@ export class PrivateKernelTailCircuitPrivateInputs { reader.readArray(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, Fr), reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, SideEffectLinkedToNoteHash), reader.readNumbers(MAX_NEW_NULLIFIERS_PER_TX), - reader.readObject({ fromBuffer: nullifierReadRequestResetHintsFromBuffer }), + reader.readObject({ fromBuffer: nullifierReadRequestHintsFromBuffer }), reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, Fr), reader.readArray(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GrumpkinScalar), ); diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts index 37d79805d11..77f3bc4cf11 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts @@ -1,6 +1,7 @@ import { serializeToBuffer } from '@aztec/foundation/serialize'; -import { NullifierReadRequestResetHints } from '../read_request_reset_hints.js'; +import { NullifierNonExistentReadRequestHints } from '../non_existent_read_request_hints.js'; +import { NullifierReadRequestHints } from '../read_request_hints.js'; import { PublicKernelData } from './public_kernel_data.js'; /** @@ -15,10 +16,18 @@ export class PublicKernelTailCircuitPrivateInputs { /** * Contains hints for the nullifier read requests to locate corresponding pending or settled nullifiers. */ - public nullifierReadRequestResetHints: NullifierReadRequestResetHints, + public readonly nullifierReadRequestHints: NullifierReadRequestHints, + /** + * Contains hints for the nullifier non existent read requests. + */ + public readonly nullifierNonExistentReadRequestHints: NullifierNonExistentReadRequestHints, ) {} toBuffer() { - return serializeToBuffer(this.previousKernel, this.nullifierReadRequestResetHints); + return serializeToBuffer( + this.previousKernel, + this.nullifierReadRequestHints, + this.nullifierNonExistentReadRequestHints, + ); } } diff --git a/yarn-project/circuits.js/src/structs/non_existent_read_request_hints.ts b/yarn-project/circuits.js/src/structs/non_existent_read_request_hints.ts new file mode 100644 index 00000000000..9cd254bc0b9 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/non_existent_read_request_hints.ts @@ -0,0 +1,152 @@ +import { makeTuple } from '@aztec/foundation/array'; +import { BufferReader, Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { IndexedTreeLeafPreimage } from '@aztec/foundation/trees'; + +import { + MAX_NEW_NULLIFIERS_PER_TX, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, + NULLIFIER_TREE_HEIGHT, +} from '../constants.gen.js'; +import { MembershipWitness } from './membership_witness.js'; +import { NullifierLeafPreimage } from './rollup/nullifier_leaf/index.js'; +import { SideEffectLinkedToNoteHash, SideEffectType } from './side_effects.js'; + +export class NonMembershipHint { + constructor(public membershipWitness: MembershipWitness, public leafPreimage: LEAF_PREIMAGE) {} + + static empty( + treeHeight: TREE_HEIGHT, + makeEmptyLeafPreimage: () => LEAF_PREIMAGE, + ) { + return new NonMembershipHint(MembershipWitness.empty(treeHeight, 0n), makeEmptyLeafPreimage()); + } + + static fromBuffer( + buffer: Buffer | BufferReader, + treeHeight: TREE_HEIGHT, + leafPreimageFromBuffer: { fromBuffer: (buffer: BufferReader) => LEAF_PREIMAGE }, + ): NonMembershipHint { + const reader = BufferReader.asReader(buffer); + return new NonMembershipHint( + MembershipWitness.fromBuffer(reader, treeHeight), + reader.readObject(leafPreimageFromBuffer), + ); + } + + toBuffer() { + return serializeToBuffer(this.membershipWitness, this.leafPreimage); + } +} + +export class NonExistentReadRequestHints< + READ_REQUEST_LEN extends number, + TREE_HEIGHT extends number, + LEAF_PREIMAGE extends IndexedTreeLeafPreimage, + PENDING_VALUE_LEN extends number, + PENDING_VALUE extends SideEffectType, +> { + constructor( + /** + * The hints for the low leaves of the read requests. + */ + public nonMembershipHints: Tuple, READ_REQUEST_LEN>, + /** + * Indices of the smallest pending values greater than the read requests. + */ + public nextPendingValueIndices: Tuple, + public sortedPendingValues: Tuple, + public sortedPendingValueHints: Tuple, + ) {} + + static fromBuffer< + READ_REQUEST_LEN extends number, + TREE_HEIGHT extends number, + LEAF_PREIMAGE extends IndexedTreeLeafPreimage, + PENDING_VALUE_LEN extends number, + PENDING_VALUE extends SideEffectType, + >( + buffer: Buffer | BufferReader, + readRequestLen: READ_REQUEST_LEN, + treeHeight: TREE_HEIGHT, + leafPreimageFromBuffer: { fromBuffer: (buffer: BufferReader) => LEAF_PREIMAGE }, + pendingValueLen: PENDING_VALUE_LEN, + orderedValueFromBuffer: { fromBuffer: (buffer: BufferReader) => PENDING_VALUE }, + ): NonExistentReadRequestHints { + const reader = BufferReader.asReader(buffer); + return new NonExistentReadRequestHints( + reader.readArray(readRequestLen, { + fromBuffer: buf => NonMembershipHint.fromBuffer(buf, treeHeight, leafPreimageFromBuffer), + }), + reader.readNumbers(readRequestLen), + reader.readArray(pendingValueLen, orderedValueFromBuffer), + reader.readNumbers(pendingValueLen), + ); + } + + toBuffer() { + return serializeToBuffer(this.nonMembershipHints, this.nextPendingValueIndices); + } +} + +export type NullifierNonExistentReadRequestHints = NonExistentReadRequestHints< + typeof MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, + typeof NULLIFIER_TREE_HEIGHT, + IndexedTreeLeafPreimage, + typeof MAX_NEW_NULLIFIERS_PER_TX, + SideEffectLinkedToNoteHash +>; + +export function nullifierNonExistentReadRequestHintsFromBuffer( + buffer: Buffer | BufferReader, +): NullifierNonExistentReadRequestHints { + return NonExistentReadRequestHints.fromBuffer( + buffer, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, + NULLIFIER_TREE_HEIGHT, + NullifierLeafPreimage, + MAX_NEW_NULLIFIERS_PER_TX, + SideEffectLinkedToNoteHash, + ); +} + +export class NullifierNonExistentReadRequestHintsBuilder { + private hints: NullifierNonExistentReadRequestHints; + private readRequestIndex = 0; + + constructor( + sortedPendingNullifiers: Tuple, + sortedPendingNullifierIndexHints: Tuple, + ) { + this.hints = new NonExistentReadRequestHints( + makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, () => + NonMembershipHint.empty(NULLIFIER_TREE_HEIGHT, NullifierLeafPreimage.empty), + ), + makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, () => 0), + sortedPendingNullifiers, + sortedPendingNullifierIndexHints, + ); + } + + static empty() { + const emptySortedPendingNullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, SideEffectLinkedToNoteHash.empty); + const emptySortedPendingNullifierIndexHints = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, () => 0); + return new NullifierNonExistentReadRequestHintsBuilder( + emptySortedPendingNullifiers, + emptySortedPendingNullifierIndexHints, + ).toHints(); + } + + addHint( + membershipWitness: MembershipWitness, + lowLeafPreimage: IndexedTreeLeafPreimage, + nextPendingValueIndex: number, + ) { + this.hints.nonMembershipHints[this.readRequestIndex] = new NonMembershipHint(membershipWitness, lowLeafPreimage); + this.hints.nextPendingValueIndices[this.readRequestIndex] = nextPendingValueIndex; + this.readRequestIndex++; + } + + toHints() { + return this.hints; + } +} diff --git a/yarn-project/circuits.js/src/structs/partial_state_reference.ts b/yarn-project/circuits.js/src/structs/partial_state_reference.ts index 28dbd86654e..0ca6b790f38 100644 --- a/yarn-project/circuits.js/src/structs/partial_state_reference.ts +++ b/yarn-project/circuits.js/src/structs/partial_state_reference.ts @@ -13,8 +13,6 @@ export class PartialStateReference { public readonly noteHashTree: AppendOnlyTreeSnapshot, /** Snapshot of the nullifier tree. */ public readonly nullifierTree: AppendOnlyTreeSnapshot, - /** Snapshot of the contract tree. */ - public readonly contractTree: AppendOnlyTreeSnapshot, /** Snapshot of the public data tree. */ public readonly publicDataTree: AppendOnlyTreeSnapshot, ) {} @@ -25,7 +23,6 @@ export class PartialStateReference { reader.readObject(AppendOnlyTreeSnapshot), reader.readObject(AppendOnlyTreeSnapshot), reader.readObject(AppendOnlyTreeSnapshot), - reader.readObject(AppendOnlyTreeSnapshot), ); } @@ -34,10 +31,9 @@ export class PartialStateReference { const noteHashTree = AppendOnlyTreeSnapshot.fromFields(reader); const nullifierTree = AppendOnlyTreeSnapshot.fromFields(reader); - const contractTree = AppendOnlyTreeSnapshot.fromFields(reader); const publicDataTree = AppendOnlyTreeSnapshot.fromFields(reader); - return new PartialStateReference(noteHashTree, nullifierTree, contractTree, publicDataTree); + return new PartialStateReference(noteHashTree, nullifierTree, publicDataTree); } static empty(): PartialStateReference { @@ -45,19 +41,17 @@ export class PartialStateReference { AppendOnlyTreeSnapshot.zero(), AppendOnlyTreeSnapshot.zero(), AppendOnlyTreeSnapshot.zero(), - AppendOnlyTreeSnapshot.zero(), ); } toBuffer() { - return serializeToBuffer(this.noteHashTree, this.nullifierTree, this.contractTree, this.publicDataTree); + return serializeToBuffer(this.noteHashTree, this.nullifierTree, this.publicDataTree); } toFields() { const fields = [ ...this.noteHashTree.toFields(), ...this.nullifierTree.toFields(), - ...this.contractTree.toFields(), ...this.publicDataTree.toFields(), ]; if (fields.length !== PARTIAL_STATE_REFERENCE_LENGTH) { @@ -69,11 +63,6 @@ export class PartialStateReference { } isEmpty(): boolean { - return ( - this.noteHashTree.isZero() && - this.nullifierTree.isZero() && - this.contractTree.isZero() && - this.publicDataTree.isZero() - ); + return this.noteHashTree.isZero() && this.nullifierTree.isZero() && this.publicDataTree.isZero(); } } diff --git a/yarn-project/circuits.js/src/structs/private_call_stack_item.test.ts b/yarn-project/circuits.js/src/structs/private_call_stack_item.test.ts index a47f725551e..4fb5783c6dc 100644 --- a/yarn-project/circuits.js/src/structs/private_call_stack_item.test.ts +++ b/yarn-project/circuits.js/src/structs/private_call_stack_item.test.ts @@ -1,3 +1,5 @@ +import { setupCustomSnapshotSerializers, updateInlineTestData } from '@aztec/foundation/testing'; + import { PRIVATE_CALL_STACK_ITEM_LENGTH } from '../constants.gen.js'; import { makePrivateCallStackItem } from '../tests/factories.js'; import { PrivateCallStackItem } from './private_call_stack_item.js'; @@ -6,6 +8,7 @@ describe('PrivateCallStackItem', () => { let item: PrivateCallStackItem; beforeAll(() => { + setupCustomSnapshotSerializers(expect); const randomInt = Math.floor(Math.random() * 1000); item = makePrivateCallStackItem(randomInt); }); @@ -39,7 +42,11 @@ describe('PrivateCallStackItem', () => { const hash = item.hash(); expect(hash).toMatchSnapshot(); - // Value used in empty_hash test in private_call_stack_item.nr - // console.log("hash", hash.toString()); + // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data + updateInlineTestData( + 'noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr', + 'test_data_empty_hash', + hash.toString(), + ); }); }); diff --git a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.test.ts b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.test.ts index ab415ed487e..2e6eb6f4bf5 100644 --- a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.test.ts +++ b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.test.ts @@ -1,3 +1,5 @@ +import { setupCustomSnapshotSerializers, updateInlineTestData } from '@aztec/foundation/testing'; + import { PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH } from '../constants.gen.js'; import { makePrivateCircuitPublicInputs } from '../tests/factories.js'; import { PrivateCircuitPublicInputs } from './private_circuit_public_inputs.js'; @@ -6,6 +8,7 @@ describe('PrivateCircuitPublicInputs', () => { let inputs: PrivateCircuitPublicInputs; beforeAll(() => { + setupCustomSnapshotSerializers(expect); const randomInt = Math.floor(Math.random() * 1000); inputs = makePrivateCircuitPublicInputs(randomInt); }); @@ -43,7 +46,11 @@ describe('PrivateCircuitPublicInputs', () => { const hash = inputs.hash(); expect(hash).toMatchSnapshot(); - // Value used in empty_hash test in private_circuit_public_inputs.nr - // console.log("hash", hash.toString()); + // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data + updateInlineTestData( + 'noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr', + 'test_data_empty_hash', + hash.toString(), + ); }); }); diff --git a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts index af8fd80dac8..48d6f7c49c7 100644 --- a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts @@ -19,7 +19,6 @@ import { PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, RETURN_VALUES_LENGTH, } from '../constants.gen.js'; -import { ContractDeploymentData } from '../structs/contract_deployment_data.js'; import { Header } from '../structs/header.js'; import { SideEffect, SideEffectLinkedToNoteHash } from '../structs/side_effects.js'; import { CallContext } from './call_context.js'; @@ -112,10 +111,6 @@ export class PrivateCircuitPublicInputs { * Header of a block whose state is used during private execution (not the block the transaction is included in). */ public historicalHeader: Header, - /** - * Deployment data of contracts being deployed in this kernel iteration. - */ - public contractDeploymentData: ContractDeploymentData, /** * Chain Id of the instance. * @@ -165,7 +160,6 @@ export class PrivateCircuitPublicInputs { reader.readObject(Fr), reader.readObject(Fr), reader.readObject(Header), - reader.readObject(ContractDeploymentData), reader.readObject(Fr), reader.readObject(Fr), ); @@ -192,7 +186,6 @@ export class PrivateCircuitPublicInputs { reader.readField(), reader.readField(), reader.readObject(Header), - reader.readObject(ContractDeploymentData), reader.readField(), reader.readField(), ); @@ -222,7 +215,6 @@ export class PrivateCircuitPublicInputs { Fr.ZERO, Fr.ZERO, Header.empty(), - ContractDeploymentData.empty(), Fr.ZERO, Fr.ZERO, ); @@ -251,7 +243,6 @@ export class PrivateCircuitPublicInputs { this.encryptedLogPreimagesLength.isZero() && this.unencryptedLogPreimagesLength.isZero() && this.historicalHeader.isEmpty() && - this.contractDeploymentData.isEmpty() && this.chainId.isZero() && this.version.isZero() ); @@ -282,7 +273,6 @@ export class PrivateCircuitPublicInputs { fields.encryptedLogPreimagesLength, fields.unencryptedLogPreimagesLength, fields.historicalHeader, - fields.contractDeploymentData, fields.chainId, fields.version, ] as const; diff --git a/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts b/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts index c615bc6f77d..247e5a75fba 100644 --- a/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts +++ b/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts @@ -1,8 +1,11 @@ +import { setupCustomSnapshotSerializers, updateInlineTestData } from '@aztec/foundation/testing'; + import { makePublicCallStackItem } from '../tests/factories.js'; import { AztecAddress, Fr, FunctionData, FunctionSelector, SideEffect } from './index.js'; import { PublicCallStackItem } from './public_call_stack_item.js'; describe('PublicCallStackItem', () => { + setupCustomSnapshotSerializers(expect); it('serializes to buffer and deserializes it back', () => { const randomInt = Math.floor(Math.random() * 1000); const expected = makePublicCallStackItem(randomInt); @@ -29,8 +32,12 @@ describe('PublicCallStackItem', () => { const hash = callStack.hash(); expect(hash.toString()).toMatchSnapshot(); - // Value used in compute_call_stack_item_hash test in public_call_stack_item.test.ts - // console.log("hash", hash.toString()); + // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data + updateInlineTestData( + 'noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr', + 'test_data_call_stack_item_request_hash', + hash.toString(), + ); }); it('Computes a callstack item hash', () => { @@ -43,7 +50,11 @@ describe('PublicCallStackItem', () => { const hash = callStack.hash(); expect(hash.toString()).toMatchSnapshot(); - // Value used in compute_call_stack_item_request_hash test in public_call_stack_item.test.ts - // console.log("hash", hash.toString()); + // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data + updateInlineTestData( + 'noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr', + 'test_data_call_stack_item_hash', + hash.toString(), + ); }); }); diff --git a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.test.ts b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.test.ts index a69c18ad6ec..59a49edea89 100644 --- a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.test.ts +++ b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.test.ts @@ -1,8 +1,11 @@ +import { setupCustomSnapshotSerializers, updateInlineTestData } from '@aztec/foundation/testing'; + import { PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH } from '../constants.gen.js'; import { makePublicCircuitPublicInputs } from '../tests/factories.js'; import { PublicCircuitPublicInputs } from './public_circuit_public_inputs.js'; describe('PublicCircuitPublicInputs', () => { + setupCustomSnapshotSerializers(expect); it('serializes to field array and deserializes it back', () => { const randomInt = Math.floor(Math.random() * 1000); const expected = makePublicCircuitPublicInputs(randomInt, undefined); @@ -34,7 +37,11 @@ describe('PublicCircuitPublicInputs', () => { const hash = item.hash(); expect(hash).toMatchSnapshot(); - // Value used in empty_hash test in public_circuit_public_inputs.nr - // console.log('hash', hash.toString()); + // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data + updateInlineTestData( + 'noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr', + 'test_data_empty_hash', + hash.toString(), + ); }); }); diff --git a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts index f4a23e63ac4..8ee7a9375cb 100644 --- a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts @@ -11,6 +11,7 @@ import { MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, @@ -48,6 +49,13 @@ export class PublicCircuitPublicInputs { * Nullifier read requests executed during the call. */ public nullifierReadRequests: Tuple, + /** + * Nullifier non existent read requests executed during the call. + */ + public nullifierNonExistentReadRequests: Tuple< + ReadRequest, + typeof MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL + >, /** * Contract storage update requests executed during the call. */ @@ -119,6 +127,7 @@ export class PublicCircuitPublicInputs { Fr.ZERO, makeTuple(RETURN_VALUES_LENGTH, Fr.zero), makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_CALL, ReadRequest.empty), + makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, ReadRequest.empty), makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ContractStorageUpdateRequest.empty), makeTuple(MAX_PUBLIC_DATA_READS_PER_CALL, ContractStorageRead.empty), makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, Fr.zero), @@ -143,6 +152,7 @@ export class PublicCircuitPublicInputs { this.argsHash.isZero() && isFrArrayEmpty(this.returnValues) && isArrayEmpty(this.nullifierReadRequests, item => item.isEmpty()) && + isArrayEmpty(this.nullifierNonExistentReadRequests, item => item.isEmpty()) && isArrayEmpty(this.contractStorageUpdateRequests, item => item.isEmpty()) && isArrayEmpty(this.contractStorageReads, item => item.isEmpty()) && isFrArrayEmpty(this.publicCallStackHashes) && @@ -168,6 +178,7 @@ export class PublicCircuitPublicInputs { fields.argsHash, fields.returnValues, fields.nullifierReadRequests, + fields.nullifierNonExistentReadRequests, fields.contractStorageUpdateRequests, fields.contractStorageReads, fields.publicCallStackHashes, @@ -212,6 +223,7 @@ export class PublicCircuitPublicInputs { reader.readObject(Fr), reader.readArray(RETURN_VALUES_LENGTH, Fr), reader.readArray(MAX_NULLIFIER_READ_REQUESTS_PER_CALL, ReadRequest), + reader.readArray(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, ReadRequest), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ContractStorageUpdateRequest), reader.readArray(MAX_PUBLIC_DATA_READS_PER_CALL, ContractStorageRead), reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, Fr), @@ -234,6 +246,7 @@ export class PublicCircuitPublicInputs { reader.readField(), reader.readFieldArray(RETURN_VALUES_LENGTH), reader.readArray(MAX_NULLIFIER_READ_REQUESTS_PER_CALL, ReadRequest), + reader.readArray(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, ReadRequest), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ContractStorageUpdateRequest), reader.readArray(MAX_PUBLIC_DATA_READS_PER_CALL, ContractStorageRead), reader.readFieldArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL), diff --git a/yarn-project/circuits.js/src/structs/read_request_reset_hints.ts b/yarn-project/circuits.js/src/structs/read_request_hints.ts similarity index 82% rename from yarn-project/circuits.js/src/structs/read_request_reset_hints.ts rename to yarn-project/circuits.js/src/structs/read_request_hints.ts index ef43419940a..880b71a4467 100644 --- a/yarn-project/circuits.js/src/structs/read_request_reset_hints.ts +++ b/yarn-project/circuits.js/src/structs/read_request_hints.ts @@ -1,5 +1,6 @@ import { makeTuple } from '@aztec/foundation/array'; import { BufferReader, Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { TreeLeafPreimage } from '@aztec/foundation/trees'; import { MAX_NULLIFIER_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT } from '../constants.gen.js'; import { MembershipWitness } from './membership_witness.js'; @@ -45,35 +46,31 @@ export class PendingReadHint { } } -interface LeafPreimageHint { - toBuffer(): Buffer; -} - -export class SettledReadHint { +export class SettledReadHint { constructor( public readRequestIndex: number, public membershipWitness: MembershipWitness, - public leafPreimage: LEAF_PREIMAGE_HINT, + public leafPreimage: LEAF_PREIMAGE, ) {} - static nada( + static nada( readRequestLen: number, treeHeight: TREE_HEIGHT, - emptyLeafPreimage: () => LEAF_PREIMAGE_HINT, + emptyLeafPreimage: () => LEAF_PREIMAGE, ) { return new SettledReadHint(readRequestLen, MembershipWitness.empty(treeHeight, 0n), emptyLeafPreimage()); } - static fromBuffer( + static fromBuffer( buffer: Buffer | BufferReader, treeHeight: TREE_HEIGHT, - leafPreimageFromBuffer: { fromBuffer: (buffer: BufferReader) => LEAF_PREIMAGE_HINT }, - ): SettledReadHint { + leafPreimage: { fromBuffer(buffer: BufferReader): LEAF_PREIMAGE }, + ): SettledReadHint { const reader = BufferReader.asReader(buffer); return new SettledReadHint( reader.readNumber(), MembershipWitness.fromBuffer(reader, treeHeight), - reader.readObject(leafPreimageFromBuffer), + reader.readObject(leafPreimage), ); } @@ -90,7 +87,7 @@ export class ReadRequestResetHints< NUM_PENDING_READS extends number, NUM_SETTLED_READS extends number, TREE_HEIGHT extends number, - LEAF_PREIMAGE_HINT extends LeafPreimageHint, + LEAF_PREIMAGE extends TreeLeafPreimage, > { constructor( public readRequestStatuses: Tuple, @@ -101,7 +98,7 @@ export class ReadRequestResetHints< /** * The hints for read requests reading settled values. */ - public settledReadHints: Tuple, NUM_SETTLED_READS>, + public settledReadHints: Tuple, NUM_SETTLED_READS>, ) {} /** @@ -114,15 +111,15 @@ export class ReadRequestResetHints< NUM_PENDING_READS extends number, NUM_SETTLED_READS extends number, TREE_HEIGHT extends number, - LEAF_PREIMAGE_HINT extends LeafPreimageHint, + LEAF_PREIMAGE extends TreeLeafPreimage, >( buffer: Buffer | BufferReader, readRequestLen: READ_REQUEST_LEN, numPendingReads: NUM_PENDING_READS, numSettledReads: NUM_SETTLED_READS, treeHeight: TREE_HEIGHT, - leafPreimageFromBuffer: { fromBuffer: (buffer: BufferReader) => LEAF_PREIMAGE_HINT }, - ): ReadRequestResetHints { + leafPreimageFromBuffer: { fromBuffer: (buffer: BufferReader) => LEAF_PREIMAGE }, + ): ReadRequestResetHints { const reader = BufferReader.asReader(buffer); return new ReadRequestResetHints( reader.readArray(readRequestLen, ReadRequestStatus), @@ -138,17 +135,15 @@ export class ReadRequestResetHints< } } -export type NullifierReadRequestResetHints = ReadRequestResetHints< +export type NullifierReadRequestHints = ReadRequestResetHints< typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX, typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX, typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX, typeof NULLIFIER_TREE_HEIGHT, - NullifierLeafPreimage + TreeLeafPreimage >; -export function nullifierReadRequestResetHintsFromBuffer( - buffer: Buffer | BufferReader, -): NullifierReadRequestResetHints { +export function nullifierReadRequestHintsFromBuffer(buffer: Buffer | BufferReader): NullifierReadRequestHints { return ReadRequestResetHints.fromBuffer( buffer, MAX_NULLIFIER_READ_REQUESTS_PER_TX, @@ -159,8 +154,8 @@ export function nullifierReadRequestResetHintsFromBuffer( ); } -export class NullifierReadRequestResetHintsBuilder { - private hints: NullifierReadRequestResetHints; +export class NullifierReadRequestHintsBuilder { + private hints: NullifierReadRequestHints; private numPendingReadHints = 0; private numSettledReadHints = 0; @@ -175,7 +170,7 @@ export class NullifierReadRequestResetHintsBuilder { } static empty() { - return new NullifierReadRequestResetHintsBuilder().toHints(); + return new NullifierReadRequestHintsBuilder().toHints(); } addPendingReadRequest(readRequestIndex: number, nullifierIndex: number) { @@ -190,7 +185,7 @@ export class NullifierReadRequestResetHintsBuilder { addSettledReadRequest( readRequestIndex: number, membershipWitness: MembershipWitness, - leafPreimage: NullifierLeafPreimage, + leafPreimage: TreeLeafPreimage, ) { this.hints.readRequestStatuses[readRequestIndex] = new ReadRequestStatus( ReadRequestState.SETTLED, diff --git a/yarn-project/circuits.js/src/structs/rollup/state_diff_hints.ts b/yarn-project/circuits.js/src/structs/rollup/state_diff_hints.ts index a73b13372f7..1a812819433 100644 --- a/yarn-project/circuits.js/src/structs/rollup/state_diff_hints.ts +++ b/yarn-project/circuits.js/src/structs/rollup/state_diff_hints.ts @@ -3,7 +3,6 @@ import { Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; import { FieldsOf } from '@aztec/foundation/types'; import { - CONTRACT_SUBTREE_SIBLING_PATH_LENGTH, MAX_NEW_NULLIFIERS_PER_TX, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, @@ -47,10 +46,6 @@ export class StateDiffHints { * Sibling path "pointing to" where the new nullifiers subtree should be inserted into the nullifier tree. */ public nullifierSubtreeSiblingPath: Tuple, - /** - * Sibling path "pointing to" where the new contracts subtree should be inserted into the contract tree. - */ - public contractSubtreeSiblingPath: Tuple, /** * Sibling path "pointing to" where the new public data subtree should be inserted into the public data tree. */ @@ -69,7 +64,6 @@ export class StateDiffHints { fields.sortedNullifierIndexes, fields.noteHashSubtreeSiblingPath, fields.nullifierSubtreeSiblingPath, - fields.contractSubtreeSiblingPath, fields.publicDataSiblingPath, ] as const; } diff --git a/yarn-project/circuits.js/src/structs/tx_context.test.ts b/yarn-project/circuits.js/src/structs/tx_context.test.ts index d090be9f0ed..71e3a580c28 100644 --- a/yarn-project/circuits.js/src/structs/tx_context.test.ts +++ b/yarn-project/circuits.js/src/structs/tx_context.test.ts @@ -1,3 +1,5 @@ +import { setupCustomSnapshotSerializers, updateInlineTestData } from '@aztec/foundation/testing'; + import { TX_CONTEXT_DATA_LENGTH } from '../constants.gen.js'; import { makeTxContext } from '../tests/factories.js'; import { TxContext } from './tx_context.js'; @@ -6,6 +8,7 @@ describe('TxContext', () => { let context: TxContext; beforeAll(() => { + setupCustomSnapshotSerializers(expect); const randomInt = Math.floor(Math.random() * 1000); context = makeTxContext(randomInt); }); @@ -29,7 +32,11 @@ describe('TxContext', () => { const hash = tc.hash(); expect(hash).toMatchSnapshot(); - // Value used in empty_hash test in contract_deployment_data.nr - // console.log("hash", hash.toString()); + // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data + updateInlineTestData( + 'noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr', + 'test_data_empty_hash', + hash.toString(), + ); }); }); diff --git a/yarn-project/circuits.js/src/structs/tx_context.ts b/yarn-project/circuits.js/src/structs/tx_context.ts index e66e0596ed8..577d4da75d1 100644 --- a/yarn-project/circuits.js/src/structs/tx_context.ts +++ b/yarn-project/circuits.js/src/structs/tx_context.ts @@ -4,7 +4,6 @@ import { BufferReader, serializeToBuffer, serializeToFields } from '@aztec/found import { FieldsOf } from '@aztec/foundation/types'; import { GeneratorIndex, TX_CONTEXT_DATA_LENGTH } from '../constants.gen.js'; -import { ContractDeploymentData } from '../structs/contract_deployment_data.js'; /** * Transaction context. @@ -26,14 +25,6 @@ export class TxContext { * the user. */ public isRebatePaymentTx: boolean, - /** - * Whether this is a contract deployment tx. - */ - public isContractDeploymentTx: boolean, - /** - * Contract deployment data. - */ - public contractDeploymentData: ContractDeploymentData, /** * Chain ID of the transaction. Here for replay protection. */ @@ -69,29 +60,15 @@ export class TxContext { */ static fromBuffer(buffer: Buffer | BufferReader): TxContext { const reader = BufferReader.asReader(buffer); - return new TxContext( - reader.readBoolean(), - reader.readBoolean(), - reader.readBoolean(), - reader.readObject(ContractDeploymentData), - Fr.fromBuffer(reader), - Fr.fromBuffer(reader), - ); + return new TxContext(reader.readBoolean(), reader.readBoolean(), Fr.fromBuffer(reader), Fr.fromBuffer(reader)); } static empty(chainId: Fr | number = 0, version: Fr | number = 0) { - return new TxContext(false, false, false, ContractDeploymentData.empty(), new Fr(chainId), new Fr(version)); + return new TxContext(false, false, new Fr(chainId), new Fr(version)); } isEmpty(): boolean { - return ( - !this.isFeePaymentTx && - !this.isRebatePaymentTx && - !this.isContractDeploymentTx && - this.contractDeploymentData.isEmpty() && - this.chainId.isZero() && - this.version.isZero() - ); + return !this.isFeePaymentTx && !this.isRebatePaymentTx && this.chainId.isZero() && this.version.isZero(); } /** @@ -109,14 +86,7 @@ export class TxContext { * @returns The array. */ static getFields(fields: FieldsOf) { - return [ - fields.isFeePaymentTx, - fields.isRebatePaymentTx, - fields.isContractDeploymentTx, - fields.contractDeploymentData, - fields.chainId, - fields.version, - ] as const; + return [fields.isFeePaymentTx, fields.isRebatePaymentTx, fields.chainId, fields.version] as const; } hash(): Fr { diff --git a/yarn-project/circuits.js/src/structs/tx_request.test.ts b/yarn-project/circuits.js/src/structs/tx_request.test.ts index 82ef6ff0361..cae72c92474 100644 --- a/yarn-project/circuits.js/src/structs/tx_request.test.ts +++ b/yarn-project/circuits.js/src/structs/tx_request.test.ts @@ -1,12 +1,11 @@ import { FunctionSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { Fr, Point } from '@aztec/foundation/fields'; +import { Fr } from '@aztec/foundation/fields'; +import { setupCustomSnapshotSerializers, updateInlineTestData } from '@aztec/foundation/testing'; import { TX_REQUEST_LENGTH } from '../constants.gen.js'; import { makeTxRequest } from '../tests/factories.js'; -import { ContractDeploymentData } from './contract_deployment_data.js'; import { FunctionData } from './function_data.js'; -import { EthAddress } from './index.js'; import { TxContext } from './tx_context.js'; import { TxRequest } from './tx_request.js'; @@ -14,6 +13,7 @@ describe('TxRequest', () => { let request: TxRequest; beforeAll(() => { + setupCustomSnapshotSerializers(expect); const randomInt = Math.floor(Math.random() * 1000); request = makeTxRequest(randomInt); }); @@ -31,25 +31,22 @@ describe('TxRequest', () => { }); it('compute hash', () => { - const deploymentData = new ContractDeploymentData( - new Point(new Fr(1), new Fr(2)), - new Fr(1), - new Fr(2), - new Fr(3), - EthAddress.fromField(new Fr(1)), - ); const txRequest = TxRequest.from({ origin: AztecAddress.fromBigInt(1n), functionData: new FunctionData(FunctionSelector.fromField(new Fr(2n)), false, true, true), argsHash: new Fr(3), - txContext: new TxContext(false, false, true, deploymentData, Fr.ZERO, Fr.ZERO), + txContext: new TxContext(false, false, Fr.ZERO, Fr.ZERO), }); const hash = txRequest.hash().toString(); expect(hash).toMatchSnapshot(); - // Value used in hash test in tx_request.nr - // console.log("hash", hash); + // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data + updateInlineTestData( + 'noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr', + 'test_data_tx_request_hash', + hash, + ); }); }); diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 128800b95b6..4a08435fb34 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -13,7 +13,6 @@ import { AppendOnlyTreeSnapshot, BaseOrMergeRollupPublicInputs, BaseRollupInputs, - CONTRACT_SUBTREE_SIBLING_PATH_LENGTH, CallContext, CallRequest, CallerContext, @@ -21,7 +20,6 @@ import { CombinedAccumulatedData, CombinedConstantData, ConstantRollupData, - ContractDeploymentData, ContractStorageRead, ContractStorageUpdateRequest, FUNCTION_TREE_HEIGHT, @@ -34,7 +32,6 @@ import { GrumpkinScalar, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, L2ToL1Message, - MAX_NEW_CONTRACTS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_CALL, @@ -50,6 +47,8 @@ import { MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, @@ -73,7 +72,6 @@ import { NULLIFIER_TREE_HEIGHT, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NUM_FIELDS_PER_SHA256, - NewContractData, NoteHashReadRequestMembershipWitness, NullifierKeyValidationRequest, NullifierKeyValidationRequestContext, @@ -157,8 +155,7 @@ export function makeNewSideEffectLinkedToNoteHash(seed: number): SideEffectLinke */ export function makeTxContext(seed: number): TxContext { // @todo @LHerskind should probably take value for chainId as it will be verified later. - // @todo @LHerskind should probably take value for version as it will be verified later. - return new TxContext(false, false, true, makeContractDeploymentData(seed), Fr.ZERO, Fr.ZERO); + return new TxContext(false, false, new Fr(seed), Fr.ZERO); } /** @@ -286,7 +283,6 @@ export function makeCombinedAccumulatedData(seed = 1, full = false): CombinedAcc tupleGenerator(2, fr, seed + 0x800), // unencrypted logs hash fr(seed + 0x900), // encrypted_log_preimages_length fr(seed + 0xa00), // unencrypted_log_preimages_length - tupleGenerator(MAX_NEW_CONTRACTS_PER_TX, makeNewContractData, seed + 0xb00), tupleGenerator(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, makePublicDataUpdateRequest, seed + 0xd00), tupleGenerator(MAX_PUBLIC_DATA_READS_PER_TX, makePublicDataRead, seed + 0xe00), ); @@ -317,7 +313,6 @@ export function makeCombinedAccumulatedRevertibleData(seed = 1, full = false): P tupleGenerator(2, fr, seed + 0x800), // unencrypted logs hash fr(seed + 0x900), // encrypted_log_preimages_length fr(seed + 0xa00), // unencrypted_log_preimages_length - tupleGenerator(MAX_NEW_CONTRACTS_PER_TX, makeNewContractData, seed + 0xb00), tupleGenerator(MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, makePublicDataUpdateRequest, seed + 0xd00), tupleGenerator(MAX_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, makePublicDataRead, seed + 0xe00), ); @@ -341,7 +336,6 @@ export function makeFinalAccumulatedData(seed = 1, full = false): PrivateAccumul tupleGenerator(2, fr, seed + 0x800), // unencrypted logs hash fr(seed + 0x900), // encrypted_log_preimages_length fr(seed + 0xa00), // unencrypted_log_preimages_length - tupleGenerator(MAX_NEW_CONTRACTS_PER_TX, makeNewContractData, seed + 0xb00), ); } @@ -365,6 +359,7 @@ export function makeCombinedAccumulatedNonRevertibleData(seed = 1, full = false) return new PublicAccumulatedNonRevertibleData( tupleGenerator(MAX_NULLIFIER_READ_REQUESTS_PER_TX, makeReadRequestContext, seed + 0x91), + tupleGenerator(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, makeReadRequestContext, seed + 0x95), tupleGenerator(MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX, sideEffectFromNumber, seed + 0x101), tupleGenerator(MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX, sideEffectLinkedFromNumber, seed + 0x201), tupleGenerator(MAX_NON_REVERTIBLE_PUBLIC_CALL_STACK_LENGTH_PER_TX, makeCallRequest, seed + 0x501), @@ -373,15 +368,6 @@ export function makeCombinedAccumulatedNonRevertibleData(seed = 1, full = false) ); } -/** - * Creates arbitrary contract data. - * @param seed - The seed to use for generating the contract data. - * @returns A contract data. - */ -export function makeNewContractData(seed = 1): NewContractData { - return new NewContractData(makeAztecAddress(seed), makeEthAddress(seed + 1), fr(seed + 2)); -} - /** * Creates arbitrary aggregation object. * @param seed - The seed to use for generating the aggregation object. @@ -410,7 +396,6 @@ export function makeCallContext(seed = 0, storageContractAddress = makeAztecAddr makeSelector(seed + 3), false, false, - false, 0, ); } @@ -433,6 +418,7 @@ export function makePublicCircuitPublicInputs( fr(seed + 0x100), tupleGenerator(RETURN_VALUES_LENGTH, fr, seed + 0x200), tupleGenerator(MAX_NULLIFIER_READ_REQUESTS_PER_CALL, makeReadRequest, seed + 0x400), + tupleGenerator(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, makeReadRequest, seed + 0x420), tupleGenerator(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, makeContractStorageUpdateRequest, seed + 0x400), tupleGenerator(MAX_PUBLIC_DATA_READS_PER_CALL, makeContractStorageRead, seed + 0x500), tupleGenerator(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, fr, seed + 0x600), @@ -532,7 +518,6 @@ export function makePublicCallRequest(seed = 1): PublicCallRequest { functionSelector: makeSelector(seed + 3), isStaticCall: false, isDelegateCall: false, - isContractDeployment: false, startSideEffectCounter: 0, }); return new PublicCallRequest( @@ -866,7 +851,6 @@ export function makePrivateCircuitPublicInputs(seed = 0): PrivateCircuitPublicIn makeSelector(seed + 4), true, true, - true, 0, ), argsHash: fr(seed + 0x100), @@ -890,27 +874,11 @@ export function makePrivateCircuitPublicInputs(seed = 0): PrivateCircuitPublicIn encryptedLogPreimagesLength: fr(seed + 0xb00), unencryptedLogPreimagesLength: fr(seed + 0xc00), historicalHeader: makeHeader(seed + 0xd00, undefined), - contractDeploymentData: makeContractDeploymentData(seed + 0xe00), chainId: fr(seed + 0x1400), version: fr(seed + 0x1500), }); } -/** - * Makes arbitrary contract deployment data. - * @param seed - The seed to use for generating the contract deployment data. - * @returns A contract deployment data. - */ -export function makeContractDeploymentData(seed = 1) { - return new ContractDeploymentData( - makePoint(seed), - fr(seed + 1), - fr(seed + 2), - fr(seed + 3), - makeEthAddress(seed + 4), - ); -} - /** * Makes global variables. * @param seed - The seed to use for generating the global variables. @@ -1140,7 +1108,6 @@ export function makePartialStateReference(seed = 0): PartialStateReference { makeAppendOnlyTreeSnapshot(seed), makeAppendOnlyTreeSnapshot(seed + 1), makeAppendOnlyTreeSnapshot(seed + 2), - makeAppendOnlyTreeSnapshot(seed + 3), ); } @@ -1197,8 +1164,6 @@ export function makeStateDiffHints(seed = 1): StateDiffHints { const nullifierSubtreeSiblingPath = makeTuple(NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, fr, seed + 0x6000); - const contractSubtreeSiblingPath = makeTuple(CONTRACT_SUBTREE_SIBLING_PATH_LENGTH, fr, seed + 0x7000); - const publicDataSiblingPath = makeTuple(PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, fr, 0x8000); return new StateDiffHints( @@ -1208,7 +1173,6 @@ export function makeStateDiffHints(seed = 1): StateDiffHints { sortedNullifierIndexes, noteHashSubtreeSiblingPath, nullifierSubtreeSiblingPath, - contractSubtreeSiblingPath, publicDataSiblingPath, ); } diff --git a/yarn-project/cli/CHANGELOG.md b/yarn-project/cli/CHANGELOG.md index 21a4fae14ff..280512eeec8 100644 --- a/yarn-project/cli/CHANGELOG.md +++ b/yarn-project/cli/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [0.27.1](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.27.0...aztec-cli-v0.27.1) (2024-03-12) + + +### Miscellaneous + +* **aztec-cli:** Synchronize aztec-packages versions + +## [0.27.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.26.6...aztec-cli-v0.27.0) (2024-03-12) + + +### Miscellaneous + +* Remove old contract deployment flow ([#4970](https://github.com/AztecProtocol/aztec-packages/issues/4970)) ([6d15947](https://github.com/AztecProtocol/aztec-packages/commit/6d1594736e96cd744ea691a239fcd3a46bdade60)) + ## [0.26.6](https://github.com/AztecProtocol/aztec-packages/compare/aztec-cli-v0.26.5...aztec-cli-v0.26.6) (2024-03-08) diff --git a/yarn-project/cli/package.json b/yarn-project/cli/package.json index f786232ddb8..839b849f0e7 100644 --- a/yarn-project/cli/package.json +++ b/yarn-project/cli/package.json @@ -1,6 +1,6 @@ { "name": "@aztec/cli", - "version": "0.26.6", + "version": "0.27.1", "type": "module", "main": "./dest/index.js", "bin": { diff --git a/yarn-project/cli/src/cmds/deploy_l1_contracts.ts b/yarn-project/cli/src/cmds/deploy_l1_contracts.ts index 86e6cea47bb..a7a5af57fe1 100644 --- a/yarn-project/cli/src/cmds/deploy_l1_contracts.ts +++ b/yarn-project/cli/src/cmds/deploy_l1_contracts.ts @@ -17,7 +17,6 @@ export async function deployL1Contracts( log(`Registry Address: ${l1ContractAddresses.registryAddress.toString()}`); log(`L1 -> L2 Inbox Address: ${l1ContractAddresses.inboxAddress.toString()}`); log(`L2 -> L1 Outbox address: ${l1ContractAddresses.outboxAddress.toString()}`); - log(`Contract Deployment Emitter Address: ${l1ContractAddresses.contractDeploymentEmitterAddress.toString()}`); log(`Availability Oracle Address: ${l1ContractAddresses.availabilityOracleAddress.toString()}`); log('\n'); } diff --git a/yarn-project/cli/src/utils.ts b/yarn-project/cli/src/utils.ts index 300a0d55a9b..281a8fd297b 100644 --- a/yarn-project/cli/src/utils.ts +++ b/yarn-project/cli/src/utils.ts @@ -48,8 +48,6 @@ export async function deployAztecContracts( debugLogger: DebugLogger, ) { const { - ContractDeploymentEmitterAbi, - ContractDeploymentEmitterBytecode, InboxAbi, InboxBytecode, OutboxAbi, @@ -67,10 +65,6 @@ export async function deployAztecContracts( : privateKeyToAccount(`${privateKey.startsWith('0x') ? '' : '0x'}${privateKey}` as `0x${string}`); const chain = createEthereumChain(rpcUrl, apiKey); const l1Artifacts: L1ContractArtifactsForDeployment = { - contractDeploymentEmitter: { - contractAbi: ContractDeploymentEmitterAbi, - contractBytecode: ContractDeploymentEmitterBytecode, - }, registry: { contractAbi: RegistryAbi, contractBytecode: RegistryBytecode, diff --git a/yarn-project/end-to-end/scripts/docker-compose-anvil.yml b/yarn-project/end-to-end/scripts/docker-compose-anvil.yml index 5e69fbea59d..509949d0f71 100644 --- a/yarn-project/end-to-end/scripts/docker-compose-anvil.yml +++ b/yarn-project/end-to-end/scripts/docker-compose-anvil.yml @@ -1,7 +1,7 @@ version: '3' services: fork: - image: ghcr.io/foundry-rs/foundry:nightly-a44aa13cfc23491ba32aaedc093e9488c1a6db43 + image: ghcr.io/foundry-rs/foundry:nightly-de33b6af53005037b463318d2628b5cfcaf39916 entrypoint: 'anvil -p 8545 --host 0.0.0.0 --chain-id 31337' ports: - '8545:8545' diff --git a/yarn-project/end-to-end/scripts/docker-compose-no-sandbox.yml b/yarn-project/end-to-end/scripts/docker-compose-no-sandbox.yml index e810a57db3d..db646499b49 100644 --- a/yarn-project/end-to-end/scripts/docker-compose-no-sandbox.yml +++ b/yarn-project/end-to-end/scripts/docker-compose-no-sandbox.yml @@ -1,7 +1,7 @@ version: '3' services: fork: - image: ghcr.io/foundry-rs/foundry:nightly-a44aa13cfc23491ba32aaedc093e9488c1a6db43 + image: ghcr.io/foundry-rs/foundry:nightly-de33b6af53005037b463318d2628b5cfcaf39916 entrypoint: > sh -c ' if [ -n "$FORK_BLOCK_NUMBER" ] && [ -n "$FORK_URL" ]; then diff --git a/yarn-project/end-to-end/scripts/docker-compose-p2p.yml b/yarn-project/end-to-end/scripts/docker-compose-p2p.yml index 50cca540d6c..f61b7bd3d8f 100644 --- a/yarn-project/end-to-end/scripts/docker-compose-p2p.yml +++ b/yarn-project/end-to-end/scripts/docker-compose-p2p.yml @@ -1,7 +1,7 @@ version: '3' services: fork: - image: ghcr.io/foundry-rs/foundry:nightly-a44aa13cfc23491ba32aaedc093e9488c1a6db43 + image: ghcr.io/foundry-rs/foundry:nightly-de33b6af53005037b463318d2628b5cfcaf39916 entrypoint: 'anvil -p 8545 --host 0.0.0.0 --chain-id 31337' ports: - '8545:8545' diff --git a/yarn-project/end-to-end/scripts/docker-compose.yml b/yarn-project/end-to-end/scripts/docker-compose.yml index 58feb709bc2..0a73d344095 100644 --- a/yarn-project/end-to-end/scripts/docker-compose.yml +++ b/yarn-project/end-to-end/scripts/docker-compose.yml @@ -1,7 +1,7 @@ version: '3' services: fork: - image: ghcr.io/foundry-rs/foundry:nightly-a44aa13cfc23491ba32aaedc093e9488c1a6db43 + image: ghcr.io/foundry-rs/foundry:nightly-de33b6af53005037b463318d2628b5cfcaf39916 entrypoint: > sh -c ' if [ -n "$FORK_BLOCK_NUMBER" ] && [ -n "$FORK_URL" ]; then diff --git a/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts b/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts index c1a355bfc65..0fb56170ce3 100644 --- a/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts +++ b/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts @@ -84,7 +84,7 @@ describe('e2e_dapp_subscription', () => { bananaCoin = await BananaCoin.deploy(aliceWallet, aliceAddress, TOKEN_NAME, TOKEN_SYMBOL, TOKEN_DECIMALS) .send() .deployed(); - bananaFPC = await FPCContract.deploy(aliceWallet, bananaCoin.address, AztecAddress.ZERO).send().deployed(); + bananaFPC = await FPCContract.deploy(aliceWallet, bananaCoin.address, gasTokenContract.address).send().deployed(); counterContract = await CounterContract.deploy(bobWallet, 0, bobAddress).send().deployed(); @@ -95,7 +95,7 @@ describe('e2e_dapp_subscription', () => { // anyone can purchase a subscription for 100 test tokens bananaCoin.address, SUBSCRIPTION_AMOUNT, - AztecAddress.ZERO, + gasTokenContract.address, ) .send() .deployed(); diff --git a/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts b/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts index 4d70a918e9a..2e247bcdf47 100644 --- a/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts @@ -2,14 +2,13 @@ import { AccountWallet, AztecAddress, CompleteAddress, - EthAddress, Fr, INITIAL_L2_BLOCK_NUM, PXE, - Point, getContractInstanceFromDeployParams, } from '@aztec/aztec.js'; -import { NewContractData } from '@aztec/circuits.js'; +import { deployInstance, registerContractClass } from '@aztec/aztec.js/deployment'; +import { StatefulTestContract, StatefulTestContractArtifact } from '@aztec/noir-contracts.js'; import { InclusionProofsContract } from '@aztec/noir-contracts.js/InclusionProofs'; import { jest } from '@jest/globals'; @@ -251,68 +250,42 @@ describe('e2e_inclusion_proofs_contract', () => { }); describe('contract inclusion', () => { - // InclusionProofs contract doesn't have associated public key because it's not an account contract - const publicKey = Point.ZERO; - let contractClassId: Fr; - let initializationHash: Fr; - let portalContractAddress: EthAddress; - - beforeAll(() => { - const contractArtifact = contract.artifact; - const constructorArgs = [publicValue]; - portalContractAddress = EthAddress.random(); - - const instance = getContractInstanceFromDeployParams( - contractArtifact, - constructorArgs, - contractAddressSalt, - publicKey, - portalContractAddress, - ); - - contractClassId = instance.contractClassId; - initializationHash = instance.initializationHash; + const assertInclusion = async ( + address: AztecAddress, + blockNumber: number, + opts: { testDeploy: boolean; testInit: boolean }, + ) => { + const { testDeploy, testInit } = opts; + // Assert contract was publicly deployed or initialized in the block in which it was deployed + await contract.methods.test_contract_inclusion(address, blockNumber, testDeploy, testInit).send().wait(); + + // And prove that it was not before that + const olderBlock = blockNumber - 2; + await contract.methods.test_contract_non_inclusion(address, olderBlock, testDeploy, testInit).send().wait(); + + // Or that the positive call fails when trying to prove in the older block + await expect( + contract.methods.test_contract_inclusion(address, olderBlock, testDeploy, testInit).simulate(), + ).rejects.toThrow(/not found/); + }; + + it('proves public deployment of a contract', async () => { + // Publicly deploy another contract (so we don't test on the same contract) + const initArgs = [accounts[0], 42n]; + const instance = getContractInstanceFromDeployParams(StatefulTestContractArtifact, initArgs); + await (await registerContractClass(wallets[0], StatefulTestContractArtifact)).send().wait(); + const receipt = await deployInstance(wallets[0], instance).send().wait(); + + await assertInclusion(instance.address, receipt.blockNumber!, { testDeploy: true, testInit: false }); }); - it('proves existence of a contract', async () => { - // Choose random block number between first block and current block number to test archival node - const blockNumber = await getRandomBlockNumberSinceDeployment(); - - // Note: We pass in preimage of AztecAddress instead of just AztecAddress in order for the contract to be able to - // test that the contract was deployed with correct constructor parameters. - await contract.methods - .test_contract_inclusion( - publicKey, - contractAddressSalt, - contractClassId, - initializationHash, - portalContractAddress, - blockNumber, - ) - .send() + it('proves initialization of a contract', async () => { + // Initialize (but not deploy) a test contract + const receipt = await StatefulTestContract.deploy(wallets[0], accounts[0], 42n) + .send({ skipClassRegistration: true, skipPublicDeployment: true }) .wait(); - }); - // TODO(@spalladino): Re-enable once we add check for non-inclusion based on nullifier - it.skip('contract existence failure case', async () => { - // This should fail because we choose a block number before the contract was deployed - const blockNumber = deploymentBlockNumber - 1; - const contractData = new NewContractData(contract.address, portalContractAddress, contractClassId); - const leaf = contractData.hash(); - - await expect( - contract.methods - .test_contract_inclusion( - publicKey, - contractAddressSalt, - contractClassId, - initializationHash, - portalContractAddress, - blockNumber, - ) - .send() - .wait(), - ).rejects.toThrow(`Leaf value: ${leaf.toString()} not found in CONTRACT_TREE`); + await assertInclusion(receipt.contract.address, receipt.blockNumber!, { testDeploy: false, testInit: true }); }); }); diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index a18f70cb847..543bd77b48f 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -30,8 +30,6 @@ import { deployInstance, registerContractClass } from '@aztec/aztec.js/deploymen import { AvailabilityOracleAbi, AvailabilityOracleBytecode, - ContractDeploymentEmitterAbi, - ContractDeploymentEmitterBytecode, InboxAbi, InboxBytecode, OutboxAbi, @@ -100,10 +98,6 @@ export const setupL1Contracts = async ( logger: DebugLogger, ) => { const l1Artifacts: L1ContractArtifactsForDeployment = { - contractDeploymentEmitter: { - contractAbi: ContractDeploymentEmitterAbi, - contractBytecode: ContractDeploymentEmitterBytecode, - }, registry: { contractAbi: RegistryAbi, contractBytecode: RegistryBytecode, diff --git a/yarn-project/end-to-end/src/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/integration_l1_publisher.test.ts index 1de3ff621d0..994f829115f 100644 --- a/yarn-project/end-to-end/src/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/integration_l1_publisher.test.ts @@ -23,13 +23,7 @@ import { PublicKernelCircuitPublicInputs, SideEffectLinkedToNoteHash, } from '@aztec/circuits.js'; -import { - fr, - makeNewContractData, - makeNewSideEffect, - makeNewSideEffectLinkedToNoteHash, - makeProof, -} from '@aztec/circuits.js/testing'; +import { fr, makeNewSideEffect, makeNewSideEffectLinkedToNoteHash, makeProof } from '@aztec/circuits.js/testing'; import { createEthereumChain } from '@aztec/ethereum'; import { makeTuple, range } from '@aztec/foundation/array'; import { openTmpStore } from '@aztec/kv-store/utils'; @@ -103,7 +97,7 @@ describe('L1Publisher integration', () => { let feeRecipient: AztecAddress; // To overwrite the test data, set this to true and run the tests. - const OVERWRITE_TEST_DATA = false; + const OVERWRITE_TEST_DATA = !!process.env.OVERWRITE_TEST_DATA; beforeEach(async () => { deployerAccount = privateKeyToAccount(deployerPK); @@ -186,7 +180,6 @@ describe('L1Publisher integration', () => { processedTx.data.end.newNullifiers[processedTx.data.end.newNullifiers.length - 1] = SideEffectLinkedToNoteHash.empty(); processedTx.data.end.newL2ToL1Msgs = makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x300); - processedTx.data.end.newContracts = [makeNewContractData(seed + 0x1000)]; processedTx.data.end.encryptedLogsHash = to2Fields(processedTx.encryptedLogs.hash()); processedTx.data.end.unencryptedLogsHash = to2Fields(processedTx.unencryptedLogs.hash()); @@ -293,10 +286,6 @@ describe('L1Publisher integration', () => { root: `0x${block.header.state.l1ToL2MessageTree.root.toBuffer().toString('hex').padStart(64, '0')}`, }, partialStateReference: { - contractTree: { - nextAvailableLeafIndex: block.header.state.partial.contractTree.nextAvailableLeafIndex, - root: `0x${block.header.state.partial.contractTree.root.toBuffer().toString('hex').padStart(64, '0')}`, - }, noteHashTree: { nextAvailableLeafIndex: block.header.state.partial.noteHashTree.nextAvailableLeafIndex, root: `0x${block.header.state.partial.noteHashTree.root.toBuffer().toString('hex').padStart(64, '0')}`, diff --git a/yarn-project/ethereum/src/deploy_l1_contracts.ts b/yarn-project/ethereum/src/deploy_l1_contracts.ts index 3ba6f1c2e29..3d05513b621 100644 --- a/yarn-project/ethereum/src/deploy_l1_contracts.ts +++ b/yarn-project/ethereum/src/deploy_l1_contracts.ts @@ -56,10 +56,6 @@ export interface ContractArtifacts { * All L1 Contract Artifacts for deployment */ export interface L1ContractArtifactsForDeployment { - /** - * Contract deployment emitter artifacts - */ - contractDeploymentEmitter: ContractArtifacts; /** * Inbox contract artifacts */ @@ -164,21 +160,12 @@ export const deployL1Contracts = async ( { account }, ); - const contractDeploymentEmitterAddress = await deployL1Contract( - walletClient, - publicClient, - contractsToDeploy.contractDeploymentEmitter.contractAbi, - contractsToDeploy.contractDeploymentEmitter.contractBytecode, - ); - logger(`Deployed contract deployment emitter at ${contractDeploymentEmitterAddress}`); - const l1Contracts: L1ContractAddresses = { availabilityOracleAddress, rollupAddress, registryAddress, inboxAddress, outboxAddress, - contractDeploymentEmitterAddress, }; return { diff --git a/yarn-project/ethereum/src/l1_contract_addresses.ts b/yarn-project/ethereum/src/l1_contract_addresses.ts index 147b2ced618..be1c3af72fc 100644 --- a/yarn-project/ethereum/src/l1_contract_addresses.ts +++ b/yarn-project/ethereum/src/l1_contract_addresses.ts @@ -6,8 +6,7 @@ export const l1ContractsNames = [ 'registryAddress', 'inboxAddress', 'outboxAddress', - 'contractDeploymentEmitterAddress', -]; +] as const; /** * Provides the directory of current L1 contract addresses diff --git a/yarn-project/foundation/src/abi/__snapshots__/function_selector.test.ts.snap b/yarn-project/foundation/src/abi/__snapshots__/function_selector.test.ts.snap index b80d8292ad3..0336e9c4e93 100644 --- a/yarn-project/foundation/src/abi/__snapshots__/function_selector.test.ts.snap +++ b/yarn-project/foundation/src/abi/__snapshots__/function_selector.test.ts.snap @@ -1,7 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`FunctionSelector computes a function selector from signature 1`] = ` -FunctionSelector { - "value": 2835717307, -} -`; +exports[`FunctionSelector computes a function selector from signature 1`] = `Selector<0xa9059cbb>`; diff --git a/yarn-project/foundation/src/abi/function_selector.test.ts b/yarn-project/foundation/src/abi/function_selector.test.ts index 0fae5417ef6..6cb6155e922 100644 --- a/yarn-project/foundation/src/abi/function_selector.test.ts +++ b/yarn-project/foundation/src/abi/function_selector.test.ts @@ -1,9 +1,11 @@ +import { setupCustomSnapshotSerializers } from '../testing/index.js'; import { FunctionSelector } from './function_selector.js'; describe('FunctionSelector', () => { let selector: FunctionSelector; beforeAll(() => { + setupCustomSnapshotSerializers(expect); selector = FunctionSelector.random(); }); diff --git a/yarn-project/foundation/src/crypto/pedersen/__snapshots__/index.test.ts.snap b/yarn-project/foundation/src/crypto/pedersen/__snapshots__/index.test.ts.snap index b650a488bcb..b8842b33c77 100644 --- a/yarn-project/foundation/src/crypto/pedersen/__snapshots__/index.test.ts.snap +++ b/yarn-project/foundation/src/crypto/pedersen/__snapshots__/index.test.ts.snap @@ -1,41 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`pedersen pedersen hash buffer 1`] = ` -{ - "data": [ - 43, - 213, - 196, - 82, - 160, - 201, - 113, - 98, - 41, - 79, - 201, - 223, - 208, - 241, - 224, - 157, - 14, - 9, - 201, - 95, - 165, - 237, - 63, - 241, - 73, - 251, - 222, - 243, - 102, - 203, - 81, - 249, - ], - "type": "Buffer", -} -`; +exports[`pedersen pedersen hash buffer 1`] = `Buffer<0x2bd5c452a0c97162294fc9dfd0f1e09d0e09c95fa5ed3ff149fbdef366cb51f9>`; diff --git a/yarn-project/foundation/src/crypto/pedersen/index.test.ts b/yarn-project/foundation/src/crypto/pedersen/index.test.ts index 298c81d1859..0e9e1c1c92a 100644 --- a/yarn-project/foundation/src/crypto/pedersen/index.test.ts +++ b/yarn-project/foundation/src/crypto/pedersen/index.test.ts @@ -1,10 +1,12 @@ import { BarretenbergSync } from '@aztec/bb.js'; import { toBufferBE } from '../../bigint-buffer/index.js'; +import { setupCustomSnapshotSerializers } from '../../testing/index.js'; import { pedersenCommit, pedersenHash, pedersenHashBuffer } from './index.js'; describe('pedersen', () => { beforeAll(async () => { + setupCustomSnapshotSerializers(expect); await BarretenbergSync.initSingleton(); }); diff --git a/yarn-project/foundation/src/json-rpc/server/json_rpc_server.ts b/yarn-project/foundation/src/json-rpc/server/json_rpc_server.ts index 08e0533aff4..bd2d537bc54 100644 --- a/yarn-project/foundation/src/json-rpc/server/json_rpc_server.ts +++ b/yarn-project/foundation/src/json-rpc/server/json_rpc_server.ts @@ -73,7 +73,7 @@ export class JsonRpcServer { app.use(compress({ br: false } as any)); app.use( bodyParser({ - jsonLimit: '10mb', + jsonLimit: '50mb', enableTypes: ['json'], detectJSON: () => true, }), diff --git a/yarn-project/foundation/src/testing/index.ts b/yarn-project/foundation/src/testing/index.ts index 40be26eb4ef..e7616a77c78 100644 --- a/yarn-project/foundation/src/testing/index.ts +++ b/yarn-project/foundation/src/testing/index.ts @@ -1 +1,2 @@ export * from './test_data.js'; +export * from './snapshot_serializer.js'; diff --git a/yarn-project/foundation/src/testing/snapshot_serializer.ts b/yarn-project/foundation/src/testing/snapshot_serializer.ts new file mode 100644 index 00000000000..7ccb1aa826b --- /dev/null +++ b/yarn-project/foundation/src/testing/snapshot_serializer.ts @@ -0,0 +1,33 @@ +import { type NewPlugin } from 'pretty-format'; +import { inspect } from 'util'; + +function makeSerializerForCustomInspect(prefix: string): NewPlugin { + return { + serialize(val: any): string { + return inspect(val); + }, + + test(arg: any): boolean { + return inspect(arg).startsWith(prefix); + }, + }; +} + +const bufferSerializer: NewPlugin = { + serialize(val: any): string { + return `Buffer<0x${val.toString('hex')}>`; + }, + + test(arg: any): boolean { + return Buffer.isBuffer(arg); + }, +}; + +const CUSTOM_INSPECT_SERIALIZABLE_TYPES = ['AztecAddress', 'Fr', 'Fq', 'Selector', 'EthAddress']; + +export function setupCustomSnapshotSerializers(expect: { addSnapshotSerializer: (serializer: NewPlugin) => void }) { + for (const type of CUSTOM_INSPECT_SERIALIZABLE_TYPES) { + expect.addSnapshotSerializer(makeSerializerForCustomInspect(type)); + } + expect.addSnapshotSerializer(bufferSerializer); +} diff --git a/yarn-project/foundation/src/testing/test_data.ts b/yarn-project/foundation/src/testing/test_data.ts index 976701e3489..241ae5eead9 100644 --- a/yarn-project/foundation/src/testing/test_data.ts +++ b/yarn-project/foundation/src/testing/test_data.ts @@ -1,3 +1,9 @@ +import { existsSync, readFileSync, writeFileSync } from 'fs'; +import { dirname, join, resolve } from 'path'; + +import { createConsoleLogger } from '../log/console.js'; +import { fileURLToPath } from '../url/index.js'; + const testData: { [key: string]: { toBuffer(): Buffer }[] } = {}; /** Returns whether test data generation is enabled */ @@ -34,3 +40,31 @@ export function getTestData(itemName: string): { toBuffer(): Buffer }[] { const fullItemName = `${testName} ${itemName}`; return testData[fullItemName]; } + +/** + * Looks for a variable assignment in the target file and updates the value, only if test data generation is enabled. + * Note that a magic inline comment would be a cleaner approach, like `/* TEST-DATA-START *\/` and `/* TEST-DATA-END *\/`, + * but running nargo fmt on it panics since the comment would be erased, so we roll with this for now. + * @remarks Requires AZTEC_GENERATE_TEST_DATA=1 to be set + */ +export function updateInlineTestData(targetFileFromRepoRoot: string, itemName: string, value: string) { + if (!isGenerateTestDataEnabled()) { + return; + } + const logger = createConsoleLogger('aztec:testing:test_data'); + const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../../../../'); + if (!existsSync(join(repoRoot, 'CODEOWNERS'))) { + throw new Error(`Path to repo root is incorrect (got ${repoRoot})`); + } + + const targetFile = join(repoRoot, targetFileFromRepoRoot); + const contents = readFileSync(targetFile, 'utf8').toString(); + const regex = new RegExp(`let ${itemName} = .*;`, 'g'); + if (!regex.exec(contents)) { + throw new Error(`Test data marker for ${itemName} not found in ${targetFile}`); + } + + const updatedContents = contents.replaceAll(regex, `let ${itemName} = ${value};`); + writeFileSync(targetFile, updatedContents); + logger(`Updated test data in ${targetFile} for ${itemName} to ${value}`); +} diff --git a/yarn-project/foundation/src/trees/index.ts b/yarn-project/foundation/src/trees/index.ts index 195877aec3e..60b025a9e13 100644 --- a/yarn-project/foundation/src/trees/index.ts +++ b/yarn-project/foundation/src/trees/index.ts @@ -23,22 +23,13 @@ export interface IndexedTreeLeaf { } /** - * Preimage of an indexed merkle tree leaf. + * Preimage of a merkle tree leaf. */ -export interface IndexedTreeLeafPreimage { +export interface TreeLeafPreimage { /** * Returns key of the leaf corresponding to this preimage. */ getKey(): bigint; - /** - * Returns the key of the next leaf. - */ - getNextKey(): bigint; - /** - * Returns the index of the next leaf. - */ - getNextIndex(): bigint; - /** * Returns the preimage as a leaf. */ @@ -52,3 +43,14 @@ export interface IndexedTreeLeafPreimage { */ toHashInputs(): Buffer[]; } + +/** + * Preimage of an indexed merkle tree leaf. + */ +export interface IndexedTreeLeafPreimage extends TreeLeafPreimage { + getNextKey(): bigint; + /** + * Returns the index of the next leaf. + */ + getNextIndex(): bigint; +} diff --git a/yarn-project/l1-artifacts/scripts/generate-artifacts.sh b/yarn-project/l1-artifacts/scripts/generate-artifacts.sh index 9c39b9526d1..83e239bf1f8 100755 --- a/yarn-project/l1-artifacts/scripts/generate-artifacts.sh +++ b/yarn-project/l1-artifacts/scripts/generate-artifacts.sh @@ -16,7 +16,6 @@ CONTRACTS=( "l1-contracts:NewInbox" "l1-contracts:Outbox" "l1-contracts:Rollup" - "l1-contracts:ContractDeploymentEmitter" "l1-contracts:TokenPortal" "l1-contracts:PortalERC20" "l1-contracts:UniswapPortal" diff --git a/yarn-project/noir-compiler/src/__snapshots__/index.test.ts.snap b/yarn-project/noir-compiler/src/__snapshots__/index.test.ts.snap deleted file mode 100644 index 5cbc1a00bb4..00000000000 --- a/yarn-project/noir-compiler/src/__snapshots__/index.test.ts.snap +++ /dev/null @@ -1,397 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`noir-compiler using nargo compiles the test contract 1`] = ` -[ - { - "aztecNrVersion": undefined, - "events": [], - "functions": [ - { - "bytecode": "H4sIAAAAAAAA/62QQQ6EMAwDQ7eHfU7SJDS57Ve2ovz/BQgQrVTOYCmyfbGiiQAQ4NJ03Ld571vLH7ir919zfCaaXtwKwxbjLFJzqsT0x+TFFEXLbGSkpksy5mpi2YtndBKutKrz2sbie3/hyLXnMPA/mcaB8Q4eX+1anAEAAA==", - "functionType": "secret", - "isInternal": false, - "name": "constructor", - "parameters": [ - { - "name": "pub_param", - "type": { - "kind": "field", - }, - "visibility": "public", - }, - ], - "returnTypes": [], - "verificationKey": "0000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f", - }, - { - "bytecode": "H4sIAAAAAAAA/61QwQ2AQAxqa+5MP86iTuAq7r+EGkmO8L3ygfQBBTcztx+LDbjohO50v8D7JDrlVXm216PBK+nnAG/oEqW55520Y1B+yMarbFxZ/lBfF/7wACd6RJX5AQAA", - "functionType": "open", - "isInternal": false, - "name": "openFunction", - "parameters": [], - "returnTypes": [ - { - "kind": "field", - }, - ], - "verificationKey": "0000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f", - }, - ], - "name": "TestContract", - }, -] -`; - -exports[`noir-compiler using nargo generates Aztec.nr external interface 1`] = ` -"/* Autogenerated file, do not edit! */ - -use dep::std; -use dep::aztec::context::{ PrivateContext, PublicContext }; -use dep::protocol_types::{ - address::AztecAddress, - abis::function_selector::FunctionSelector, - constants::RETURN_VALUES_LENGTH, -}; - - - -// Interface for calling TestContract functions from a private context -struct TestContractPrivateContextInterface { - address: AztecAddress, -} - -impl TestContractPrivateContextInterface { - pub fn at(address: AztecAddress) -> Self { - Self { - address, - } - } - - pub fn openFunction( - self, - context: &mut PrivateContext - ) { - let mut serialized_args = [0; 0]; - - context.call_public_function(self.address, FunctionSelector::from_field(0x46be982e), serialized_args) - } - -} - - - - -// Interface for calling TestContract functions from a public context -struct TestContractPublicContextInterface { - address: AztecAddress, -} - -impl TestContractPublicContextInterface { - pub fn at(address: AztecAddress) -> Self { - Self { - address, - } - } - - pub fn openFunction( - self, - context: PublicContext - ) -> [Field; RETURN_VALUES_LENGTH] { - let mut serialized_args = [0; 0]; - - context.call_public_function(self.address, FunctionSelector::from_field(0x46be982e), serialized_args) - } - -} - - -" -`; - -exports[`noir-compiler using nargo generates typescript interface 1`] = ` -" -/* Autogenerated file, do not edit! */ - -/* eslint-disable */ -import { - AztecAddress, - AztecAddressLike, - CompleteAddress, - Contract, - ContractArtifact, - ContractBase, - ContractFunctionInteraction, - ContractMethod, - DeployMethod, - EthAddress, - EthAddressLike, - FieldLike, - Fr, - FunctionSelectorLike, - Point, - PublicKey, - Wallet, -} from '@aztec/aztec.js'; -import TestContractContractArtifactJson from '../target/test.json' assert { type: 'json' }; -export const TestContractContractArtifact = TestContractContractArtifactJson as ContractArtifact; - -/** - * Type-safe interface for contract TestContract; - */ -export class TestContractContract extends ContractBase { - - private constructor( - completeAddress: CompleteAddress, - wallet: Wallet, - portalContract = EthAddress.ZERO - ) { - super(completeAddress, TestContractContractArtifact, wallet, portalContract); - } - - - - /** - * 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, TestContractContract.artifact, wallet) as Promise; - } - - - /** - * Creates a tx to deploy a new instance of this contract. - */ - public static deploy(wallet: Wallet, pub_param: FieldLike) { - return new DeployMethod(Point.ZERO, wallet, TestContractContractArtifact, TestContractContract.at, Array.from(arguments).slice(1)); - } - - /** - * Creates a tx to deploy a new instance of this contract using the specified public key to derive the address. - */ - public static deployWithPublicKey(publicKey: PublicKey, wallet: Wallet, pub_param: FieldLike) { - return new DeployMethod(publicKey, wallet, TestContractContractArtifact, TestContractContract.at, Array.from(arguments).slice(2)); - } - - - - /** - * Returns this contract's artifact. - */ - public static get artifact(): ContractArtifact { - return TestContractContractArtifact; - } - - - /** Type-safe wrappers for the public methods exposed by the contract. */ - public methods!: { - - /** openFunction() */ - openFunction: (() => ContractFunctionInteraction) & Pick; - }; -} -" -`; - -exports[`noir-compiler using wasm binary compiles the test contract 1`] = ` -[ - { - "aztecNrVersion": undefined, - "events": [], - "functions": [ - { - "bytecode": "H4sIAAAAAAAA/62QQQ6EMAwDQ7eHfU7SJDS57Ve2ovz/BQgQrVTOYCmyfbGiiQAQ4NJ03Ld571vLH7ir919zfCaaXtwKwxbjLFJzqsT0x+TFFEXLbGSkpksy5mpi2YtndBKutKrz2sbie3/hyLXnMPA/mcaB8Q4eX+1anAEAAA==", - "functionType": "secret", - "isInternal": false, - "name": "constructor", - "parameters": [ - { - "name": "pub_param", - "type": { - "kind": "field", - }, - "visibility": "public", - }, - ], - "returnTypes": [], - "verificationKey": "0000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f", - }, - { - "bytecode": "H4sIAAAAAAAA/61QwQ2AQAxqa+5MP86iTuAq7r+EGkmO8L3ygfQBBTcztx+LDbjohO50v8D7JDrlVXm216PBK+nnAG/oEqW55520Y1B+yMarbFxZ/lBfF/7wACd6RJX5AQAA", - "functionType": "open", - "isInternal": false, - "name": "openFunction", - "parameters": [], - "returnTypes": [ - { - "kind": "field", - }, - ], - "verificationKey": "0000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f", - }, - ], - "name": "TestContract", - }, -] -`; - -exports[`noir-compiler using wasm binary generates Aztec.nr external interface 1`] = ` -"/* Autogenerated file, do not edit! */ - -use dep::std; -use dep::aztec::context::{ PrivateContext, PublicContext }; -use dep::protocol_types::{ - address::AztecAddress, - abis::function_selector::FunctionSelector, - constants::RETURN_VALUES_LENGTH, -}; - - - -// Interface for calling TestContract functions from a private context -struct TestContractPrivateContextInterface { - address: AztecAddress, -} - -impl TestContractPrivateContextInterface { - pub fn at(address: AztecAddress) -> Self { - Self { - address, - } - } - - pub fn openFunction( - self, - context: &mut PrivateContext - ) { - let mut serialized_args = [0; 0]; - - context.call_public_function(self.address, FunctionSelector::from_field(0x46be982e), serialized_args) - } - -} - - - - -// Interface for calling TestContract functions from a public context -struct TestContractPublicContextInterface { - address: AztecAddress, -} - -impl TestContractPublicContextInterface { - pub fn at(address: AztecAddress) -> Self { - Self { - address, - } - } - - pub fn openFunction( - self, - context: PublicContext - ) -> [Field; RETURN_VALUES_LENGTH] { - let mut serialized_args = [0; 0]; - - context.call_public_function(self.address, FunctionSelector::from_field(0x46be982e), serialized_args) - } - -} - - -" -`; - -exports[`noir-compiler using wasm binary generates typescript interface 1`] = ` -" -/* Autogenerated file, do not edit! */ - -/* eslint-disable */ -import { - AztecAddress, - AztecAddressLike, - CompleteAddress, - Contract, - ContractArtifact, - ContractBase, - ContractFunctionInteraction, - ContractMethod, - DeployMethod, - EthAddress, - EthAddressLike, - FieldLike, - Fr, - FunctionSelectorLike, - Point, - PublicKey, - Wallet, -} from '@aztec/aztec.js'; -import TestContractContractArtifactJson from '../target/test.json' assert { type: 'json' }; -export const TestContractContractArtifact = TestContractContractArtifactJson as ContractArtifact; - -/** - * Type-safe interface for contract TestContract; - */ -export class TestContractContract extends ContractBase { - - private constructor( - completeAddress: CompleteAddress, - wallet: Wallet, - portalContract = EthAddress.ZERO - ) { - super(completeAddress, TestContractContractArtifact, wallet, portalContract); - } - - - - /** - * 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, TestContractContract.artifact, wallet) as Promise; - } - - - /** - * Creates a tx to deploy a new instance of this contract. - */ - public static deploy(wallet: Wallet, pub_param: FieldLike) { - return new DeployMethod(Point.ZERO, wallet, TestContractContractArtifact, TestContractContract.at, Array.from(arguments).slice(1)); - } - - /** - * Creates a tx to deploy a new instance of this contract using the specified public key to derive the address. - */ - public static deployWithPublicKey(publicKey: PublicKey, wallet: Wallet, pub_param: FieldLike) { - return new DeployMethod(publicKey, wallet, TestContractContractArtifact, TestContractContract.at, Array.from(arguments).slice(2)); - } - - - - /** - * Returns this contract's artifact. - */ - public static get artifact(): ContractArtifact { - return TestContractContractArtifact; - } - - - /** Type-safe wrappers for the public methods exposed by the contract. */ - public methods!: { - - /** openFunction() */ - openFunction: (() => ContractFunctionInteraction) & Pick; - }; -} -" -`; diff --git a/yarn-project/noir-protocol-circuits-types/src/__snapshots__/index.test.ts.snap b/yarn-project/noir-protocol-circuits-types/src/__snapshots__/index.test.ts.snap index 4db3b7a346e..85b0acd0aba 100644 --- a/yarn-project/noir-protocol-circuits-types/src/__snapshots__/index.test.ts.snap +++ b/yarn-project/noir-protocol-circuits-types/src/__snapshots__/index.test.ts.snap @@ -5,168 +5,12 @@ PrivateKernelInnerCircuitPublicInputs { "aggregationObject": AggregationObject { "hasData": false, "p0": G1AffineElement { - "x": Fq { - "asBigInt": 1n, - "asBuffer": { - "data": [ - 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, - 1, - ], - "type": "Buffer", - }, - }, - "y": Fq { - "asBigInt": 2n, - "asBuffer": { - "data": [ - 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, - 2, - ], - "type": "Buffer", - }, - }, + "x": Fq<0x0000000000000000000000000000000000000000000000000000000000000001>, + "y": Fq<0x0000000000000000000000000000000000000000000000000000000000000002>, }, "p1": G1AffineElement { - "x": Fq { - "asBigInt": 1n, - "asBuffer": { - "data": [ - 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, - 1, - ], - "type": "Buffer", - }, - }, - "y": Fq { - "asBigInt": 2n, - "asBuffer": { - "data": [ - 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, - 2, - ], - "type": "Buffer", - }, - }, + "x": Fq<0x0000000000000000000000000000000000000000000000000000000000000001>, + "y": Fq<0x0000000000000000000000000000000000000000000000000000000000000002>, }, "proofWitnessIndices": [ 3027, @@ -191,35337 +35,1731 @@ PrivateKernelInnerCircuitPublicInputs { "constants": CombinedConstantData { "historicalHeader": Header { "contentCommitment": ContentCommitment { - "inHash": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - "outHash": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - "txTreeHeight": Fr { - "asBigInt": 1n, - "asBuffer": { - "data": [ - 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, - 1, - ], - "type": "Buffer", - }, - }, - "txsEffectsHash": { - "data": [ - 205, - 51, - 138, - 49, - 148, - 182, - 175, - 72, - 51, - 165, - 57, - 247, - 87, - 9, - 133, - 91, - 204, - 161, - 45, - 52, - 112, - 246, - 255, - 218, - 120, - 164, - 73, - 204, - 71, - 149, - 238, - 103, - ], - "type": "Buffer", - }, + "inHash": Buffer<0x0000000000000000000000000000000000000000000000000000000000000000>, + "outHash": Buffer<0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71>, + "txTreeHeight": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, + "txsEffectsHash": Buffer<0x0cad04c3a06c5f97d6d094af228a4a7b761a1d38df3665978a0d762dc469c942>, }, "globalVariables": { "blockNumber": "0x0000000000000000000000000000000000000000000000000000000000000003", "chainId": "0x0000000000000000000000000000000000000000000000000000000000007a69", "coinbase": "0x0000000000000000000000000000000000000000", "feeRecipient": "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp": "0x0000000000000000000000000000000000000000000000000000000065dfa8d7", + "timestamp": "0x0000000000000000000000000000000000000000000000000000000065eb877a", "version": "0x0000000000000000000000000000000000000000000000000000000000000001", }, "lastArchive": AppendOnlyTreeSnapshot { "nextAvailableLeafIndex": 3, - "root": Fr { - "asBigInt": 5969944478967194141388904584480353988461619538833868682217715714162104866329n, - "asBuffer": { - "data": [ - 13, - 50, - 222, - 107, - 206, - 117, - 42, - 64, - 25, - 77, - 235, - 87, - 127, - 201, - 69, - 103, - 47, - 3, - 182, - 242, - 10, - 163, - 66, - 227, - 65, - 196, - 110, - 214, - 78, - 254, - 22, - 25, - ], - "type": "Buffer", - }, - }, + "root": Fr<0x1030919bf145ee4734f98c79b7afc25bcc6a930e1dc04c72eb5c4b9e09c35d46>, }, "state": StateReference { "l1ToL2MessageTree": AppendOnlyTreeSnapshot { "nextAvailableLeafIndex": 48, - "root": Fr { - "asBigInt": 11033938207523021649122316027295742559227608161317650429835019071130941169536n, - "asBuffer": { - "data": [ - 24, - 100, - 252, - 218, - 168, - 15, - 242, - 113, - 145, - 84, - 250, - 124, - 138, - 144, - 80, - 102, - 41, - 114, - 112, - 113, - 104, - 214, - 158, - 172, - 157, - 182, - 253, - 49, - 16, - 130, - 159, - 128, - ], - "type": "Buffer", - }, - }, + "root": Fr<0x1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80>, }, "partial": PartialStateReference { - "contractTree": AppendOnlyTreeSnapshot { - "nextAvailableLeafIndex": 6, - "root": Fr { - "asBigInt": 19268439499695681738128610275388603494001746813417330117124952063327879457040n, - "asBuffer": { - "data": [ - 42, - 153, - 140, - 223, - 16, - 111, - 52, - 30, - 132, - 96, - 209, - 148, - 219, - 30, - 198, - 76, - 179, - 27, - 201, - 185, - 135, - 11, - 228, - 78, - 176, - 109, - 82, - 169, - 243, - 126, - 105, - 16, - ], - "type": "Buffer", - }, - }, - }, "noteHashTree": AppendOnlyTreeSnapshot { "nextAvailableLeafIndex": 384, - "root": Fr { - "asBigInt": 3465039335176256862253437740363938814226646564972974663280802681105950370836n, - "asBuffer": { - "data": [ - 7, - 169, - 36, - 140, - 36, - 227, - 125, - 251, - 165, - 49, - 229, - 97, - 111, - 182, - 145, - 182, - 159, - 119, - 89, - 72, - 69, - 129, - 104, - 52, - 69, - 216, - 203, - 245, - 159, - 214, - 236, - 20, - ], - "type": "Buffer", - }, - }, + "root": Fr<0x229639c5f9187f3c44fa0eb2e8a64646e29f1268363740671c821e919585c76b>, }, "nullifierTree": AppendOnlyTreeSnapshot { "nextAvailableLeafIndex": 512, - "root": Fr { - "asBigInt": 6067156592360049447774272880746506121082222923352663084907772779978044188583n, - "asBuffer": { - "data": [ - 13, - 105, - 227, - 145, - 126, - 227, - 85, - 20, - 14, - 73, - 114, - 199, - 52, - 112, - 62, - 0, - 195, - 211, - 93, - 55, - 175, - 151, - 106, - 25, - 220, - 183, - 85, - 198, - 131, - 167, - 167, - 167, - ], - "type": "Buffer", - }, - }, + "root": Fr<0x0a17c7e333d7bdd626e86629674447bab07b373ea73dd6458318faea4c25e391>, }, "publicDataTree": AppendOnlyTreeSnapshot { "nextAvailableLeafIndex": 256, - "root": Fr { - "asBigInt": 2464371076137037726517004591164179763520655210409104559778217674715468871211n, - "asBuffer": { - "data": [ - 5, - 114, - 200, - 219, - 136, - 38, - 116, - 221, - 2, - 107, - 136, - 119, - 251, - 186, - 27, - 112, - 10, - 68, - 7, - 218, - 58, - 233, - 206, - 95, - 164, - 50, - 21, - 162, - 129, - 99, - 54, - 43, - ], - "type": "Buffer", - }, - }, + "root": Fr<0x0572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b>, }, }, }, }, "txContext": TxContext { - "chainId": Fr { - "asBigInt": 31337n, - "asBuffer": { - "data": [ - 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, - 122, - 105, - ], - "type": "Buffer", - }, - }, - "contractDeploymentData": ContractDeploymentData { - "contractAddressSalt": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "contractClassId": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "initializationHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "portalContractAddress": EthAddress { - "buffer": { - "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - ], - "type": "Buffer", - }, - }, - "publicKey": Point { - "kind": "point", - "x": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "y": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - }, - "isContractDeploymentTx": false, + "chainId": Fr<0x0000000000000000000000000000000000000000000000000000000000007a69>, "isFeePaymentTx": false, "isRebatePaymentTx": false, - "version": Fr { - "asBigInt": 1n, - "asBuffer": { - "data": [ - 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, - 1, - ], - "type": "Buffer", - }, - }, + "version": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, }, }, "end": CombinedAccumulatedData { - "encryptedLogPreimagesLength": Fr { - "asBigInt": 12n, - "asBuffer": { - "data": [ - 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, - 12, - ], - "type": "Buffer", - }, - }, + "encryptedLogPreimagesLength": Fr<0x000000000000000000000000000000000000000000000000000000000000000c>, "encryptedLogsHash": [ - Fr { - "asBigInt": 10654334908029642268226261618939201427n, - "asBuffer": { - "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8, - 3, - 243, - 68, - 123, - 49, - 16, - 181, - 87, - 150, - 38, - 199, - 134, - 29, - 7, - 147, - ], - "type": "Buffer", - }, - }, - Fr { - "asBigInt": 133338275028334099210129003420909668908n, - "asBuffer": { - "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 100, - 80, - 4, - 133, - 110, - 109, - 121, - 70, - 184, - 235, - 48, - 170, - 28, - 9, - 138, - 44, - ], - "type": "Buffer", - }, - }, - ], - "newContracts": [ - NewContractData { - "contractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "contractClassId": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "portalContractAddress": EthAddress { - "buffer": { - "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - ], - "type": "Buffer", - }, - }, - }, + Fr<0x000000000000000000000000000000000803f3447b3110b5579626c7861d0793>, + Fr<0x00000000000000000000000000000000645004856e6d7946b8eb30aa1c098a2c>, ], "newL2ToL1Msgs": [ - Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, ], "newNoteHashes": [ SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], "newNullifiers": [ SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 7099803906405316731155190465507726995860977202683126152628181404682873070911n, - "asBuffer": { - "data": [ - 15, - 178, - 88, - 187, - 46, - 225, - 186, - 36, - 144, - 217, - 181, - 174, - 143, - 100, - 52, - 185, - 163, - 160, - 198, - 184, - 77, - 45, - 36, - 189, - 149, - 45, - 9, - 128, - 153, - 141, - 229, - 63, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x1c99b3cc8b40ecf8a0467e913a1da927dffdcb1e2e75c3b15b460248c3da9eb6>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], "noteHashReadRequests": [ SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], "nullifierKeyValidationRequests": [ NullifierKeyValidationRequestContext { - "contractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, "publicKey": Point { "kind": "point", - "x": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "y": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "secretKey": Fq { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "x": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "y": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "secretKey": Fq<0x0000000000000000000000000000000000000000000000000000000000000000>, }, NullifierKeyValidationRequestContext { - "contractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, "publicKey": Point { "kind": "point", - "x": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "y": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "secretKey": Fq { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "x": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "y": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "secretKey": Fq<0x0000000000000000000000000000000000000000000000000000000000000000>, }, NullifierKeyValidationRequestContext { - "contractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, "publicKey": Point { "kind": "point", - "x": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "y": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "secretKey": Fq { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "x": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "y": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "secretKey": Fq<0x0000000000000000000000000000000000000000000000000000000000000000>, }, NullifierKeyValidationRequestContext { - "contractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, "publicKey": Point { "kind": "point", - "x": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "y": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "secretKey": Fq { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "x": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "y": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "secretKey": Fq<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], "nullifierReadRequests": [ ReadRequestContext { - "contractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, "counter": 0, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ReadRequestContext { - "contractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, "counter": 0, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ReadRequestContext { - "contractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, "counter": 0, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ReadRequestContext { - "contractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, "counter": 0, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ReadRequestContext { - "contractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, "counter": 0, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ReadRequestContext { - "contractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, "counter": 0, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ReadRequestContext { - "contractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, "counter": 0, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ReadRequestContext { - "contractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "contractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, "counter": 0, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], "privateCallStack": [ CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + CallRequest { + "callerContext": CallerContext { + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + CallRequest { + "callerContext": CallerContext { + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + CallRequest { + "callerContext": CallerContext { + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - CallRequest { - "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], "publicCallStack": [ CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], "publicDataReads": [ PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, PublicDataRead { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], "publicDataUpdateRequests": [ PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, PublicDataUpdateRequest { - "leafSlot": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "newValue": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "leafSlot": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "newValue": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "sideEffectCounter": undefined, }, ], - "unencryptedLogPreimagesLength": Fr { - "asBigInt": 12n, - "asBuffer": { - "data": [ - 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, - 12, - ], - "type": "Buffer", - }, - }, + "unencryptedLogPreimagesLength": Fr<0x000000000000000000000000000000000000000000000000000000000000000c>, "unencryptedLogsHash": [ - Fr { - "asBigInt": 10654334908029642268226261618939201427n, - "asBuffer": { - "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8, - 3, - 243, - 68, - 123, - 49, - 16, - 181, - 87, - 150, - 38, - 199, - 134, - 29, - 7, - 147, - ], - "type": "Buffer", - }, - }, - Fr { - "asBigInt": 133338275028334099210129003420909668908n, - "asBuffer": { - "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 100, - 80, - 4, - 133, - 110, - 109, - 121, - 70, - 184, - 235, - 48, - 170, - 28, - 9, - 138, - 44, - ], - "type": "Buffer", - }, - }, + Fr<0x000000000000000000000000000000000803f3447b3110b5579626c7861d0793>, + Fr<0x00000000000000000000000000000000645004856e6d7946b8eb30aa1c098a2c>, ], }, "isPrivate": true, - "minRevertibleSideEffectCounter": Fr { - "asBigInt": 2n, - "asBuffer": { - "data": [ - 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, - 2, - ], - "type": "Buffer", - }, - }, + "minRevertibleSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000002>, } `; @@ -35530,168 +1768,12 @@ PrivateKernelTailCircuitPublicInputs { "aggregationObject": AggregationObject { "hasData": false, "p0": G1AffineElement { - "x": Fq { - "asBigInt": 1n, - "asBuffer": { - "data": [ - 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, - 1, - ], - "type": "Buffer", - }, - }, - "y": Fq { - "asBigInt": 2n, - "asBuffer": { - "data": [ - 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, - 2, - ], - "type": "Buffer", - }, - }, + "x": Fq<0x0000000000000000000000000000000000000000000000000000000000000001>, + "y": Fq<0x0000000000000000000000000000000000000000000000000000000000000002>, }, "p1": G1AffineElement { - "x": Fq { - "asBigInt": 1n, - "asBuffer": { - "data": [ - 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, - 1, - ], - "type": "Buffer", - }, - }, - "y": Fq { - "asBigInt": 2n, - "asBuffer": { - "data": [ - 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, - 2, - ], - "type": "Buffer", - }, - }, + "x": Fq<0x0000000000000000000000000000000000000000000000000000000000000001>, + "y": Fq<0x0000000000000000000000000000000000000000000000000000000000000002>, }, "proofWitnessIndices": [ 3027, @@ -35716,157 +1798,10 @@ PrivateKernelTailCircuitPublicInputs { "constants": CombinedConstantData { "historicalHeader": Header { "contentCommitment": ContentCommitment { - "inHash": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - "outHash": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - "txTreeHeight": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "txsEffectsHash": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "inHash": Buffer<0x0000000000000000000000000000000000000000000000000000000000000000>, + "outHash": Buffer<0x0000000000000000000000000000000000000000000000000000000000000000>, + "txTreeHeight": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "txsEffectsHash": Buffer<0x0000000000000000000000000000000000000000000000000000000000000000>, }, "globalVariables": { "blockNumber": "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -35878,17997 +1813,801 @@ PrivateKernelTailCircuitPublicInputs { }, "lastArchive": AppendOnlyTreeSnapshot { "nextAvailableLeafIndex": 0, - "root": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "root": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, "state": StateReference { "l1ToL2MessageTree": AppendOnlyTreeSnapshot { "nextAvailableLeafIndex": 0, - "root": Fr { - "asBigInt": 11033938207523021649122316027295742559227608161317650429835019071130941169536n, - "asBuffer": { - "data": [ - 24, - 100, - 252, - 218, - 168, - 15, - 242, - 113, - 145, - 84, - 250, - 124, - 138, - 144, - 80, - 102, - 41, - 114, - 112, - 113, - 104, - 214, - 158, - 172, - 157, - 182, - 253, - 49, - 16, - 130, - 159, - 128, - ], - "type": "Buffer", - }, - }, + "root": Fr<0x1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80>, }, "partial": PartialStateReference { - "contractTree": AppendOnlyTreeSnapshot { - "nextAvailableLeafIndex": 0, - "root": Fr { - "asBigInt": 11033938207523021649122316027295742559227608161317650429835019071130941169536n, - "asBuffer": { - "data": [ - 24, - 100, - 252, - 218, - 168, - 15, - 242, - 113, - 145, - 84, - 250, - 124, - 138, - 144, - 80, - 102, - 41, - 114, - 112, - 113, - 104, - 214, - 158, - 172, - 157, - 182, - 253, - 49, - 16, - 130, - 159, - 128, - ], - "type": "Buffer", - }, - }, - }, "noteHashTree": AppendOnlyTreeSnapshot { "nextAvailableLeafIndex": 0, - "root": Fr { - "asBigInt": 10127882181290008410413105921460858232892226592306749913988016925836213768395n, - "asBuffer": { - "data": [ - 22, - 100, - 45, - 156, - 205, - 131, - 70, - 196, - 3, - 170, - 76, - 63, - 164, - 81, - 23, - 139, - 34, - 83, - 74, - 39, - 3, - 92, - 218, - 166, - 236, - 52, - 174, - 83, - 178, - 156, - 80, - 203, - ], - "type": "Buffer", - }, - }, + "root": Fr<0x16642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb>, }, "nullifierTree": AppendOnlyTreeSnapshot { "nextAvailableLeafIndex": 128, - "root": Fr { - "asBigInt": 5342309968596764527275045470866818007603635181649161546597860399861598581368n, - "asBuffer": { - "data": [ - 11, - 207, - 163, - 233, - 241, - 168, - 146, - 46, - 233, - 44, - 109, - 201, - 100, - 214, - 89, - 89, - 7, - 193, - 128, - 74, - 134, - 117, - 55, - 116, - 50, - 43, - 70, - 143, - 105, - 212, - 242, - 120, - ], - "type": "Buffer", - }, - }, + "root": Fr<0x0bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278>, }, "publicDataTree": AppendOnlyTreeSnapshot { "nextAvailableLeafIndex": 64, - "root": Fr { - "asBigInt": 2464371076137037726517004591164179763520655210409104559778217674715468871211n, - "asBuffer": { - "data": [ - 5, - 114, - 200, - 219, - 136, - 38, - 116, - 221, - 2, - 107, - 136, - 119, - 251, - 186, - 27, - 112, - 10, - 68, - 7, - 218, - 58, - 233, - 206, - 95, - 164, - 50, - 21, - 162, - 129, - 99, - 54, - 43, - ], - "type": "Buffer", - }, - }, + "root": Fr<0x0572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b>, }, }, }, }, "txContext": TxContext { - "chainId": Fr { - "asBigInt": 31337n, - "asBuffer": { - "data": [ - 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, - 122, - 105, - ], - "type": "Buffer", - }, - }, - "contractDeploymentData": ContractDeploymentData { - "contractAddressSalt": Fr { - "asBigInt": 7311030382399597338163861050252213120062382238748931123802938997328081077437n, - "asBuffer": { - "data": [ - 16, - 41, - 229, - 132, - 159, - 98, - 47, - 239, - 16, - 243, - 88, - 76, - 228, - 253, - 225, - 211, - 122, - 230, - 2, - 70, - 67, - 253, - 214, - 192, - 63, - 91, - 30, - 182, - 138, - 120, - 68, - 189, - ], - "type": "Buffer", - }, - }, - "contractClassId": Fr { - "asBigInt": 11261402799649960560055000010277762683410792601251733926790783605870480450198n, - "asBuffer": { - "data": [ - 24, - 229, - 186, - 101, - 76, - 93, - 129, - 216, - 77, - 248, - 70, - 35, - 140, - 108, - 124, - 28, - 165, - 28, - 107, - 182, - 1, - 227, - 79, - 193, - 238, - 229, - 78, - 162, - 188, - 61, - 226, - 150, - ], - "type": "Buffer", - }, - }, - "initializationHash": Fr { - "asBigInt": 3884686677032078163997642338925277146524405337138768470479362501814185729076n, - "asBuffer": { - "data": [ - 8, - 150, - 167, - 157, - 40, - 207, - 1, - 80, - 166, - 109, - 36, - 234, - 213, - 25, - 10, - 104, - 19, - 150, - 27, - 33, - 153, - 252, - 65, - 127, - 75, - 183, - 160, - 143, - 246, - 213, - 156, - 52, - ], - "type": "Buffer", - }, - }, - "portalContractAddress": EthAddress { - "buffer": { - "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - ], - "type": "Buffer", - }, - }, - "publicKey": Point { - "kind": "point", - "x": Fr { - "asBigInt": 10877683337198452447572828431295314307935837383103134363936023229320737992362n, - "asBuffer": { - "data": [ - 24, - 12, - 140, - 243, - 101, - 74, - 89, - 224, - 70, - 151, - 91, - 83, - 159, - 210, - 134, - 195, - 226, - 246, - 219, - 66, - 226, - 180, - 19, - 122, - 58, - 217, - 28, - 91, - 195, - 118, - 46, - 170, - ], - "type": "Buffer", - }, - }, - "y": Fr { - "asBigInt": 3455974765174171425005393027783108758891497964940554641728595773967640820666n, - "asBuffer": { - "data": [ - 7, - 164, - 3, - 44, - 142, - 89, - 0, - 9, - 7, - 207, - 135, - 144, - 192, - 241, - 229, - 102, - 126, - 157, - 252, - 36, - 201, - 140, - 252, - 233, - 203, - 111, - 146, - 176, - 24, - 167, - 251, - 186, - ], - "type": "Buffer", - }, - }, - }, - }, - "isContractDeploymentTx": true, + "chainId": Fr<0x0000000000000000000000000000000000000000000000000000000000007a69>, "isFeePaymentTx": false, "isRebatePaymentTx": false, - "version": Fr { - "asBigInt": 1n, - "asBuffer": { - "data": [ - 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, - 1, - ], - "type": "Buffer", - }, - }, + "version": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, }, }, "end": PrivateAccumulatedRevertibleData { - "encryptedLogPreimagesLength": Fr { - "asBigInt": 280n, - "asBuffer": { - "data": [ - 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, - 24, - ], - "type": "Buffer", - }, - }, + "encryptedLogPreimagesLength": Fr<0x0000000000000000000000000000000000000000000000000000000000000138>, "encryptedLogsHash": [ - Fr { - "asBigInt": 304961715322094719555589373722999098792n, - "asBuffer": { - "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 229, - 109, - 125, - 108, - 232, - 104, - 91, - 8, - 42, - 49, - 179, - 39, - 30, - 123, - 141, - 168, - ], - "type": "Buffer", - }, - }, - Fr { - "asBigInt": 136897649095513224144746737282190647814n, - "asBuffer": { - "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 102, - 253, - 135, - 54, - 53, - 184, - 16, - 83, - 173, - 31, - 167, - 250, - 250, - 195, - 162, - 6, - ], - "type": "Buffer", - }, - }, - ], - "newContracts": [ - NewContractData { - "contractAddress": AztecAddress { - "asBigInt": 21544707939378960316433445764943485561122552040387269174561235639352922598468n, - "asBuffer": { - "data": [ - 47, - 161, - 223, - 96, - 8, - 251, - 94, - 166, - 209, - 190, - 16, - 33, - 8, - 72, - 169, - 219, - 48, - 139, - 28, - 212, - 243, - 51, - 57, - 80, - 175, - 115, - 0, - 252, - 61, - 241, - 236, - 68, - ], - "type": "Buffer", - }, - }, - "contractClassId": Fr { - "asBigInt": 11261402799649960560055000010277762683410792601251733926790783605870480450198n, - "asBuffer": { - "data": [ - 24, - 229, - 186, - 101, - 76, - 93, - 129, - 216, - 77, - 248, - 70, - 35, - 140, - 108, - 124, - 28, - 165, - 28, - 107, - 182, - 1, - 227, - 79, - 193, - 238, - 229, - 78, - 162, - 188, - 61, - 226, - 150, - ], - "type": "Buffer", - }, - }, - "portalContractAddress": EthAddress { - "buffer": { - "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - ], - "type": "Buffer", - }, - }, - }, + Fr<0x0000000000000000000000000000000061f5a418c428fb1975c2e8b76f482ebf>, + Fr<0x0000000000000000000000000000000072ccf265f6aeee4d2c8891ff291e2bd6>, ], "newL2ToL1Msgs": [ - Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, ], "newNoteHashes": [ SideEffect { - "counter": Fr { - "asBigInt": 3n, - "asBuffer": { - "data": [ - 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, - 3, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 4921006138425954289239931824112847627978176763443183116545252407591448418403n, - "asBuffer": { - "data": [ - 10, - 225, - 48, - 214, - 92, - 185, - 53, - 99, - 229, - 40, - 149, - 153, - 67, - 71, - 49, - 184, - 167, - 148, - 80, - 179, - 169, - 139, - 51, - 211, - 113, - 50, - 103, - 110, - 134, - 73, - 24, - 99, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000002>, + "value": Fr<0x072c4b0da6f03ff188d150944f5454ad2bdcf33165792b512c1a96fa228ef942>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], "newNullifiers": [ SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 2n, - "asBuffer": { - "data": [ - 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, - 2, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 2235505794528283094820486688568040133162370705176549719754391397044877345626n, - "asBuffer": { - "data": [ - 4, - 241, - 64, - 94, - 109, - 251, - 93, - 153, - 47, - 243, - 125, - 4, - 161, - 88, - 143, - 42, - 242, - 216, - 160, - 244, - 156, - 38, - 103, - 194, - 194, - 133, - 84, - 17, - 46, - 245, - 67, - 90, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x103b591beaebdb709340d6ee8cfaf69acc0b785c8173747f2aec03be183fe86f>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000003>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x064dd0ecbabee0ee83581becef6195951cf972f6e68023ed41c14757d55c9e7e>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffectLinkedToNoteHash { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffectLinkedToNoteHash { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], "privateCallStack": [ CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], "publicCallStack": [ CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], - "unencryptedLogPreimagesLength": Fr { - "asBigInt": 4n, - "asBuffer": { - "data": [ - 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, - 4, - ], - "type": "Buffer", - }, - }, + "unencryptedLogPreimagesLength": Fr<0x0000000000000000000000000000000000000000000000000000000000000004>, "unencryptedLogsHash": [ - Fr { - "asBigInt": 38042960891247304977978366569914796636n, - "asBuffer": { - "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28, - 158, - 206, - 201, - 14, - 40, - 210, - 70, - 22, - 80, - 65, - 134, - 53, - 135, - 138, - 92, - ], - "type": "Buffer", - }, - }, - Fr { - "asBigInt": 193925133628253903808777040905688936722n, - "asBuffer": { - "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 145, - 228, - 159, - 71, - 88, - 110, - 207, - 117, - 242, - 176, - 203, - 185, - 78, - 137, - 113, - 18, - ], - "type": "Buffer", - }, - }, + Fr<0x000000000000000000000000000000001c9ecec90e28d2461650418635878a5c>, + Fr<0x0000000000000000000000000000000091e49f47586ecf75f2b0cbb94e897112>, ], }, "endNonRevertibleData": PrivateAccumulatedNonRevertibleData { "newNoteHashes": [ SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffect { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], "newNullifiers": [ SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 2085978395838630903138509509608442216338599373364944549224860426572052415435n, - "asBuffer": { - "data": [ - 4, - 156, - 159, - 54, - 245, - 224, - 135, - 162, - 37, - 138, - 154, - 200, - 13, - 140, - 155, - 224, - 246, - 110, - 195, - 182, - 121, - 63, - 125, - 68, - 36, - 180, - 180, - 162, - 75, - 29, - 195, - 203, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x1ed72effef28948e615c3ddb240c1f8e05d99f72a498152689c7d7313d3d5258>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 1n, - "asBuffer": { - "data": [ - 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, - 1, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 15588520419822240287766178447960259909304026659317837370954464410240843027039n, - "asBuffer": { - "data": [ - 34, - 118, - 202, - 54, - 54, - 149, - 2, - 0, - 139, - 167, - 160, - 185, - 67, - 176, - 242, - 40, - 35, - 12, - 13, - 113, - 205, - 88, - 221, - 174, - 153, - 136, - 33, - 2, - 70, - 104, - 146, - 95, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, SideEffectLinkedToNoteHash { - "counter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "noteHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "value": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], "publicCallStack": [ CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, CallRequest { "callerContext": CallerContext { - "msgSender": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "storageContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - }, - "callerContractAddress": AztecAddress { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "endSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "hash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, - "startSideEffectCounter": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, + "msgSender": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "storageContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, }, + "callerContractAddress": AztecAddress<0x0000000000000000000000000000000000000000000000000000000000000000>, + "endSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "hash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "startSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], }, diff --git a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex index 6f67c2d5fae..6492d3c7b53 100644 --- a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex +++ b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex @@ -1 +1 @@ -2fa1df6008fb5ea6d1be10210848a9db308b1cd4f3333950af7300fc3df1ec44af9f8c440001011124c94143e0599b7c02fbbc7efe5c82b4a9fd4cd42e1c504042e6aad8c2d072000001180c8cf3654a59e046975b539fd286c3e2f6db42e2b4137a3ad91c5bc3762eaa07a4032c8e59000907cf8790c0f1e5667e9dfc24c98cfce9cb6f92b018a7fbba0896a79d28cf0150a66d24ead5190a6813961b2199fc417f4bb7a08ff6d59c3418e5ba654c5d81d84df846238c6c7c1ca51c6bb601e34fc1eee54ea2bc3de2961029e5849f622fef10f3584ce4fde1d37ae6024643fdd6c03f5b1eb68a7844bd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000012fa1df6008fb5ea6d1be10210848a9db308b1cd4f3333950af7300fc3df1ec44af9f8c4400010100000000000000000000000000000000000000000000000000000000000000002fa1df6008fb5ea6d1be10210848a9db308b1cd4f3333950af7300fc3df1ec440000000000000000000000000000000000000000af9f8c44000001000000021124c94143e0599b7c02fbbc7efe5c82b4a9fd4cd42e1c504042e6aad8c2d0720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002ab7c7cbe0c74f1a820cc839e9cfb4211de764e2838d0fe9a2e2276d349f527e000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003579f468b2283611cc4d7adfbb93b8a4815d93ac0b1e1d11dace012cf73c7aa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000002091787b9330916da83946762ff9a8360000000000000000000000000000000014e39cfb57281e6bb0f622f4d24da33300000000000000000000000000000000e3b0c44298fc1c149afbf4c8996fb9240000000000000000000000000000000027ae41e4649b934ca495991b7852b8550000000000000000000000000000000000000000000000000000000000000118000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000801864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b00000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000180c8cf3654a59e046975b539fd286c3e2f6db42e2b4137a3ad91c5bc3762eaa07a4032c8e59000907cf8790c0f1e5667e9dfc24c98cfce9cb6f92b018a7fbba0896a79d28cf0150a66d24ead5190a6813961b2199fc417f4bb7a08ff6d59c3418e5ba654c5d81d84df846238c6c7c1ca51c6bb601e34fc1eee54ea2bc3de2961029e5849f622fef10f3584ce4fde1d37ae6024643fdd6c03f5b1eb68a7844bd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f05d15d0248d5b7b6527f94f0ebf3dcd5cab2c92289d6b24e52c5e32d3afb23881b80304b483b90bc161c8777e275813d54198bdcb91799c205a4259e79a8fc342d542c018dc7396aa42ff0eb4280d5644510d5130c09acb863d9ca58a95f89de205f55504647dd32569dddc7f7c77eae94a46166b96a37120c5c15bc42d0754400000000000000000000000000000000000000000000000000000000000000011d81e3a46dc51e14eefa4573af363bc3075d859d28d9ee73c545eceaf429ccc91fd163e98c3058b28c0c78a7cea427a8d86699c79c4cf9eeeeca2dc63288c0850bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file +16dc92860e90559980ac4a51c162c75bacd7d5c68627ca4f842aae790ad3267caf9f8c440001012ba0471a69c76696ed57b252d4dd871bb33031380b53e8053ad87bc1eb0c500e00000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000116dc92860e90559980ac4a51c162c75bacd7d5c68627ca4f842aae790ad3267caf9f8c44000101000000000000000000000000000000000000000000000000000000000000000016dc92860e90559980ac4a51c162c75bacd7d5c68627ca4f842aae790ad3267c0000000000000000000000000000000000000000af9f8c440000000000012ba0471a69c76696ed57b252d4dd871bb33031380b53e8053ad87bc1eb0c500e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004dbb23d59a9f7374c26afbc5049b1b8b32129f11f5fc4d9daae20d7bc1a745d000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003579f468b2283611cc4d7adfbb93b8a4815d93ac0b1e1d11dace012cf73c7aa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000116dc92860e90559980ac4a51c162c75bacd7d5c68627ca4f842aae790ad3267c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000056ae3b292dde3653fddebd0e2e58e45000000000000000000000000000000000818a8354b5a18267c5dd284c5a48ad900000000000000000000000000000000e3b0c44298fc1c149afbf4c8996fb9240000000000000000000000000000000027ae41e4649b934ca495991b7852b8550000000000000000000000000000000000000000000000000000000000000138000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f1371c1aa479d7cd2801b0f2203b6889a051b10f7c1195df845cc1985c12039b61760928ccb58e1add32fff9de1789f9590f8525a9d3b3489da5ae198e9c3a34d1cab56c2964198a1b67616dd6bee80971cd6c16f1a0acdeabe618a92d81392aa22240ffc780baee02f15e2c96fd74a2f4ea19932966225bc9a4f8598ca6309d400000000000000000000000000000000000000000000000000000000000000022b09ad2b1765e61b2203cd359f9b833c9c611271e5c80df92c35ef522d3731e42706fc59cda1c448173c4a7739dca4fd4325c970e6f035ed9929fd84719533bb0bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex index a15ed703c0c..68498cfeaee 100644 --- a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex +++ b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex @@ -1 +1 @@ -0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be20000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fb258bb2ee1ba2490d9b5ae8f6434b9a3a0c6b84d2d24bd952d0980998de53f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001cd1176371a8a323858dd5afe8d2be97ab088dfeefbf6dbb0679f71f88188dcc28db17e55aa2aee25bb126e1264aec3cf0223257e668c58bc9b1e31ce32329c800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d3735899d9fa7162447ca631f0ba2cd500000000000000000000000000000000eb57d0965a756d78291da33072610eb200000000000000000000000000000000d3735899d9fa7162447ca631f0ba2cd500000000000000000000000000000000eb57d0965a756d78291da33072610eb200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d32de6bce752a40194deb577fc945672f03b6f20aa342e341c46ed64efe1619000000030000000000000000000000000000000000000000000000000000000000000001cd338a3194b6af4833a539f75709855bcca12d3470f6ffda78a449cc4795ee67000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000003007a9248c24e37dfba531e5616fb691b69f7759484581683445d8cbf59fd6ec14000001800d69e3917ee355140e4972c734703e00c3d35d37af976a19dcb755c683a7a7a7000002002a998cdf106f341e8460d194db1ec64cb31bc9b9870be44eb06d52a9f37e6910000000060572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000065dfa8d7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000101000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000002ead99235b90e9c2d13627770d805e8337f639ea69d2c4f769f65bafa9daf6b507694224920d263a002dca02b3746882f8d222a150c28785978f9255c3cceca40b142544847554d75f2546c160023eaeaa60b4d9d6d0c14e37922c7d7853ae211cd0403df7845c5ce5cf0afa77cf73b6a173a6cf3e8bca0c736c5b308624a5bc0906bca100010028db17e55aa2aee25bb126e1264aec3cf0223257e668c58bc9b1e31ce32329c81cd0403df7845c5ce5cf0afa77cf73b6a173a6cf3e8bca0c736c5b308624a5bc00000000000000000000000000000000000000000906bca100000000000003173812cb2d7243dc1f635ed13d44b8e073ca8d9471192fa4b324986ebe9595100000000000000000000000000000000000000000000000000000000000007a6a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000e3b0c44298fc1c149afbf4c8996fb9240000000000000000000000000000000027ae41e4649b934ca495991b7852b85500000000000000000000000000000000e3b0c44298fc1c149afbf4c8996fb9240000000000000000000000000000000027ae41e4649b934ca495991b7852b855000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040d32de6bce752a40194deb577fc945672f03b6f20aa342e341c46ed64efe1619000000030000000000000000000000000000000000000000000000000000000000000001cd338a3194b6af4833a539f75709855bcca12d3470f6ffda78a449cc4795ee67000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000003007a9248c24e37dfba531e5616fb691b69f7759484581683445d8cbf59fd6ec14000001800d69e3917ee355140e4972c734703e00c3d35d37af976a19dcb755c683a7a7a7000002002a998cdf106f341e8460d194db1ec64cb31bc9b9870be44eb06d52a9f37e6910000000060572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000065dfa8d7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f1be487bf00306769c092fff7aa7542f6e2e555b2b8f368355da674b74a34dd291dd9b12727a1e0dfb9e94af2718bd6eaadb7489ca6a5381e43dad39ef1c10f8c27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed2a6f9aaad465e3cb17d121b9e461d332c0b1998bfd59a957ab4c8f3a502ea40a00000000000000000000000000000000000000000000000000000000000000001e53e2a4a2ea07593ada9539cab59e6f37d7a01d7d402c51c3d2eb337a960dec2daefd8c101018a4a3a076131a4d44d9ed900dbe3b3bee5f88d8de8ba4bcb76a1696a166ff19126c9aae06722ae10ebda42f3638167ae5c0597e1a290e3bc7ff06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file +0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be20000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c99b3cc8b40ecf8a0467e913a1da927dffdcb1e2e75c3b15b460248c3da9eb6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002de8ea3cb67cbf05163d48efb6a1768bbd1fcba5a7b360f59c6d6a69b72d7b51065f52c09cf85a10f47ee62f69fb617d521db6331931a1a49401db2b772cd6ec00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d3735899d9fa7162447ca631f0ba2cd500000000000000000000000000000000eb57d0965a756d78291da33072610eb200000000000000000000000000000000d3735899d9fa7162447ca631f0ba2cd500000000000000000000000000000000eb57d0965a756d78291da33072610eb200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001030919bf145ee4734f98c79b7afc25bcc6a930e1dc04c72eb5c4b9e09c35d460000000300000000000000000000000000000000000000000000000000000000000000010cad04c3a06c5f97d6d094af228a4a7b761a1d38df3665978a0d762dc469c9420000000000000000000000000000000000000000000000000000000000000000db56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d711864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f8000000030229639c5f9187f3c44fa0eb2e8a64646e29f1268363740671c821e919585c76b000001800a17c7e333d7bdd626e86629674447bab07b373ea73dd6458318faea4c25e391000002000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000065eb877a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000101000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f0000000029f6c6d02864676c3a735e198bdc062963b5c014299f0924fafb461717a354cd2950ce30c5f8cc743c2303ae0e2243346d9c31a2be86222c580561c4a0b85d4327c5d1425c0b6373e02e74c59332e350bab948f6042193da67960c26463215b212c4c71c3a8f8811738ddaa42174a013c6125ce135b501c0548394eaf92da4ae0906bca1000100065f52c09cf85a10f47ee62f69fb617d521db6331931a1a49401db2b772cd6ec12c4c71c3a8f8811738ddaa42174a013c6125ce135b501c0548394eaf92da4ae00000000000000000000000000000000000000000906bca1000000000003173812cb2d7243dc1f635ed13d44b8e073ca8d9471192fa4b324986ebe9595100000000000000000000000000000000000000000000000000000000000007a6a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000e3b0c44298fc1c149afbf4c8996fb9240000000000000000000000000000000027ae41e4649b934ca495991b7852b85500000000000000000000000000000000e3b0c44298fc1c149afbf4c8996fb9240000000000000000000000000000000027ae41e4649b934ca495991b7852b855000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000041030919bf145ee4734f98c79b7afc25bcc6a930e1dc04c72eb5c4b9e09c35d460000000300000000000000000000000000000000000000000000000000000000000000010cad04c3a06c5f97d6d094af228a4a7b761a1d38df3665978a0d762dc469c9420000000000000000000000000000000000000000000000000000000000000000db56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d711864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f8000000030229639c5f9187f3c44fa0eb2e8a64646e29f1268363740671c821e919585c76b000001800a17c7e333d7bdd626e86629674447bab07b373ea73dd6458318faea4c25e391000002000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000065eb877a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f083bb29cf968271b4ed555fc44929b491efd595175d7796a072873c1aa5407f00108ae65293fa98abe82d32e39bb59ff3c38fb56692e03364d1fb9f76e1d2f7827b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed1c4d584bdd1c82ca3fa7f288682776d2159650f421a3f0c6fc465d9013fc0ff000000000000000000000000000000000000000000000000000000000000000001e53e2a4a2ea07593ada9539cab59e6f37d7a01d7d402c51c3d2eb337a960dec0f88b6aae0852d85238cb5a6714acb2d60d0326c43879b53bd86b20d678d364d269ea59eeea8c4b06aaa8ff5f0f116fc129ec221fa0339888f69490bcecb620a06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex index a1fc053755b..d77d42d73c7 100644 --- a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex +++ b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex @@ -1 +1 @@ -0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be2000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e75d21b5f1f78004ea3c470c4e935dd566aae467f4f7175081cde2e0da87d50000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000049c9f36f5e087a2258a9ac80d8c9be0f66ec3b6793f7d4424b4b4a24b1dc3cb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004f1405e6dfb5d992ff37d04a1588f2af2d8a0f49c2667c2c28554112ef5435a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022276ca36369502008ba7a0b943b0f228230c0d71cd58ddae998821024668925f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e56d7d6ce8685b082a31b3271e7b8da80000000000000000000000000000000066fd873635b81053ad1fa7fafac3a206000000000000000000000000000000001c9ecec90e28d2461650418635878a5c0000000000000000000000000000000091e49f47586ecf75f2b0cbb94e897112000000000000000000000000000000000000000000000000000000000000011800000000000000000000000000000000000000000000000000000000000000042fa1df6008fb5ea6d1be10210848a9db308b1cd4f3333950af7300fc3df1ec44000000000000000000000000000000000000000018e5ba654c5d81d84df846238c6c7c1ca51c6bb601e34fc1eee54ea2bc3de2960000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000801864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b00000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001180c8cf3654a59e046975b539fd286c3e2f6db42e2b4137a3ad91c5bc3762eaa07a4032c8e59000907cf8790c0f1e5667e9dfc24c98cfce9cb6f92b018a7fbba0896a79d28cf0150a66d24ead5190a6813961b2199fc417f4bb7a08ff6d59c3418e5ba654c5d81d84df846238c6c7c1ca51c6bb601e34fc1eee54ea2bc3de2961029e5849f622fef10f3584ce4fde1d37ae6024643fdd6c03f5b1eb68a7844bd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000101000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f0000000013b6f5321c6a82e4bad2481d029eab76cbae772f47b81ef94979734f5fc960402ead05dacacca344f741faf74423ffa51a5c4764d96cb68e3530de6774d42ce1298a146f3b6558ea1be6f42b48d3854581fde967809ab90376742fcad1db6aef04e75d21b5f1f78004ea3c470c4e935dd566aae467f4f7175081cde2e0da87d50000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000049c9f36f5e087a2258a9ac80d8c9be0f66ec3b6793f7d4424b4b4a24b1dc3cb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002276ca36369502008ba7a0b943b0f228230c0d71cd58ddae998821024668925f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104f1405e6dfb5d992ff37d04a1588f2af2d8a0f49c2667c2c28554112ef5435a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000001000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000800000000000000080000000000000008000000000000000800000000000000080000000000000008000000000000000800000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file +0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be20000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000199eaffab9a7ddc1a75f8acf0681fb95d53fe00ff26430f05b0472bbf50ad53700000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ed72effef28948e615c3ddb240c1f8e05d99f72a498152689c7d7313d3d525800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103b591beaebdb709340d6ee8cfaf69acc0b785c8173747f2aec03be183fe86f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001064dd0ecbabee0ee83581becef6195951cf972f6e68023ed41c14757d55c9e7e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061f5a418c428fb1975c2e8b76f482ebf0000000000000000000000000000000072ccf265f6aeee4d2c8891ff291e2bd6000000000000000000000000000000001c9ecec90e28d2461650418635878a5c0000000000000000000000000000000091e49f47586ecf75f2b0cbb94e897112000000000000000000000000000000000000000000000000000000000000013800000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b0000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000101000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f00000000200f9f6318b491e09a817e936f44ff81e6553396538244f5b61bd427d68eec401ba8742d972310ca9efeea5bb67505d7d300e0c6451232af6df21fe058c384f304a2d2e1c35566adba51be66f949ee51a2b8d9c7f6f9ec18e76fe44d087dc62d199eaffab9a7ddc1a75f8acf0681fb95d53fe00ff26430f05b0472bbf50ad5370000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ed72effef28948e615c3ddb240c1f8e05d99f72a498152689c7d7313d3d525800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103b591beaebdb709340d6ee8cfaf69acc0b785c8173747f2aec03be183fe86f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001064dd0ecbabee0ee83581becef6195951cf972f6e68023ed41c14757d55c9e7e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000800000000000000080000000000000008000000000000000800000000000000080000000000000008000000000000000800000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits-types/src/index.test.ts b/yarn-project/noir-protocol-circuits-types/src/index.test.ts index 30d4a9f0449..3e381b6ba00 100644 --- a/yarn-project/noir-protocol-circuits-types/src/index.test.ts +++ b/yarn-project/noir-protocol-circuits-types/src/index.test.ts @@ -1,42 +1,21 @@ -import { - PrivateKernelInitCircuitPrivateInputs, - PrivateKernelInnerCircuitPrivateInputs, - PrivateKernelTailCircuitPrivateInputs, -} from '@aztec/circuits.js'; +import { PrivateKernelInnerCircuitPrivateInputs, PrivateKernelTailCircuitPrivateInputs } from '@aztec/circuits.js'; import { DebugLogger, createDebugLogger } from '@aztec/foundation/log'; +import { setupCustomSnapshotSerializers } from '@aztec/foundation/testing'; import { fileURLToPath } from '@aztec/foundation/url'; import { readFileSync } from 'fs'; import { dirname, resolve } from 'path'; -import { executeInit, executeInner, executeTail } from './index.js'; +import { executeInner, executeTail } from './index.js'; describe('Private kernel', () => { let logger: DebugLogger; beforeAll(() => { + setupCustomSnapshotSerializers(expect); logger = createDebugLogger('noir-private-kernel'); }); - // Taken from e2e_nested_contract => performs nested calls => first init (corresponds to deployment) - // To regenerate fixture data run the following on the yarn-project/e2e folder - // AZTEC_GENERATE_TEST_DATA=1 yarn test e2e_nested_contract -t 'performs nested calls' - // TODO(@spalladino) Re-enable this test - it.skip('Executes private kernel init circuit for a contract deployment', async () => { - logger('Initialized Noir instance with private kernel init circuit'); - - const filepath = resolve(dirname(fileURLToPath(import.meta.url)), './fixtures/nested-call-private-kernel-init.hex'); - const serialized = Buffer.from(readFileSync(filepath).toString(), 'hex'); - const kernelInputs = PrivateKernelInitCircuitPrivateInputs.fromBuffer(serialized); - - // We check that the test data is for a contract deployment - expect(kernelInputs.txRequest.txContext.isContractDeploymentTx).toBe(true); - - const kernelOutputs = await executeInit(kernelInputs); - - expect(kernelOutputs).toMatchSnapshot(); - }); - // Taken from e2e_nested_contract => performs nested calls => last inner // To regenerate fixture data run the following on the yarn-project/e2e folder // AZTEC_GENERATE_TEST_DATA=1 yarn test e2e_nested_contract -t 'performs nested calls' diff --git a/yarn-project/noir-protocol-circuits-types/src/noir_test_gen.test.ts b/yarn-project/noir-protocol-circuits-types/src/noir_test_gen.test.ts index 2f8bad46b4e..0322787c46a 100644 --- a/yarn-project/noir-protocol-circuits-types/src/noir_test_gen.test.ts +++ b/yarn-project/noir-protocol-circuits-types/src/noir_test_gen.test.ts @@ -12,11 +12,14 @@ import { computeSaltedInitializationHash, } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; +import { setupCustomSnapshotSerializers } from '@aztec/foundation/testing'; import { openTmpStore } from '@aztec/kv-store/utils'; import { Pedersen, StandardTree } from '@aztec/merkle-tree'; import { ContractClass, ContractInstance } from '@aztec/types/contracts'; describe('Data generation for noir tests', () => { + setupCustomSnapshotSerializers(expect); + type FixtureContractData = Omit & Pick & Pick & { toString: () => string }; diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.test.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.test.ts index 92285ce4c0f..da506acb62d 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.test.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.test.ts @@ -1,20 +1,9 @@ -import { - AztecAddress, - ContractDeploymentData, - EthAddress, - Fr, - FunctionData, - FunctionSelector, - Point, - TxContext, -} from '@aztec/circuits.js'; +import { AztecAddress, EthAddress, Fr, FunctionData, FunctionSelector, Point } from '@aztec/circuits.js'; import { makeHeader } from '@aztec/circuits.js/testing'; import { mapAztecAddressFromNoir, mapAztecAddressToNoir, - mapContractDeploymentDataFromNoir, - mapContractDeploymentDataToNoir, mapEthAddressFromNoir, mapEthAddressToNoir, mapFieldFromNoir, @@ -27,8 +16,6 @@ import { mapHeaderToNoir, mapPointFromNoir, mapPointToNoir, - mapTxContextFromNoir, - mapTxContextToNoir, } from './type_conversion.js'; describe('Noir<>Circuits.js type conversion test suite', () => { @@ -54,25 +41,6 @@ describe('Noir<>Circuits.js type conversion test suite', () => { expect(mapEthAddressFromNoir(mapEthAddressToNoir(ethAddress))).toEqual(ethAddress); }); - const contractDeploymentData = new ContractDeploymentData( - point, - new Fr(29n), - new Fr(30n), - new Fr(31n), - EthAddress.random(), - ); - - it('should map contract deployment data', () => { - expect(mapContractDeploymentDataFromNoir(mapContractDeploymentDataToNoir(contractDeploymentData))).toEqual( - contractDeploymentData, - ); - }); - - it('should map tx context', () => { - const txContext = new TxContext(false, true, false, contractDeploymentData, new Fr(32n), new Fr(33n)); - expect(mapTxContextFromNoir(mapTxContextToNoir(txContext))).toEqual(txContext); - }); - const functionSelector = new FunctionSelector(34); it('should map function selectors', () => { diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index 10fa0fabdba..fef5e799bb2 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -12,7 +12,6 @@ import { CombinedConstantData, ConstantRollupData, ContentCommitment, - ContractDeploymentData, ContractStorageRead, ContractStorageUpdateRequest, EthAddress, @@ -25,7 +24,6 @@ import { GrumpkinScalar, Header, L2ToL1Message, - MAX_NEW_CONTRACTS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, @@ -36,6 +34,7 @@ import { MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, @@ -50,12 +49,13 @@ import { MergeRollupInputs, NULLIFIER_TREE_HEIGHT, NUM_FIELDS_PER_SHA256, - NewContractData, + NonMembershipHint, NoteHashReadRequestMembershipWitness, NullifierKeyValidationRequest, NullifierKeyValidationRequestContext, NullifierLeafPreimage, - NullifierReadRequestResetHints, + NullifierNonExistentReadRequestHints, + NullifierReadRequestHints, PUBLIC_DATA_TREE_HEIGHT, PartialStateReference, PendingReadHint, @@ -108,15 +108,12 @@ import { CallerContext as CallerContextNoir, CombinedAccumulatedData as CombinedAccumulatedDataNoir, CombinedConstantData as CombinedConstantDataNoir, - ContractDeploymentData as ContractDeploymentDataNoir, FunctionData as FunctionDataNoir, FunctionLeafMembershipWitness as FunctionLeafMembershipWitnessNoir, FunctionSelector as FunctionSelectorNoir, GrumpkinPrivateKey as GrumpkinPrivateKeyNoir, L2ToL1Message as L2ToL1MessageNoir, - NewContractData as NewContractDataNoir, AztecAddress as NoirAztecAddress, - ContractClassId as NoirContractClassId, EthAddress as NoirEthAddress, Field as NoirField, GrumpkinPoint as NoirPoint, @@ -142,7 +139,7 @@ import { PrivateKernelInnerData as PrivateKernelInnerDataNoir, } from './types/private_kernel_inner_types.js'; import { - NullifierReadRequestResetHints as NullifierReadRequestResetHintsNoir, + NullifierReadRequestHints as NullifierReadRequestHintsNoir, NullifierSettledReadHint as NullifierSettledReadHintNoir, PendingReadHint as PendingReadHintNoir, PrivateAccumulatedNonRevertibleData as PrivateAccumulatedNonRevertibleDataNoir, @@ -165,7 +162,11 @@ import { StorageRead as StorageReadNoir, StorageUpdateRequest as StorageUpdateRequestNoir, } from './types/public_kernel_setup_types.js'; -import { PublicKernelTailCircuitPrivateInputs as PublicKernelTailCircuitPrivateInputsNoir } from './types/public_kernel_tail_types.js'; +import { + NullifierNonExistentReadRequestHints as NullifierNonExistentReadRequestHintsNoir, + NullifierNonMembershipHint as NullifierNonMembershipHintNoir, + PublicKernelTailCircuitPrivateInputs as PublicKernelTailCircuitPrivateInputsNoir, +} from './types/public_kernel_tail_types.js'; import { ArchiveRootMembershipWitness as ArchiveRootMembershipWitnessNoir, BaseRollupInputs as BaseRollupInputsNoir, @@ -320,46 +321,6 @@ export function mapEthAddressFromNoir(address: NoirEthAddress): EthAddress { return EthAddress.fromField(mapFieldFromNoir(address.inner)); } -/** Maps a field to a contract class id in Noir. */ -export function mapContractClassIdToNoir(contractClassId: Fr): NoirContractClassId { - return { inner: mapFieldToNoir(contractClassId) }; -} - -/** Maps a noir contract class id to typescript. */ -export function mapContractClassIdFromNoir(contractClassId: NoirContractClassId): Fr { - return mapFieldFromNoir(contractClassId.inner); -} - -/** - * Maps a contract deployment data to a noir contract deployment data. - * @param data - The data. - * @returns The noir contract deployment data. - */ -export function mapContractDeploymentDataToNoir(data: ContractDeploymentData): ContractDeploymentDataNoir { - return { - public_key: mapPointToNoir(data.publicKey), - initialization_hash: mapFieldToNoir(data.initializationHash), - contract_class_id: mapContractClassIdToNoir(data.contractClassId), - contract_address_salt: mapFieldToNoir(data.contractAddressSalt), - portal_contract_address: mapEthAddressToNoir(data.portalContractAddress), - }; -} - -/** - * Maps a noir contract deployment data to a contract deployment data. - * @param data - The noir data. - * @returns The contract deployment data. - */ -export function mapContractDeploymentDataFromNoir(data: ContractDeploymentDataNoir): ContractDeploymentData { - return new ContractDeploymentData( - mapPointFromNoir(data.public_key), - mapFieldFromNoir(data.initialization_hash), - mapContractClassIdFromNoir(data.contract_class_id), - mapFieldFromNoir(data.contract_address_salt), - mapEthAddressFromNoir(data.portal_contract_address), - ); -} - /** * Maps a tx context to a noir tx context. * @param txContext - The tx context. @@ -369,8 +330,6 @@ export function mapTxContextToNoir(txContext: TxContext): TxContextNoir { return { is_fee_payment_tx: txContext.isFeePaymentTx, is_rebate_payment_tx: txContext.isRebatePaymentTx, - is_contract_deployment_tx: txContext.isContractDeploymentTx, - contract_deployment_data: mapContractDeploymentDataToNoir(txContext.contractDeploymentData), chain_id: mapFieldToNoir(txContext.chainId), version: mapFieldToNoir(txContext.version), }; @@ -385,8 +344,6 @@ export function mapTxContextFromNoir(txContext: TxContextNoir): TxContext { return new TxContext( txContext.is_fee_payment_tx, txContext.is_rebate_payment_tx, - txContext.is_contract_deployment_tx, - mapContractDeploymentDataFromNoir(txContext.contract_deployment_data), mapFieldFromNoir(txContext.chain_id), mapFieldFromNoir(txContext.version), ); @@ -467,7 +424,6 @@ export function mapCallContextFromNoir(callContext: CallContextNoir): CallContex mapFunctionSelectorFromNoir(callContext.function_selector), callContext.is_delegate_call, callContext.is_static_call, - callContext.is_contract_deployment, mapNumberFromNoir(callContext.start_side_effect_counter), ); } @@ -485,7 +441,6 @@ export function mapCallContextToNoir(callContext: CallContext): CallContextNoir function_selector: mapFunctionSelectorToNoir(callContext.functionSelector), is_delegate_call: callContext.isDelegateCall, is_static_call: callContext.isStaticCall, - is_contract_deployment: callContext.isContractDeployment, start_side_effect_counter: mapNumberToNoir(callContext.startSideEffectCounter), }; } @@ -741,7 +696,6 @@ export function mapPrivateCircuitPublicInputsToNoir( encrypted_log_preimages_length: mapFieldToNoir(privateCircuitPublicInputs.encryptedLogPreimagesLength), unencrypted_log_preimages_length: mapFieldToNoir(privateCircuitPublicInputs.unencryptedLogPreimagesLength), historical_header: mapHeaderToNoir(privateCircuitPublicInputs.historicalHeader), - contract_deployment_data: mapContractDeploymentDataToNoir(privateCircuitPublicInputs.contractDeploymentData), chain_id: mapFieldToNoir(privateCircuitPublicInputs.chainId), version: mapFieldToNoir(privateCircuitPublicInputs.version), min_revertible_side_effect_counter: mapFieldToNoir(privateCircuitPublicInputs.minRevertibleSideEffectCounter), @@ -856,32 +810,6 @@ export function mapSha256HashToNoir(hash: Buffer): FixedLengthArray { return to2Fields(hash).map(mapFieldToNoir) as FixedLengthArray; } -/** - * Maps new contract data from noir to the parsed type. - * @param newContractData - The noir new contract data. - * @returns The parsed new contract data. - */ -export function mapNewContractDataFromNoir(newContractData: NewContractDataNoir): NewContractData { - return new NewContractData( - mapAztecAddressFromNoir(newContractData.contract_address), - mapEthAddressFromNoir(newContractData.portal_contract_address), - mapContractClassIdFromNoir(newContractData.contract_class_id), - ); -} - -/** - * Maps new contract data to noir new contract data. - * @param newContractData - The new contract data. - * @returns The noir new contract data. - */ -export function mapNewContractDataToNoir(newContractData: NewContractData): NewContractDataNoir { - return { - contract_address: mapAztecAddressToNoir(newContractData.contractAddress), - portal_contract_address: mapEthAddressToNoir(newContractData.portalContractAddress), - contract_class_id: mapContractClassIdToNoir(newContractData.contractClassId), - }; -} - /** * Maps public data update request from noir to the parsed type. * @param publicDataUpdateRequest - The noir public data update request. @@ -955,9 +883,7 @@ function mapNullifierSettledReadHintToNoir( }; } -function mapNullifierReadRequestResetHintsToNoir( - hints: NullifierReadRequestResetHints, -): NullifierReadRequestResetHintsNoir { +function mapNullifierReadRequestHintsToNoir(hints: NullifierReadRequestHints): NullifierReadRequestHintsNoir { return { read_request_statuses: mapTuple(hints.readRequestStatuses, mapReadRequestStatusToNoir), pending_read_hints: mapTuple(hints.pendingReadHints, mapPendingReadHintToNoir), @@ -965,6 +891,26 @@ function mapNullifierReadRequestResetHintsToNoir( }; } +function mapNullifierNonMembershipHintToNoir( + hint: NonMembershipHint, +): NullifierNonMembershipHintNoir { + return { + low_leaf_preimage: mapNullifierLeafPreimageToNoir(hint.leafPreimage), + membership_witness: mapNullifierMembershipWitnessToNoir(hint.membershipWitness), + }; +} + +function mapNullifierNonExistentReadRequestHintsToNoir( + hints: NullifierNonExistentReadRequestHints, +): NullifierNonExistentReadRequestHintsNoir { + return { + non_membership_hints: mapTuple(hints.nonMembershipHints, mapNullifierNonMembershipHintToNoir), + sorted_pending_values: mapTuple(hints.sortedPendingValues, mapSideEffectLinkedToNoir), + sorted_pending_value_index_hints: mapTuple(hints.sortedPendingValueHints, mapNumberToNoir), + next_pending_value_indices: mapTuple(hints.nextPendingValueIndices, mapNumberToNoir), + }; +} + /** * Maps combined accumulated data from noir to the parsed type. * @param combinedAccumulatedData - The noir combined accumulated data. @@ -1006,7 +952,6 @@ export function mapCombinedAccumulatedDataFromNoir( mapTupleFromNoir(combinedAccumulatedData.unencrypted_logs_hash, NUM_FIELDS_PER_SHA256, mapFieldFromNoir), mapFieldFromNoir(combinedAccumulatedData.encrypted_log_preimages_length), mapFieldFromNoir(combinedAccumulatedData.unencrypted_log_preimages_length), - mapTupleFromNoir(combinedAccumulatedData.new_contracts, MAX_NEW_CONTRACTS_PER_TX, mapNewContractDataFromNoir), mapTupleFromNoir( combinedAccumulatedData.public_data_update_requests, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, @@ -1050,7 +995,6 @@ export function mapFinalAccumulatedDataFromNoir( mapTupleFromNoir(finalAccumulatedData.unencrypted_logs_hash, NUM_FIELDS_PER_SHA256, mapFieldFromNoir), mapFieldFromNoir(finalAccumulatedData.encrypted_log_preimages_length), mapFieldFromNoir(finalAccumulatedData.unencrypted_log_preimages_length), - mapTupleFromNoir(finalAccumulatedData.new_contracts, MAX_NEW_CONTRACTS_PER_TX, mapNewContractDataFromNoir), ); } @@ -1105,7 +1049,6 @@ export function mapPrivateAccumulatedRevertibleDataToNoir( unencrypted_logs_hash: mapTuple(data.unencryptedLogsHash, mapFieldToNoir), encrypted_log_preimages_length: mapFieldToNoir(data.encryptedLogPreimagesLength), unencrypted_log_preimages_length: mapFieldToNoir(data.unencryptedLogPreimagesLength), - new_contracts: mapTuple(data.newContracts, mapNewContractDataToNoir), }; } @@ -1133,7 +1076,6 @@ export function mapCombinedAccumulatedDataToNoir( unencrypted_logs_hash: mapTuple(combinedAccumulatedData.unencryptedLogsHash, mapFieldToNoir), encrypted_log_preimages_length: mapFieldToNoir(combinedAccumulatedData.encryptedLogPreimagesLength), unencrypted_log_preimages_length: mapFieldToNoir(combinedAccumulatedData.unencryptedLogPreimagesLength), - new_contracts: mapTuple(combinedAccumulatedData.newContracts, mapNewContractDataToNoir), public_data_update_requests: mapTuple( combinedAccumulatedData.publicDataUpdateRequests, mapPublicDataUpdateRequestToNoir, @@ -1224,7 +1166,6 @@ export function mapPublicAccumulatedRevertibleDataToNoir( unencrypted_logs_hash: mapTuple(data.unencryptedLogsHash, mapFieldToNoir), encrypted_log_preimages_length: mapFieldToNoir(data.encryptedLogPreimagesLength), unencrypted_log_preimages_length: mapFieldToNoir(data.unencryptedLogPreimagesLength), - new_contracts: mapTuple(data.newContracts, mapNewContractDataToNoir), public_data_update_requests: mapTuple(data.publicDataUpdateRequests, mapPublicDataUpdateRequestToNoir), public_data_reads: mapTuple(data.publicDataReads, mapPublicDataReadToNoir), }; @@ -1235,6 +1176,7 @@ export function mapPublicAccumulatedNonRevertibleDataToNoir( ): PublicAccumulatedNonRevertibleDataNoir { return { nullifier_read_requests: mapTuple(data.nullifierReadRequests, mapReadRequestContextToNoir), + nullifier_non_existent_read_requests: mapTuple(data.nullifierNonExistentReadRequests, mapReadRequestContextToNoir), new_note_hashes: mapTuple(data.newNoteHashes, mapSideEffectToNoir), new_nullifiers: mapTuple(data.newNullifiers, mapSideEffectLinkedToNoir), public_call_stack: mapTuple(data.publicCallStack, mapCallRequestToNoir), @@ -1327,7 +1269,6 @@ export function mapFinalAccumulatedDataToNoir( unencrypted_logs_hash: mapTuple(finalAccumulatedData.unencryptedLogsHash, mapFieldToNoir), encrypted_log_preimages_length: mapFieldToNoir(finalAccumulatedData.encryptedLogPreimagesLength), unencrypted_log_preimages_length: mapFieldToNoir(finalAccumulatedData.unencryptedLogPreimagesLength), - new_contracts: mapTuple(finalAccumulatedData.newContracts, mapNewContractDataToNoir), }; } @@ -1388,7 +1329,7 @@ export function mapPrivateKernelTailCircuitPrivateInputsToNoir( read_commitment_hints: mapTuple(inputs.readCommitmentHints, mapFieldToNoir), sorted_new_nullifiers: mapTuple(inputs.sortedNewNullifiers, mapSideEffectLinkedToNoir), sorted_new_nullifiers_indexes: mapTuple(inputs.sortedNewNullifiersIndexes, mapNumberToNoir), - nullifier_read_request_reset_hints: mapNullifierReadRequestResetHintsToNoir(inputs.nullifierReadRequestResetHints), + nullifier_read_request_hints: mapNullifierReadRequestHintsToNoir(inputs.nullifierReadRequestHints), nullifier_commitment_hints: mapTuple(inputs.nullifierCommitmentHints, mapFieldToNoir), master_nullifier_secret_keys: mapTuple(inputs.masterNullifierSecretKeys, mapGrumpkinPrivateKeyToNoir), }; @@ -1408,7 +1349,10 @@ export function mapPublicKernelTailCircuitPrivateInputsToNoir( ): PublicKernelTailCircuitPrivateInputsNoir { return { previous_kernel: mapPublicKernelDataToNoir(inputs.previousKernel), - nullifier_read_request_reset_hints: mapNullifierReadRequestResetHintsToNoir(inputs.nullifierReadRequestResetHints), + nullifier_read_request_hints: mapNullifierReadRequestHintsToNoir(inputs.nullifierReadRequestHints), + nullifier_non_existent_read_request_hints: mapNullifierNonExistentReadRequestHintsToNoir( + inputs.nullifierNonExistentReadRequestHints, + ), }; } @@ -1432,6 +1376,11 @@ export function mapPublicAccumulatedNonRevertibleDataFromNoir( ): PublicAccumulatedNonRevertibleData { return new PublicAccumulatedNonRevertibleData( mapTupleFromNoir(data.nullifier_read_requests, MAX_NULLIFIER_READ_REQUESTS_PER_TX, mapReadRequestContextFromNoir), + mapTupleFromNoir( + data.nullifier_non_existent_read_requests, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, + mapReadRequestContextFromNoir, + ), mapTupleFromNoir(data.new_note_hashes, MAX_NON_REVERTIBLE_NOTE_HASHES_PER_TX, mapSideEffectFromNoir), mapTupleFromNoir(data.new_nullifiers, MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX, mapSideEffectLinkedFromNoir), mapTupleFromNoir( @@ -1468,7 +1417,6 @@ export function mapPublicAccumulatedRevertibleDataFromNoir( mapTupleFromNoir(data.unencrypted_logs_hash, NUM_FIELDS_PER_SHA256, mapFieldFromNoir), mapFieldFromNoir(data.encrypted_log_preimages_length), mapFieldFromNoir(data.unencrypted_log_preimages_length), - mapTupleFromNoir(data.new_contracts, MAX_NEW_CONTRACTS_PER_TX, mapNewContractDataFromNoir), mapTupleFromNoir( data.public_data_update_requests, MAX_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, @@ -1563,6 +1511,7 @@ export function mapPublicCircuitPublicInputsToNoir( args_hash: mapFieldToNoir(publicInputs.argsHash), return_values: mapTuple(publicInputs.returnValues, mapFieldToNoir), nullifier_read_requests: mapTuple(publicInputs.nullifierReadRequests, mapReadRequestToNoir), + nullifier_non_existent_read_requests: mapTuple(publicInputs.nullifierNonExistentReadRequests, mapReadRequestToNoir), contract_storage_update_requests: mapTuple( publicInputs.contractStorageUpdateRequests, mapStorageUpdateRequestToNoir, @@ -1834,7 +1783,6 @@ export function mapPartialStateReferenceFromNoir( return new PartialStateReference( mapAppendOnlyTreeSnapshotFromNoir(partialStateReference.note_hash_tree), mapAppendOnlyTreeSnapshotFromNoir(partialStateReference.nullifier_tree), - mapAppendOnlyTreeSnapshotFromNoir(partialStateReference.contract_tree), mapAppendOnlyTreeSnapshotFromNoir(partialStateReference.public_data_tree), ); } @@ -1938,7 +1886,6 @@ export function mapPartialStateReferenceToNoir( return { note_hash_tree: mapAppendOnlyTreeSnapshotToNoir(partialStateReference.noteHashTree), nullifier_tree: mapAppendOnlyTreeSnapshotToNoir(partialStateReference.nullifierTree), - contract_tree: mapAppendOnlyTreeSnapshotToNoir(partialStateReference.contractTree), public_data_tree: mapAppendOnlyTreeSnapshotToNoir(partialStateReference.publicDataTree), }; } @@ -1959,7 +1906,6 @@ export function mapStateDiffHintsToNoir(hints: StateDiffHints): StateDiffHintsNo sorted_nullifier_indexes: mapTuple(hints.sortedNullifierIndexes, (index: number) => mapNumberToNoir(index)), note_hash_subtree_sibling_path: mapTuple(hints.noteHashSubtreeSiblingPath, mapFieldToNoir), nullifier_subtree_sibling_path: mapTuple(hints.nullifierSubtreeSiblingPath, mapFieldToNoir), - contract_subtree_sibling_path: mapTuple(hints.contractSubtreeSiblingPath, mapFieldToNoir), public_data_sibling_path: mapTuple(hints.publicDataSiblingPath, mapFieldToNoir), }; } diff --git a/yarn-project/p2p/src/service/tx_messages.test.ts b/yarn-project/p2p/src/service/tx_messages.test.ts index e20f90582d1..eedaca26560 100644 --- a/yarn-project/p2p/src/service/tx_messages.test.ts +++ b/yarn-project/p2p/src/service/tx_messages.test.ts @@ -20,10 +20,6 @@ const verifyTx = (actual: Tx, expected: Tx) => { expect(actual.data!.toBuffer()).toEqual(expected.data?.toBuffer()); expect(actual.proof!.toBuffer()).toEqual(expected.proof!.toBuffer()); expect(actual.encryptedLogs!.toBuffer()).toEqual(expected.encryptedLogs?.toBuffer()); - expect(actual.newContracts!.length).toEqual(expected.newContracts!.length); - for (let i = 0; i < actual.newContracts!.length; i++) { - expect(actual.newContracts![i].toBuffer()).toEqual(expected.newContracts![i].toBuffer()); - } }; describe('Messages', () => { diff --git a/yarn-project/p2p/src/service/tx_messages.ts b/yarn-project/p2p/src/service/tx_messages.ts index a3710223cfb..5858f6e3678 100644 --- a/yarn-project/p2p/src/service/tx_messages.ts +++ b/yarn-project/p2p/src/service/tx_messages.ts @@ -1,11 +1,6 @@ -import { ExtendedContractData, Tx, TxHash, TxL2Logs } from '@aztec/circuit-types'; -import { - MAX_NEW_CONTRACTS_PER_TX, - PrivateKernelTailCircuitPublicInputs, - Proof, - PublicCallRequest, -} from '@aztec/circuits.js'; -import { Tuple, numToUInt32BE } from '@aztec/foundation/serialize'; +import { Tx, TxHash, TxL2Logs } from '@aztec/circuit-types'; +import { PrivateKernelTailCircuitPublicInputs, Proof, PublicCallRequest } from '@aztec/circuits.js'; +import { numToUInt32BE } from '@aztec/foundation/serialize'; /** * Enumeration of P2P message types. @@ -151,7 +146,6 @@ export function toTxMessage(tx: Tx): Buffer { createMessageComponent(tx.encryptedLogs), createMessageComponent(tx.unencryptedLogs), createMessageComponents(tx.enqueuedPublicFunctionCalls), - createMessageComponents(tx.newContracts), ]); const messageLength = numToUInt32BE(messageBuffer.length); return Buffer.concat([messageLength, messageBuffer]); @@ -204,13 +198,5 @@ export function fromTxMessage(buffer: Buffer): Tx { } const publicCalls = toObjectArray(unencryptedLogs.remainingData, PublicCallRequest); - const newContracts = toObjectArray(publicCalls.remainingData, ExtendedContractData); - return new Tx( - publicInputs.obj!, - proof.obj!, - encryptedLogs.obj, - unencryptedLogs.obj, - publicCalls.objects, - newContracts.objects as Tuple, - ); + return new Tx(publicInputs.obj!, proof.obj!, encryptedLogs.obj, unencryptedLogs.obj, publicCalls.objects); } diff --git a/yarn-project/protocol-contracts/src/class-registerer/__snapshots__/index.test.ts.snap b/yarn-project/protocol-contracts/src/class-registerer/__snapshots__/index.test.ts.snap index 007772174fc..8c3db32215a 100644 --- a/yarn-project/protocol-contracts/src/class-registerer/__snapshots__/index.test.ts.snap +++ b/yarn-project/protocol-contracts/src/class-registerer/__snapshots__/index.test.ts.snap @@ -2,633 +2,45 @@ exports[`ClassRegisterer returns canonical protocol contract 1`] = ` { - "address": AztecAddress { - "asBigInt": 16782756145759928719149283510239227487276026664652666301289472823408773532318n, - "asBuffer": { - "data": [ - 37, - 26, - 180, - 15, - 54, - 161, - 72, - 165, - 172, - 136, - 254, - 60, - 35, - 152, - 236, - 25, - 104, - 213, - 103, - 107, - 0, - 102, - 41, - 146, - 120, - 97, - 11, - 135, - 13, - 115, - 138, - 158, - ], - "type": "Buffer", - }, - }, + "address": AztecAddress<0x251ab40f36a148a5ac88fe3c2398ec1968d5676b0066299278610b870d738a9e>, "contractClass": { - "artifactHash": Fr { - "asBigInt": 16849511505047847203273396629509951427400035309439142008111973067225945181374n, - "asBuffer": { - "data": [ - 37, - 64, - 124, - 77, - 27, - 36, - 23, - 73, - 81, - 17, - 116, - 88, - 222, - 208, - 217, - 214, - 218, - 239, - 54, - 118, - 248, - 164, - 248, - 200, - 193, - 92, - 204, - 111, - 120, - 101, - 140, - 190, - ], - "type": "Buffer", - }, - }, - "id": Fr { - "asBigInt": 6459203616861001844074101389807539136298812127324721680929212139138484648106n, - "asBuffer": { - "data": [ - 14, - 71, - 199, - 153, - 215, - 143, - 115, - 227, - 153, - 133, - 163, - 8, - 166, - 65, - 142, - 137, - 249, - 189, - 105, - 134, - 85, - 180, - 166, - 60, - 24, - 82, - 12, - 219, - 196, - 57, - 184, - 170, - ], - "type": "Buffer", - }, - }, - "packedBytecode": { - "data": [ - 0, - 0, - 0, - 0, - ], - "type": "Buffer", - }, + "artifactHash": Fr<0x25407c4d1b24174951117458ded0d9d6daef3676f8a4f8c8c15ccc6f78658cbe>, + "id": Fr<0x0e47c799d78f73e39985a308a6418e89f9bd698655b4a63c18520cdbc439b8aa>, + "packedBytecode": Buffer<0x00000000>, "privateFunctions": [ { "isInternal": false, - "selector": FunctionSelector { - "value": 588837637, - }, - "vkHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "selector": Selector<0x2318f305>, + "vkHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, { "isInternal": false, - "selector": FunctionSelector { - "value": 595568763, - }, - "vkHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "selector": Selector<0x237fa87b>, + "vkHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, { "isInternal": false, - "selector": FunctionSelector { - "value": 2432309179, - }, - "vkHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "selector": Selector<0x90fa17bb>, + "vkHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, { "isInternal": false, - "selector": FunctionSelector { - "value": 2562483603, - }, - "vkHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "selector": Selector<0x98bc6593>, + "vkHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], - "privateFunctionsRoot": Fr { - "asBigInt": 3517286851632816228452217354955431312081086184223594011972279331675045466476n, - "asBuffer": { - "data": [ - 7, - 198, - 182, - 188, - 60, - 243, - 25, - 4, - 208, - 224, - 141, - 46, - 193, - 171, - 222, - 237, - 79, - 232, - 128, - 10, - 174, - 175, - 173, - 88, - 133, - 49, - 210, - 133, - 124, - 41, - 145, - 108, - ], - "type": "Buffer", - }, - }, - "publicBytecodeCommitment": Fr { - "asBigInt": 13424778679590722659186070167781649503057405647123863047387123265455936508181n, - "asBuffer": { - "data": [ - 29, - 174, - 39, - 204, - 127, - 226, - 175, - 52, - 95, - 22, - 2, - 83, - 190, - 56, - 117, - 212, - 73, - 167, - 233, - 186, - 107, - 214, - 135, - 71, - 216, - 125, - 78, - 112, - 84, - 184, - 17, - 21, - ], - "type": "Buffer", - }, - }, + "privateFunctionsRoot": Fr<0x07c6b6bc3cf31904d0e08d2ec1abdeed4fe8800aaeafad588531d2857c29916c>, + "publicBytecodeCommitment": Fr<0x1dae27cc7fe2af345f160253be3875d449a7e9ba6bd68747d87d4e7054b81115>, "publicFunctions": [], "version": 1, }, "instance": { - "address": AztecAddress { - "asBigInt": 16782756145759928719149283510239227487276026664652666301289472823408773532318n, - "asBuffer": { - "data": [ - 37, - 26, - 180, - 15, - 54, - 161, - 72, - 165, - 172, - 136, - 254, - 60, - 35, - 152, - 236, - 25, - 104, - 213, - 103, - 107, - 0, - 102, - 41, - 146, - 120, - 97, - 11, - 135, - 13, - 115, - 138, - 158, - ], - "type": "Buffer", - }, - }, - "contractClassId": Fr { - "asBigInt": 6459203616861001844074101389807539136298812127324721680929212139138484648106n, - "asBuffer": { - "data": [ - 14, - 71, - 199, - 153, - 215, - 143, - 115, - 227, - 153, - 133, - 163, - 8, - 166, - 65, - 142, - 137, - 249, - 189, - 105, - 134, - 85, - 180, - 166, - 60, - 24, - 82, - 12, - 219, - 196, - 57, - 184, - 170, - ], - "type": "Buffer", - }, - }, - "initializationHash": Fr { - "asBigInt": 5411687428194306823799197943510367074755080310726877398642044502900791103391n, - "asBuffer": { - "data": [ - 11, - 246, - 232, - 18, - 241, - 75, - 176, - 41, - 247, - 203, - 156, - 141, - 168, - 54, - 125, - 217, - 124, - 6, - 142, - 120, - 141, - 79, - 33, - 0, - 127, - 217, - 112, - 20, - 235, - 168, - 207, - 159, - ], - "type": "Buffer", - }, - }, - "portalContractAddress": EthAddress { - "buffer": { - "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - ], - "type": "Buffer", - }, - }, - "publicKeysHash": Fr { - "asBigInt": 17954372136461894568820199868962143715279932924957662285438325406238856880109n, - "asBuffer": { - "data": [ - 39, - 177, - 208, - 131, - 154, - 91, - 35, - 186, - 241, - 42, - 141, - 25, - 91, - 24, - 172, - 40, - 143, - 207, - 64, - 26, - 251, - 47, - 112, - 184, - 164, - 181, - 41, - 237, - 229, - 250, - 159, - 237, - ], - "type": "Buffer", - }, - }, - "salt": Fr { - "asBigInt": 1n, - "asBuffer": { - "data": [ - 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, - 1, - ], - "type": "Buffer", - }, - }, + "address": AztecAddress<0x251ab40f36a148a5ac88fe3c2398ec1968d5676b0066299278610b870d738a9e>, + "contractClassId": Fr<0x0e47c799d78f73e39985a308a6418e89f9bd698655b4a63c18520cdbc439b8aa>, + "initializationHash": Fr<0x0bf6e812f14bb029f7cb9c8da8367dd97c068e788d4f21007fd97014eba8cf9f>, + "portalContractAddress": EthAddress<0x0000000000000000000000000000000000000000>, + "publicKeysHash": Fr<0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed>, + "salt": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, "version": 1, }, } diff --git a/yarn-project/protocol-contracts/src/class-registerer/index.test.ts b/yarn-project/protocol-contracts/src/class-registerer/index.test.ts index 3ec33b4a2ea..26b85367caf 100644 --- a/yarn-project/protocol-contracts/src/class-registerer/index.test.ts +++ b/yarn-project/protocol-contracts/src/class-registerer/index.test.ts @@ -1,8 +1,11 @@ +import { setupCustomSnapshotSerializers } from '@aztec/foundation/testing'; + import omit from 'lodash.omit'; import { ClassRegistererAddress, getCanonicalClassRegisterer } from './index.js'; describe('ClassRegisterer', () => { + setupCustomSnapshotSerializers(expect); it('returns canonical protocol contract', () => { const contract = getCanonicalClassRegisterer(); expect(omit(contract, 'artifact')).toMatchSnapshot(); diff --git a/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap b/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap index 79c161f0dcb..41071066dc1 100644 --- a/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap +++ b/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap @@ -2,274 +2,14 @@ exports[`GasToken returns canonical protocol contract 1`] = ` { - "address": AztecAddress { - "asBigInt": 10518537853519909204957666322334442672584410385979059968848104222965977783517n, - "asBuffer": { - "data": [ - 23, - 65, - 72, - 13, - 6, - 111, - 233, - 124, - 40, - 151, - 239, - 36, - 144, - 234, - 34, - 48, - 149, - 204, - 24, - 108, - 103, - 5, - 224, - 47, - 181, - 106, - 33, - 6, - 27, - 203, - 28, - 221, - ], - "type": "Buffer", - }, - }, + "address": AztecAddress<0x2b3035985f1a4ed792a70cde88b7fee0f90f361b9e7f5842343fe67530906597>, "instance": { - "address": AztecAddress { - "asBigInt": 10518537853519909204957666322334442672584410385979059968848104222965977783517n, - "asBuffer": { - "data": [ - 23, - 65, - 72, - 13, - 6, - 111, - 233, - 124, - 40, - 151, - 239, - 36, - 144, - 234, - 34, - 48, - 149, - 204, - 24, - 108, - 103, - 5, - 224, - 47, - 181, - 106, - 33, - 6, - 27, - 203, - 28, - 221, - ], - "type": "Buffer", - }, - }, - "contractClassId": Fr { - "asBigInt": 1081288800764539456992515725727545013194509212534089179832398000157107722146n, - "asBuffer": { - "data": [ - 2, - 99, - 252, - 222, - 180, - 100, - 28, - 30, - 214, - 18, - 131, - 72, - 114, - 250, - 186, - 113, - 101, - 40, - 14, - 133, - 193, - 94, - 154, - 6, - 203, - 103, - 189, - 107, - 88, - 212, - 151, - 162, - ], - "type": "Buffer", - }, - }, - "initializationHash": Fr { - "asBigInt": 5411687428194306823799197943510367074755080310726877398642044502900791103391n, - "asBuffer": { - "data": [ - 11, - 246, - 232, - 18, - 241, - 75, - 176, - 41, - 247, - 203, - 156, - 141, - 168, - 54, - 125, - 217, - 124, - 6, - 142, - 120, - 141, - 79, - 33, - 0, - 127, - 217, - 112, - 20, - 235, - 168, - 207, - 159, - ], - "type": "Buffer", - }, - }, - "portalContractAddress": EthAddress { - "buffer": { - "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - ], - "type": "Buffer", - }, - }, - "publicKeysHash": Fr { - "asBigInt": 17954372136461894568820199868962143715279932924957662285438325406238856880109n, - "asBuffer": { - "data": [ - 39, - 177, - 208, - 131, - 154, - 91, - 35, - 186, - 241, - 42, - 141, - 25, - 91, - 24, - 172, - 40, - 143, - 207, - 64, - 26, - 251, - 47, - 112, - 184, - 164, - 181, - 41, - 237, - 229, - 250, - 159, - 237, - ], - "type": "Buffer", - }, - }, - "salt": Fr { - "asBigInt": 1n, - "asBuffer": { - "data": [ - 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, - 1, - ], - "type": "Buffer", - }, - }, + "address": AztecAddress<0x2b3035985f1a4ed792a70cde88b7fee0f90f361b9e7f5842343fe67530906597>, + "contractClassId": Fr<0x065cf6dd52fb349293d583cfc8ac8f4553770e7aa48ed37a5adf679fdbee7be4>, + "initializationHash": Fr<0x0bf6e812f14bb029f7cb9c8da8367dd97c068e788d4f21007fd97014eba8cf9f>, + "portalContractAddress": EthAddress<0x0000000000000000000000000000000000000000>, + "publicKeysHash": Fr<0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed>, + "salt": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, "version": 1, }, } @@ -277,214 +17,17 @@ exports[`GasToken returns canonical protocol contract 1`] = ` exports[`GasToken returns canonical protocol contract 2`] = ` { - "artifactHash": Fr { - "asBigInt": 3363571886208995000060653132822906490593381833217164785427349714321114865759n, - "asBuffer": { - "data": [ - 7, - 111, - 182, - 215, - 73, - 59, - 7, - 90, - 136, - 14, - 238, - 217, - 15, - 236, - 124, - 76, - 1, - 224, - 162, - 77, - 68, - 37, - 34, - 68, - 158, - 77, - 86, - 194, - 99, - 87, - 32, - 95, - ], - "type": "Buffer", - }, - }, - "id": Fr { - "asBigInt": 1081288800764539456992515725727545013194509212534089179832398000157107722146n, - "asBuffer": { - "data": [ - 2, - 99, - 252, - 222, - 180, - 100, - 28, - 30, - 214, - 18, - 131, - 72, - 114, - 250, - 186, - 113, - 101, - 40, - 14, - 133, - 193, - 94, - 154, - 6, - 203, - 103, - 189, - 107, - 88, - 212, - 151, - 162, - ], - "type": "Buffer", - }, - }, + "artifactHash": Fr<0x076fb6d7493b075a880eeed90fec7c4c01e0a24d442522449e4d56c26357205f>, + "id": Fr<0x065cf6dd52fb349293d583cfc8ac8f4553770e7aa48ed37a5adf679fdbee7be4>, "privateFunctions": [ { "isInternal": false, - "selector": FunctionSelector { - "value": 2432309179, - }, - "vkHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "selector": Selector<0x90fa17bb>, + "vkHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], - "privateFunctionsRoot": Fr { - "asBigInt": 8909521279374546913798331365196924937704969493731099782202223186665436350504n, - "asBuffer": { - "data": [ - 19, - 178, - 156, - 63, - 74, - 150, - 235, - 20, - 213, - 211, - 83, - 154, - 99, - 8, - 255, - 151, - 54, - 173, - 93, - 103, - 227, - 246, - 31, - 251, - 183, - 218, - 144, - 142, - 20, - 152, - 8, - 40, - ], - "type": "Buffer", - }, - }, - "publicBytecodeCommitment": Fr { - "asBigInt": 11070879835458647599904872869544251898416073411427356569372185618409843299916n, - "asBuffer": { - "data": [ - 24, - 121, - 229, - 91, - 202, - 195, - 128, - 170, - 238, - 201, - 145, - 159, - 246, - 6, - 245, - 115, - 211, - 60, - 229, - 130, - 225, - 76, - 234, - 38, - 46, - 15, - 108, - 202, - 129, - 107, - 150, - 76, - ], - "type": "Buffer", - }, - }, + "privateFunctionsRoot": Fr<0x13b29c3f4a96eb14d5d3539a6308ff9736ad5d67e3f61ffbb7da908e14980828>, + "publicBytecodeCommitment": Fr<0x18485f6c7fc11c817ccb544ba30e0c4f9c83742b3d6318d68037290e4e8c1c51>, "version": 1, } `; @@ -493,27 +36,19 @@ exports[`GasToken returns canonical protocol contract 3`] = ` [ { "isInternal": false, - "selector": FunctionSelector { - "value": 190347739, - }, + "selector": Selector<0x0b5879db>, }, { "isInternal": false, - "selector": FunctionSelector { - "value": 1776307709, - }, + "selector": Selector<0x69e04dfd>, }, { "isInternal": false, - "selector": FunctionSelector { - "value": 1811750235, - }, + "selector": Selector<0x6bfd1d5b>, }, { "isInternal": false, - "selector": FunctionSelector { - "value": 3422298534, - }, + "selector": Selector<0xcbfc21a6>, }, ] `; diff --git a/yarn-project/protocol-contracts/src/gas-token/index.test.ts b/yarn-project/protocol-contracts/src/gas-token/index.test.ts index b85b0c29d86..68a23995858 100644 --- a/yarn-project/protocol-contracts/src/gas-token/index.test.ts +++ b/yarn-project/protocol-contracts/src/gas-token/index.test.ts @@ -1,8 +1,11 @@ +import { setupCustomSnapshotSerializers } from '@aztec/foundation/testing'; + import omit from 'lodash.omit'; import { GasTokenAddress, getCanonicalGasToken } from './index.js'; describe('GasToken', () => { + setupCustomSnapshotSerializers(expect); it('returns canonical protocol contract', () => { // if you're updating the snapshots here then you'll also have to update CANONICAL_GAS_TOKEN_ADDRESS in // - noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr diff --git a/yarn-project/protocol-contracts/src/instance-deployer/__snapshots__/index.test.ts.snap b/yarn-project/protocol-contracts/src/instance-deployer/__snapshots__/index.test.ts.snap index a30fc6c0ba0..a562c6a022f 100644 --- a/yarn-project/protocol-contracts/src/instance-deployer/__snapshots__/index.test.ts.snap +++ b/yarn-project/protocol-contracts/src/instance-deployer/__snapshots__/index.test.ts.snap @@ -2,541 +2,35 @@ exports[`InstanceDeployer returns canonical protocol contract 1`] = ` { - "address": AztecAddress { - "asBigInt": 3292754564016949916718877297115777598905061669834342030471417311460989046852n, - "asBuffer": { - "data": [ - 7, - 71, - 162, - 14, - 208, - 200, - 96, - 53, - 228, - 78, - 165, - 96, - 111, - 48, - 222, - 69, - 159, - 64, - 181, - 92, - 94, - 130, - 1, - 38, - 64, - 170, - 85, - 69, - 70, - 175, - 144, - 68, - ], - "type": "Buffer", - }, - }, + "address": AztecAddress<0x0747a20ed0c86035e44ea5606f30de459f40b55c5e82012640aa554546af9044>, "contractClass": { - "artifactHash": Fr { - "asBigInt": 14004623793815794786663172306952806542169300491436089583084017080489106515164n, - "asBuffer": { - "data": [ - 30, - 246, - 86, - 15, - 36, - 14, - 183, - 120, - 232, - 198, - 163, - 244, - 175, - 96, - 159, - 150, - 221, - 22, - 123, - 72, - 71, - 20, - 2, - 134, - 20, - 176, - 2, - 23, - 9, - 248, - 164, - 220, - ], - "type": "Buffer", - }, - }, - "id": Fr { - "asBigInt": 18800681354736902372207149850261995699819228885238981092036778984892317144615n, - "asBuffer": { - "data": [ - 41, - 144, - 206, - 253, - 46, - 88, - 237, - 15, - 191, - 185, - 124, - 36, - 46, - 254, - 144, - 100, - 66, - 216, - 236, - 181, - 113, - 20, - 163, - 159, - 75, - 11, - 21, - 162, - 80, - 133, - 150, - 39, - ], - "type": "Buffer", - }, - }, - "packedBytecode": { - "data": [ - 0, - 0, - 0, - 0, - ], - "type": "Buffer", - }, + "artifactHash": Fr<0x1ef6560f240eb778e8c6a3f4af609f96dd167b484714028614b0021709f8a4dc>, + "id": Fr<0x2990cefd2e58ed0fbfb97c242efe906442d8ecb57114a39f4b0b15a250859627>, + "packedBytecode": Buffer<0x00000000>, "privateFunctions": [ { "isInternal": false, - "selector": FunctionSelector { - "value": 2285065643, - }, - "vkHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "selector": Selector<0x883355ab>, + "vkHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, { "isInternal": false, - "selector": FunctionSelector { - "value": 2432309179, - }, - "vkHash": Fr { - "asBigInt": 0n, - "asBuffer": { - "data": [ - 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, - 0, - ], - "type": "Buffer", - }, - }, + "selector": Selector<0x90fa17bb>, + "vkHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, ], - "privateFunctionsRoot": Fr { - "asBigInt": 10175937322611504760053163396285173722489074882473725995897130952520062304283n, - "asBuffer": { - "data": [ - 22, - 127, - 96, - 93, - 15, - 118, - 143, - 145, - 206, - 97, - 129, - 56, - 23, - 230, - 12, - 1, - 170, - 115, - 219, - 197, - 231, - 133, - 116, - 128, - 74, - 71, - 30, - 51, - 115, - 5, - 128, - 27, - ], - "type": "Buffer", - }, - }, - "publicBytecodeCommitment": Fr { - "asBigInt": 13424778679590722659186070167781649503057405647123863047387123265455936508181n, - "asBuffer": { - "data": [ - 29, - 174, - 39, - 204, - 127, - 226, - 175, - 52, - 95, - 22, - 2, - 83, - 190, - 56, - 117, - 212, - 73, - 167, - 233, - 186, - 107, - 214, - 135, - 71, - 216, - 125, - 78, - 112, - 84, - 184, - 17, - 21, - ], - "type": "Buffer", - }, - }, + "privateFunctionsRoot": Fr<0x167f605d0f768f91ce61813817e60c01aa73dbc5e78574804a471e337305801b>, + "publicBytecodeCommitment": Fr<0x1dae27cc7fe2af345f160253be3875d449a7e9ba6bd68747d87d4e7054b81115>, "publicFunctions": [], "version": 1, }, "instance": { - "address": AztecAddress { - "asBigInt": 3292754564016949916718877297115777598905061669834342030471417311460989046852n, - "asBuffer": { - "data": [ - 7, - 71, - 162, - 14, - 208, - 200, - 96, - 53, - 228, - 78, - 165, - 96, - 111, - 48, - 222, - 69, - 159, - 64, - 181, - 92, - 94, - 130, - 1, - 38, - 64, - 170, - 85, - 69, - 70, - 175, - 144, - 68, - ], - "type": "Buffer", - }, - }, - "contractClassId": Fr { - "asBigInt": 18800681354736902372207149850261995699819228885238981092036778984892317144615n, - "asBuffer": { - "data": [ - 41, - 144, - 206, - 253, - 46, - 88, - 237, - 15, - 191, - 185, - 124, - 36, - 46, - 254, - 144, - 100, - 66, - 216, - 236, - 181, - 113, - 20, - 163, - 159, - 75, - 11, - 21, - 162, - 80, - 133, - 150, - 39, - ], - "type": "Buffer", - }, - }, - "initializationHash": Fr { - "asBigInt": 5411687428194306823799197943510367074755080310726877398642044502900791103391n, - "asBuffer": { - "data": [ - 11, - 246, - 232, - 18, - 241, - 75, - 176, - 41, - 247, - 203, - 156, - 141, - 168, - 54, - 125, - 217, - 124, - 6, - 142, - 120, - 141, - 79, - 33, - 0, - 127, - 217, - 112, - 20, - 235, - 168, - 207, - 159, - ], - "type": "Buffer", - }, - }, - "portalContractAddress": EthAddress { - "buffer": { - "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - ], - "type": "Buffer", - }, - }, - "publicKeysHash": Fr { - "asBigInt": 17954372136461894568820199868962143715279932924957662285438325406238856880109n, - "asBuffer": { - "data": [ - 39, - 177, - 208, - 131, - 154, - 91, - 35, - 186, - 241, - 42, - 141, - 25, - 91, - 24, - 172, - 40, - 143, - 207, - 64, - 26, - 251, - 47, - 112, - 184, - 164, - 181, - 41, - 237, - 229, - 250, - 159, - 237, - ], - "type": "Buffer", - }, - }, - "salt": Fr { - "asBigInt": 1n, - "asBuffer": { - "data": [ - 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, - 1, - ], - "type": "Buffer", - }, - }, + "address": AztecAddress<0x0747a20ed0c86035e44ea5606f30de459f40b55c5e82012640aa554546af9044>, + "contractClassId": Fr<0x2990cefd2e58ed0fbfb97c242efe906442d8ecb57114a39f4b0b15a250859627>, + "initializationHash": Fr<0x0bf6e812f14bb029f7cb9c8da8367dd97c068e788d4f21007fd97014eba8cf9f>, + "portalContractAddress": EthAddress<0x0000000000000000000000000000000000000000>, + "publicKeysHash": Fr<0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed>, + "salt": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, "version": 1, }, } diff --git a/yarn-project/protocol-contracts/src/instance-deployer/index.test.ts b/yarn-project/protocol-contracts/src/instance-deployer/index.test.ts index 11cb86d64e3..0bd8e117eb6 100644 --- a/yarn-project/protocol-contracts/src/instance-deployer/index.test.ts +++ b/yarn-project/protocol-contracts/src/instance-deployer/index.test.ts @@ -1,8 +1,11 @@ +import { setupCustomSnapshotSerializers } from '@aztec/foundation/testing'; + import omit from 'lodash.omit'; import { InstanceDeployerAddress, getCanonicalInstanceDeployer } from './index.js'; describe('InstanceDeployer', () => { + setupCustomSnapshotSerializers(expect); it('returns canonical protocol contract', () => { // TODO(@spalladino): Consider sorting functions by selector when constructing the contract // class, or even better, when calling loadContractArtifact from the Noir output. diff --git a/yarn-project/pxe/src/kernel_prover/hints_builder.ts b/yarn-project/pxe/src/kernel_prover/hints_builder.ts index 7f5dfd881e7..eb7ee451963 100644 --- a/yarn-project/pxe/src/kernel_prover/hints_builder.ts +++ b/yarn-project/pxe/src/kernel_prover/hints_builder.ts @@ -13,7 +13,7 @@ import { SideEffect, SideEffectLinkedToNoteHash, SideEffectType, - buildNullifierReadRequestResetHints, + buildNullifierReadRequestHints, } from '@aztec/circuits.js'; import { makeTuple } from '@aztec/foundation/array'; import { Tuple } from '@aztec/foundation/serialize'; @@ -74,11 +74,11 @@ export class HintsBuilder { return hints; } - getNullifierReadRequestResetHints( + getNullifierReadRequestHints( nullifierReadRequests: Tuple, nullifiers: Tuple, ) { - return buildNullifierReadRequestResetHints(this, nullifierReadRequests, nullifiers); + return buildNullifierReadRequestHints(this, nullifierReadRequests, nullifiers); } async getNullifierMembershipWitness(nullifier: Fr) { diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts index 5ecb98cfba7..b761f93855b 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts @@ -189,7 +189,7 @@ export class KernelProver { sortedNoteHashes, ); - const nullifierReadRequestResetHints = await this.hintsBuilder.getNullifierReadRequestResetHints( + const nullifierReadRequestHints = await this.hintsBuilder.getNullifierReadRequestHints( output.publicInputs.end.nullifierReadRequests, output.publicInputs.end.newNullifiers, ); @@ -214,7 +214,7 @@ export class KernelProver { readNoteHashHints, sortedNullifiers, sortedNullifiersIndexes, - nullifierReadRequestResetHints, + nullifierReadRequestHints, nullifierNoteHashHints, masterNullifierSecretKeys, ); diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 661091a8c67..a2db19a39f8 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -21,7 +21,6 @@ import { TxHash, TxL2Logs, TxReceipt, - getNewContractPublicFunctions, isNoirCallStackUnresolved, } from '@aztec/circuit-types'; import { TxPXEProcessingStats } from '@aztec/circuit-types/stats'; @@ -38,7 +37,6 @@ import { PublicCallRequest, computeArtifactHash, computeContractClassId, - computeSaltedInitializationHash, getContractClassFromArtifact, } from '@aztec/circuits.js'; import { computeCommitmentNonce, siloNullifier } from '@aztec/circuits.js/hash'; @@ -390,13 +388,8 @@ export class PXEService implements PXE { // all simulations must be serialized w.r.t. the synchronizer return await this.jobQueue.put(async () => { - // We get the contract address from origin, since contract deployments are signalled as origin from their own address - // TODO: Is this ok? Should it be changed to be from ZERO? - const deployedContractAddress = txRequest.txContext.isContractDeploymentTx ? txRequest.origin : undefined; - const newContract = deployedContractAddress ? await this.db.getContract(deployedContractAddress) : undefined; - const timer = new Timer(); - const tx = await this.#simulateAndProve(txRequest, newContract); + const tx = await this.#simulateAndProve(txRequest); this.log(`Processed private part of ${tx.getTxHash()}`, { eventName: 'tx-pxe-processing', duration: timer.ms(), @@ -614,10 +607,9 @@ export class PXEService implements PXE { * * @param txExecutionRequest - The transaction request to be simulated and proved. * @param signature - The ECDSA signature for the transaction request. - * @param newContract - Optional. The address of a new contract to be included in the transaction object. * @returns A private transaction object containing the proof, public inputs, and encrypted logs. */ - async #simulateAndProve(txExecutionRequest: TxExecutionRequest, newContract: ContractDao | undefined) { + async #simulateAndProve(txExecutionRequest: TxExecutionRequest) { // TODO - Pause syncing while simulating. // Get values that allow us to reconstruct the block hash @@ -635,21 +627,11 @@ export class PXEService implements PXE { const unencryptedLogs = new TxL2Logs(collectUnencryptedLogs(executionResult)); const enqueuedPublicFunctions = collectEnqueuedPublicFunctionCalls(executionResult); - const extendedContractData = newContract - ? new ExtendedContractData( - new ContractData(newContract.instance.address, newContract.instance.portalContractAddress), - getNewContractPublicFunctions(newContract), - getContractClassFromArtifact(newContract).id, - computeSaltedInitializationHash(newContract.instance), - newContract.instance.publicKeysHash, - ) - : ExtendedContractData.empty(); - // HACK(#1639): Manually patches the ordering of the public call stack // TODO(#757): Enforce proper ordering of enqueued public calls await this.patchPublicCallStackOrdering(publicInputs, enqueuedPublicFunctions); - return new Tx(publicInputs, proof, encryptedLogs, unencryptedLogs, enqueuedPublicFunctions, [extendedContractData]); + return new Tx(publicInputs, proof, encryptedLogs, unencryptedLogs, enqueuedPublicFunctions); } /** diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts index 43048e9e31f..01588b0e3ba 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts @@ -31,7 +31,6 @@ function createPXEService(): Promise { registryAddress: EthAddress.random(), inboxAddress: EthAddress.random(), outboxAddress: EthAddress.random(), - contractDeploymentEmitterAddress: EthAddress.random(), }; node.getL1ContractAddresses.mockResolvedValue(mockedContracts); diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index eae626c07c5..b105f4a1e8a 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -161,8 +161,6 @@ export class SimulatorOracle implements DBOracle { public async getSiblingPath(blockNumber: number, treeId: MerkleTreeId, leafIndex: bigint): Promise { switch (treeId) { - case MerkleTreeId.CONTRACT_TREE: - return (await this.aztecNode.getContractSiblingPath(blockNumber, leafIndex)).toFields(); case MerkleTreeId.NULLIFIER_TREE: return (await this.aztecNode.getNullifierSiblingPath(blockNumber, leafIndex)).toFields(); case MerkleTreeId.NOTE_HASH_TREE: diff --git a/yarn-project/scripts/src/benchmarks/aggregate.ts b/yarn-project/scripts/src/benchmarks/aggregate.ts index d3e027f3e6f..54bdb56dd4f 100644 --- a/yarn-project/scripts/src/benchmarks/aggregate.ts +++ b/yarn-project/scripts/src/benchmarks/aggregate.ts @@ -151,7 +151,7 @@ function processNodeSyncedChain(entry: NodeSyncedChainHistoryStats, results: Ben /** Processes entries for events tx-added-to-pool, with grouping by deployed contract count. */ function processTxAddedToPool(entry: TxAddedToPoolStats, results: BenchmarkCollectedResults) { - append(results, 'tx_size_in_bytes', entry.newContractCount, entry.size); + append(results, 'tx_size_in_bytes', entry.classRegisteredCount, entry.size); } /** Process entries for events tx-private-part-processed, grouped by new note hashes */ diff --git a/yarn-project/scripts/src/benchmarks/markdown.ts b/yarn-project/scripts/src/benchmarks/markdown.ts index 2fb3ddec168..bdd88c5f0c6 100644 --- a/yarn-project/scripts/src/benchmarks/markdown.ts +++ b/yarn-project/scripts/src/benchmarks/markdown.ts @@ -186,7 +186,7 @@ export function getMarkdown() { const metricsByBlockSize = Metrics.filter(m => m.groupBy === 'block-size').map(m => m.name); const metricsByChainLength = Metrics.filter(m => m.groupBy === 'chain-length').map(m => m.name); const metricsByCircuitName = Metrics.filter(m => m.groupBy === 'circuit-name').map(m => m.name); - const metricsByContractCount = Metrics.filter(m => m.groupBy === 'contract-count').map(m => m.name); + const metricsByClassesRegistered = Metrics.filter(m => m.groupBy === 'classes-registered').map(m => m.name); const metricsByLeafCount = Metrics.filter(m => m.groupBy === 'leaf-count').map(m => m.name); const metricsTxPxeProcessing = Metrics.filter(m => m.name === 'tx_pxe_processing_time_ms').map(m => m.name); @@ -239,8 +239,8 @@ ${getTableContent(pick(benchmark, metricsByLeafCount), baseBenchmark, 'leaves')} ### Miscellaneous -Transaction sizes based on how many contracts are deployed in the tx. -${getTableContent(pick(benchmark, metricsByContractCount), baseBenchmark, 'deployed contracts')} +Transaction sizes based on how many contract classes are registered in the tx. +${getTableContent(pick(benchmark, metricsByClassesRegistered), baseBenchmark, 'registered classes')} Transaction processing duration by data writes. ${getTableContent(pick(benchmark, metricsTxPxeProcessing), baseBenchmark, 'new note hashes')} diff --git a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts index 5ffe538c8e8..21b73c3f3b7 100644 --- a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts +++ b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts @@ -1,13 +1,4 @@ -import { - Body, - ExtendedContractData, - L2Block, - MerkleTreeId, - Tx, - TxEffect, - makeEmptyLogs, - mockTx, -} from '@aztec/circuit-types'; +import { Body, L2Block, MerkleTreeId, Tx, TxEffect, makeEmptyLogs, mockTx } from '@aztec/circuit-types'; import { AppendOnlyTreeSnapshot, AztecAddress, @@ -40,7 +31,6 @@ import { import { fr, makeBaseOrMergeRollupPublicInputs, - makeNewContractData, makeNewSideEffect, makeNewSideEffectLinkedToNoteHash, makePrivateKernelTailCircuitPublicInputs, @@ -135,18 +125,12 @@ describe('sequencer/solo_block_builder', () => { // Updates the expectedDb trees based on the new note hashes, contracts, and nullifiers from these txs const updateExpectedTreesFromTxs = async (txs: ProcessedTx[]) => { - const newContracts = txs.flatMap(tx => tx.data.end.newContracts.map(cd => cd.hash())); - for (const [tree, leaves] of [ - [ - MerkleTreeId.NOTE_HASH_TREE, - txs.flatMap(tx => - [...tx.data.endNonRevertibleData.newNoteHashes, ...tx.data.end.newNoteHashes].map(l => l.value.toBuffer()), - ), - ], - [MerkleTreeId.CONTRACT_TREE, newContracts.map(x => x.toBuffer())], - ] as const) { - await expectsDb.appendLeaves(tree, leaves); - } + await expectsDb.appendLeaves( + MerkleTreeId.NOTE_HASH_TREE, + txs.flatMap(tx => + [...tx.data.endNonRevertibleData.newNoteHashes, ...tx.data.end.newNoteHashes].map(l => l.value.toBuffer()), + ), + ); await expectsDb.batchInsert( MerkleTreeId.NULLIFIER_TREE, txs.flatMap(tx => @@ -186,7 +170,6 @@ describe('sequencer/solo_block_builder', () => { return new PartialStateReference( await getTreeSnapshot(MerkleTreeId.NOTE_HASH_TREE), await getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE), - await getTreeSnapshot(MerkleTreeId.CONTRACT_TREE), await getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE), ); }; @@ -212,7 +195,6 @@ describe('sequencer/solo_block_builder', () => { makeEmptyLogs(), makeEmptyLogs(), times(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, makePublicCallRequest), - [ExtendedContractData.random()], ), ); @@ -298,13 +280,8 @@ describe('sequencer/solo_block_builder', () => { builder = new SoloBlockBuilder(builderDb, vks, simulator, prover); }); - const makeContractDeployProcessedTx = async (seed = 0x1) => { - const tx = await makeEmptyProcessedTx(); - tx.data.end.newContracts = [makeNewContractData(seed + 0x1000)]; - return tx; - }; - const makeBloatedProcessedTx = async (seed = 0x1) => { + seed *= MAX_NEW_NULLIFIERS_PER_TX; // Ensure no clashing given incremental seeds const tx = mockTx(seed); const kernelOutput = PublicKernelCircuitPublicInputs.empty(); kernelOutput.constants.historicalHeader = await builderDb.buildInitialHeader(); @@ -334,17 +311,18 @@ describe('sequencer/solo_block_builder', () => { processedTx.data.end.newNullifiers = makeTuple( MAX_REVERTIBLE_NULLIFIERS_PER_TX, makeNewSideEffectLinkedToNoteHash, - seed + 0x200, + seed + 0x100000, ); + processedTx.data.endNonRevertibleData.newNullifiers = makeTuple( MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX, makeNewSideEffectLinkedToNoteHash, - seed + 0x300, + seed + 0x100000 + MAX_REVERTIBLE_NULLIFIERS_PER_TX, ); + processedTx.data.end.newNullifiers[tx.data.end.newNullifiers.length - 1] = SideEffectLinkedToNoteHash.empty(); processedTx.data.end.newL2ToL1Msgs = makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x300); - processedTx.data.end.newContracts = [makeNewContractData(seed + 0x1000)]; processedTx.data.end.encryptedLogsHash = to2Fields(processedTx.encryptedLogs.hash()); processedTx.data.end.unencryptedLogsHash = to2Fields(processedTx.unencryptedLogs.hash()); @@ -358,28 +336,26 @@ describe('sequencer/solo_block_builder', () => { [0, 16], [16, 16], ] as const)( - 'builds an L2 block with %i contract deploy txs and %i txs total', - async (deployCount: number, totalCount: number) => { - const contractTreeBefore = await builderDb.getTreeInfo(MerkleTreeId.CONTRACT_TREE); - + 'builds an L2 block with %i bloated txs and %i txs total', + async (bloatedCount: number, totalCount: number) => { + const noteHashTreeBefore = await builderDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE); const txs = [ - ...(await Promise.all(times(deployCount, makeContractDeployProcessedTx))), - ...(await Promise.all(times(totalCount - deployCount, makeEmptyProcessedTx))), + ...(await Promise.all(times(bloatedCount, makeBloatedProcessedTx))), + ...(await Promise.all(times(totalCount - bloatedCount, makeEmptyProcessedTx))), ]; const [l2Block] = await builder.buildL2Block(globalVariables, txs, mockL1ToL2Messages); expect(l2Block.number).toEqual(blockNumber); await updateExpectedTreesFromTxs(txs); - const contractTreeAfter = await builderDb.getTreeInfo(MerkleTreeId.CONTRACT_TREE); + const noteHashTreeAfter = await builderDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE); - if (deployCount > 0) { - expect(contractTreeAfter.root).not.toEqual(contractTreeBefore.root); + if (bloatedCount > 0) { + expect(noteHashTreeAfter.root).not.toEqual(noteHashTreeBefore.root); } - const expectedContractTreeAfter = await expectsDb.getTreeInfo(MerkleTreeId.CONTRACT_TREE).then(t => t.root); - expect(contractTreeAfter.root).toEqual(expectedContractTreeAfter); - expect(contractTreeAfter.size).toEqual(BigInt(totalCount)); + const expectedNoteHashTreeAfter = await expectsDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE).then(t => t.root); + expect(noteHashTreeAfter.root).toEqual(expectedNoteHashTreeAfter); }, 60000, ); @@ -397,12 +373,11 @@ describe('sequencer/solo_block_builder', () => { }, 30_000); it('builds a mixed L2 block', async () => { - // Ensure that each transaction has unique (non-intersecting nullifier values) const txs = await Promise.all([ - makeBloatedProcessedTx(1 * MAX_NEW_NULLIFIERS_PER_TX), - makeBloatedProcessedTx(2 * MAX_NEW_NULLIFIERS_PER_TX), - makeBloatedProcessedTx(3 * MAX_NEW_NULLIFIERS_PER_TX), - makeBloatedProcessedTx(4 * MAX_NEW_NULLIFIERS_PER_TX), + makeBloatedProcessedTx(1), + makeBloatedProcessedTx(2), + makeBloatedProcessedTx(3), + makeBloatedProcessedTx(4), ]); const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); diff --git a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts index 42045d6416e..da3553c64a8 100644 --- a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts +++ b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts @@ -5,8 +5,6 @@ import { AppendOnlyTreeSnapshot, BaseOrMergeRollupPublicInputs, BaseRollupInputs, - CONTRACT_SUBTREE_HEIGHT, - CONTRACT_SUBTREE_SIBLING_PATH_LENGTH, ConstantRollupData, GlobalVariables, L1_TO_L2_MSG_SUBTREE_HEIGHT, @@ -137,9 +135,6 @@ export class SoloBlockBuilder implements BlockBuilder { if (txHeader.state.partial.nullifierTree.isZero()) { throw new Error(`Empty nullifier tree in tx: ${toFriendlyJSON(tx)}`); } - if (txHeader.state.partial.contractTree.isZero()) { - throw new Error(`Empty contract tree in tx: ${toFriendlyJSON(tx)}`); - } if (txHeader.state.partial.publicDataTree.isZero()) { throw new Error(`Empty public data tree in tx: ${toFriendlyJSON(tx)}`); } @@ -171,14 +166,11 @@ export class SoloBlockBuilder implements BlockBuilder { for (const tx of txs) { const input = await this.buildBaseRollupInput(tx, globalVariables); baseRollupInputs.push(input); - const promises = [ - MerkleTreeId.NOTE_HASH_TREE, - MerkleTreeId.CONTRACT_TREE, - MerkleTreeId.NULLIFIER_TREE, - MerkleTreeId.PUBLIC_DATA_TREE, - ].map(async (id: MerkleTreeId) => { - return { key: id, value: await this.getTreeSnapshot(id) }; - }); + const promises = [MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.PUBLIC_DATA_TREE].map( + async (id: MerkleTreeId) => { + return { key: id, value: await this.getTreeSnapshot(id) }; + }, + ); const snapshots: Map = new Map( (await Promise.all(promises)).map(obj => [obj.key, obj.value]), ); @@ -316,11 +308,6 @@ export class SoloBlockBuilder implements BlockBuilder { partialState.nullifierTree, 'NullifierTree', ); - this.validateSimulatedTree( - treeSnapshots.get(MerkleTreeId.CONTRACT_TREE)!, - partialState.contractTree, - 'ContractTree', - ); this.validateSimulatedTree( treeSnapshots.get(MerkleTreeId.PUBLIC_DATA_TREE)!, partialState.publicDataTree, @@ -329,14 +316,11 @@ export class SoloBlockBuilder implements BlockBuilder { } protected async validateState(state: StateReference) { - const promises = [ - MerkleTreeId.NOTE_HASH_TREE, - MerkleTreeId.CONTRACT_TREE, - MerkleTreeId.NULLIFIER_TREE, - MerkleTreeId.PUBLIC_DATA_TREE, - ].map(async (id: MerkleTreeId) => { - return { key: id, value: await this.getTreeSnapshot(id) }; - }); + const promises = [MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.PUBLIC_DATA_TREE].map( + async (id: MerkleTreeId) => { + return { key: id, value: await this.getTreeSnapshot(id) }; + }, + ); const snapshots: Map = new Map( (await Promise.all(promises)).map(obj => [obj.key, obj.value]), ); @@ -636,7 +620,6 @@ export class SoloBlockBuilder implements BlockBuilder { const start = new PartialStateReference( await this.getTreeSnapshot(MerkleTreeId.NOTE_HASH_TREE), await this.getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE), - await this.getTreeSnapshot(MerkleTreeId.CONTRACT_TREE), await this.getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE), ); @@ -650,25 +633,9 @@ export class SoloBlockBuilder implements BlockBuilder { i < noteHashSubtreeSiblingPathArray.length ? noteHashSubtreeSiblingPathArray[i] : Fr.ZERO, ); - const contractSubtreeSiblingPathArray = await this.getSubtreeSiblingPath( - MerkleTreeId.CONTRACT_TREE, - CONTRACT_SUBTREE_HEIGHT, - ); - - const contractSubtreeSiblingPath = makeTuple(CONTRACT_SUBTREE_SIBLING_PATH_LENGTH, i => - i < contractSubtreeSiblingPathArray.length ? contractSubtreeSiblingPathArray[i] : Fr.ZERO, - ); - - // Update the contract and note hash trees with the new items being inserted to get the new roots + // Update the note hash trees with the new items being inserted to get the new roots // that will be used by the next iteration of the base rollup circuit, skipping the empty ones - const newContracts = tx.data.combinedData.newContracts.map(cd => cd.hash()); const newNoteHashes = tx.data.combinedData.newNoteHashes.map(x => x.value.toBuffer()); - - await this.db.appendLeaves( - MerkleTreeId.CONTRACT_TREE, - newContracts.map(x => x.toBuffer()), - ); - await this.db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, newNoteHashes); // The read witnesses for a given TX should be generated before the writes of the same TX are applied. @@ -720,7 +687,6 @@ export class SoloBlockBuilder implements BlockBuilder { sortedNullifierIndexes: makeTuple(MAX_NEW_NULLIFIERS_PER_TX, i => sortedNewLeavesIndexes[i]), noteHashSubtreeSiblingPath, nullifierSubtreeSiblingPath, - contractSubtreeSiblingPath, publicDataSiblingPath, }); diff --git a/yarn-project/sequencer-client/src/config.ts b/yarn-project/sequencer-client/src/config.ts index 0c6eed374ae..e0e6a9c701a 100644 --- a/yarn-project/sequencer-client/src/config.ts +++ b/yarn-project/sequencer-client/src/config.ts @@ -44,7 +44,6 @@ export function getConfigEnvVars(): SequencerClientConfig { ROLLUP_CONTRACT_ADDRESS, REGISTRY_CONTRACT_ADDRESS, INBOX_CONTRACT_ADDRESS, - CONTRACT_DEPLOYMENT_EMITTER_ADDRESS, OUTBOX_CONTRACT_ADDRESS, COINBASE, FEE_RECIPIENT, @@ -64,9 +63,6 @@ export function getConfigEnvVars(): SequencerClientConfig { registryAddress: REGISTRY_CONTRACT_ADDRESS ? EthAddress.fromString(REGISTRY_CONTRACT_ADDRESS) : EthAddress.ZERO, inboxAddress: INBOX_CONTRACT_ADDRESS ? EthAddress.fromString(INBOX_CONTRACT_ADDRESS) : EthAddress.ZERO, outboxAddress: OUTBOX_CONTRACT_ADDRESS ? EthAddress.fromString(OUTBOX_CONTRACT_ADDRESS) : EthAddress.ZERO, - contractDeploymentEmitterAddress: CONTRACT_DEPLOYMENT_EMITTER_ADDRESS - ? EthAddress.fromString(CONTRACT_DEPLOYMENT_EMITTER_ADDRESS) - : EthAddress.ZERO, }; return { diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 26a6ea64975..4fb6a11fcb2 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -1,4 +1,4 @@ -import { ExtendedContractData, L2Block } from '@aztec/circuit-types'; +import { L2Block } from '@aztec/circuit-types'; import { L1PublishStats } from '@aztec/circuit-types/stats'; import { createDebugLogger } from '@aztec/foundation/log'; import { InterruptibleSleep } from '@aztec/foundation/sleep'; @@ -54,22 +54,6 @@ export interface L1PublisherTxSender { */ sendProcessTx(encodedData: L1ProcessArgs): Promise; - /** - * Sends a tx to the contract deployment emitter contract with contract deployment data such as bytecode. Returns once the tx has been mined. - * @param l2BlockNum - Number of the L2 block that owns this encrypted logs. - * @param l2BlockHash - The hash of the block corresponding to this data. - * @param partialAddresses - The partial addresses of the deployed contract - * @param publicKeys - The public keys of the deployed contract - * @param newExtendedContractData - Data to publish. - * @returns The hash of the mined tx. - * @remarks Partial addresses, public keys and contract data has to be in the same order. Read more {@link https://docs.aztec.network/concepts/foundation/accounts/keys#addresses-partial-addresses-and-public-keys | here}. - */ - sendEmitContractDeploymentTx( - l2BlockNum: number, - l2BlockHash: Buffer, - newExtendedContractData: ExtendedContractData[], - ): Promise<(string | undefined)[]>; - /** * Returns a tx receipt if the tx has been mined. * @param txHash - Hash of the tx to look for. @@ -111,16 +95,6 @@ export type L1ProcessArgs = { proof: Buffer; }; -/** - * Helper function to filter out undefined items from an array. - * Also asserts the resulting array is of type . - * @param item - An item from an array to check if undefined or not. - * @returns True if the item is not undefined. - */ -function isNotUndefined(item: T | undefined): item is T { - return item !== undefined; -} - /** * Publishes L2 blocks to L1. This implementation does *not* retry a transaction in * the event of network congestion, but should work for local development. @@ -234,49 +208,6 @@ export class L1Publisher implements L2BlockReceiver { return false; } - /** - * Publishes new contract data to L1. - * @param l2BlockNum - The L2 block number that the new contracts were deployed on. - * @param l2BlockHash - The hash of the block corresponding to this data. - * @param contractData - The new contract data to publish. - * @returns True once the tx has been confirmed and is successful, false on revert or interrupt, blocks otherwise. - */ - public async processNewContractData(l2BlockNum: number, l2BlockHash: Buffer, contractData: ExtendedContractData[]) { - let _contractData: ExtendedContractData[] = []; - while (!this.interrupted) { - const arr = _contractData.length ? _contractData : contractData; - const txHashes = await this.sendEmitNewContractDataTx(l2BlockNum, l2BlockHash, arr); - if (!txHashes) { - break; - } - // filter successful txs - _contractData = arr.filter((_, i) => !!txHashes[i]); - - const receipts = await Promise.all( - txHashes.filter(isNotUndefined).map(txHash => this.getTransactionReceipt(txHash)), - ); - if (!receipts?.length) { - break; - } - - // ALL Txs were mined successfully - if (receipts.length === contractData.length && receipts.every(r => r?.status)) { - return true; - } - - this.log( - `Transaction status failed: ${receipts - .filter(r => !r?.status) - .map(r => r?.transactionHash) - .join(',')}`, - ); - await this.sleepOrInterrupted(); - } - - this.log('L2 block data syncing interrupted while processing contract data.'); - return false; - } - /** * Calling `interrupt` will cause any in progress call to `publishRollup` to return `false` asap. * Be warned, the call may return false even if the tx subsequently gets successfully mined. @@ -330,21 +261,6 @@ export class L1Publisher implements L2BlockReceiver { } } - private async sendEmitNewContractDataTx( - l2BlockNum: number, - l2BlockHash: Buffer, - newExtendedContractData: ExtendedContractData[], - ) { - while (!this.interrupted) { - try { - return await this.txSender.sendEmitContractDeploymentTx(l2BlockNum, l2BlockHash, newExtendedContractData); - } catch (err) { - this.log.error(`Error sending contract data to L1`, err); - await this.sleepOrInterrupted(); - } - } - } - private async getTransactionReceipt(txHash: string): Promise { while (!this.interrupted) { try { diff --git a/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts b/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts index cecaa20b453..7c41c469f1f 100644 --- a/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts +++ b/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts @@ -1,8 +1,7 @@ -import { ExtendedContractData, L2Block } from '@aztec/circuit-types'; -import { BLOB_SIZE_IN_BYTES } from '@aztec/circuits.js/constants'; +import { L2Block } from '@aztec/circuit-types'; import { createEthereumChain } from '@aztec/ethereum'; import { createDebugLogger } from '@aztec/foundation/log'; -import { AvailabilityOracleAbi, ContractDeploymentEmitterAbi, RollupAbi } from '@aztec/l1-artifacts'; +import { AvailabilityOracleAbi, RollupAbi } from '@aztec/l1-artifacts'; import { GetContractReturnType, @@ -40,10 +39,6 @@ export class ViemTxSender implements L1PublisherTxSender { typeof RollupAbi, WalletClient >; - private contractDeploymentEmitterContract: GetContractReturnType< - typeof ContractDeploymentEmitterAbi, - WalletClient - >; private log = createDebugLogger('aztec:sequencer:viem-tx-sender'); private publicClient: PublicClient; @@ -74,11 +69,6 @@ export class ViemTxSender implements L1PublisherTxSender { abi: RollupAbi, client: walletClient, }); - this.contractDeploymentEmitterContract = getContract({ - address: getAddress(l1Contracts.contractDeploymentEmitterAddress.toString()), - abi: ContractDeploymentEmitterAbi, - client: walletClient, - }); } async getCurrentArchive(): Promise { @@ -169,46 +159,6 @@ export class ViemTxSender implements L1PublisherTxSender { return hash; } - /** - * Sends a tx to the contract deployment emitter contract with contract deployment data such as bytecode. Returns once the tx has been mined. - * @param l2BlockNum - Number of the L2 block that owns this encrypted logs. - * @param l2BlockHash - The hash of the block corresponding to this data. - * @param newExtendedContractData - Data to publish. - * @returns The hash of the mined tx. - */ - async sendEmitContractDeploymentTx( - l2BlockNum: number, - l2BlockHash: Buffer, - newExtendedContractData: ExtendedContractData[], - ): Promise<(string | undefined)[]> { - const hashes: string[] = []; - for (const extendedContractData of newExtendedContractData) { - const args = [ - BigInt(l2BlockNum), - extendedContractData.contractData.contractAddress.toString() as Hex, - extendedContractData.contractData.portalContractAddress.toString() as Hex, - `0x${l2BlockHash.toString('hex')}`, - extendedContractData.contractClassId.toString(), - extendedContractData.saltedInitializationHash.toString(), - extendedContractData.publicKeyHash.toString(), - `0x${extendedContractData.bytecode.toString('hex')}`, - ] as const; - - const codeSize = extendedContractData.bytecode.length; - this.log(`Bytecode is ${codeSize} bytes and require ${codeSize / BLOB_SIZE_IN_BYTES} blobs`); - - const gas = await this.contractDeploymentEmitterContract.estimateGas.emitContractDeployment(args, { - account: this.account, - }); - const hash = await this.contractDeploymentEmitterContract.write.emitContractDeployment(args, { - gas, - account: this.account, - }); - hashes.push(hash); - } - return hashes; - } - /** * Gets the chain object for the given chain id. * @param chainId - Chain id of the target EVM chain. diff --git a/yarn-project/sequencer-client/src/sequencer/abstract_phase_manager.ts b/yarn-project/sequencer-client/src/sequencer/abstract_phase_manager.ts index 063ba0b88fd..86f39110bcc 100644 --- a/yarn-project/sequencer-client/src/sequencer/abstract_phase_manager.ts +++ b/yarn-project/sequencer-client/src/sequencer/abstract_phase_manager.ts @@ -13,6 +13,7 @@ import { MAX_NEW_NULLIFIERS_PER_CALL, MAX_NON_REVERTIBLE_PUBLIC_DATA_READS_PER_TX, MAX_NON_REVERTIBLE_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, @@ -264,13 +265,22 @@ export abstract class AbstractPhaseManager { if (this.phase === PublicKernelPhase.TAIL) { const { endNonRevertibleData, end } = previousOutput; - const nullifierReadRequestResetHints = await this.hintsBuilder.getNullifierReadRequestResetHints( + const nullifierReadRequestHints = await this.hintsBuilder.getNullifierReadRequestHints( endNonRevertibleData.nullifierReadRequests, end.nullifierReadRequests, endNonRevertibleData.newNullifiers, end.newNullifiers, ); - const inputs = new PublicKernelTailCircuitPrivateInputs(previousKernel, nullifierReadRequestResetHints); + const nullifierNonExistentReadRequestHints = await this.hintsBuilder.getNullifierNonExistentReadRequestHints( + endNonRevertibleData.nullifierNonExistentReadRequests, + endNonRevertibleData.newNullifiers, + end.newNullifiers, + ); + const inputs = new PublicKernelTailCircuitPrivateInputs( + previousKernel, + nullifierReadRequestHints, + nullifierNonExistentReadRequestHints, + ); return this.publicKernel.publicKernelCircuitTail(inputs); } @@ -329,6 +339,11 @@ export abstract class AbstractPhaseManager { ReadRequest.empty(), MAX_NULLIFIER_READ_REQUESTS_PER_CALL, ), + nullifierNonExistentReadRequests: padArrayEnd( + result.nullifierNonExistentReadRequests, + ReadRequest.empty(), + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, + ), contractStorageReads: padArrayEnd( result.contractStorageReads, ContractStorageRead.empty(), diff --git a/yarn-project/sequencer-client/src/sequencer/hints_builder.ts b/yarn-project/sequencer-client/src/sequencer/hints_builder.ts index d7abe9fa0d9..1f5b17c7cf2 100644 --- a/yarn-project/sequencer-client/src/sequencer/hints_builder.ts +++ b/yarn-project/sequencer-client/src/sequencer/hints_builder.ts @@ -3,14 +3,15 @@ import { Fr, MAX_NEW_NULLIFIERS_PER_TX, MAX_NON_REVERTIBLE_NULLIFIERS_PER_TX, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_REVERTIBLE_NULLIFIERS_PER_TX, MembershipWitness, NULLIFIER_TREE_HEIGHT, - NullifierLeafPreimage, ReadRequestContext, SideEffectLinkedToNoteHash, - buildNullifierReadRequestResetHints, + buildNullifierNonExistentReadRequestHints, + buildNullifierReadRequestHints, concatAccumulatedData, mergeAccumulatedData, } from '@aztec/circuits.js'; @@ -20,13 +21,13 @@ import { MerkleTreeOperations } from '@aztec/world-state'; export class HintsBuilder { constructor(private db: MerkleTreeOperations) {} - getNullifierReadRequestResetHints( + getNullifierReadRequestHints( nullifierReadRequestsNonRevertible: Tuple, nullifierReadRequestsRevertible: Tuple, nullifiersNonRevertible: Tuple, nullifiersRevertible: Tuple, ) { - return buildNullifierReadRequestResetHints( + return buildNullifierReadRequestHints( this, mergeAccumulatedData( MAX_NULLIFIER_READ_REQUESTS_PER_TX, @@ -37,19 +38,54 @@ export class HintsBuilder { ); } + getNullifierNonExistentReadRequestHints( + nullifierNonExistentReadRequests: Tuple, + nullifiersNonRevertible: Tuple, + nullifiersRevertible: Tuple, + ) { + const pendingNullifiers = concatAccumulatedData( + MAX_NEW_NULLIFIERS_PER_TX, + nullifiersNonRevertible, + nullifiersRevertible, + ); + return buildNullifierNonExistentReadRequestHints(this, nullifierNonExistentReadRequests, pendingNullifiers); + } + async getNullifierMembershipWitness(nullifier: Fr) { const index = await this.db.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer()); if (index === undefined) { return; } - const siblingPath = await this.db.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, index); + return this.getNullifierMembershipWitnessWithPreimage(index); + } + + async getLowNullifierMembershipWitness(nullifier: Fr) { + const res = await this.db.getPreviousValueIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBigInt()); + if (res === undefined) { + throw new Error(`Cannot find the low leaf for nullifier ${nullifier.toBigInt()}.`); + } + + const { index, alreadyPresent } = res; + if (alreadyPresent) { + throw new Error(`Nullifier ${nullifier.toBigInt()} already exists in the tree.`); + } + + return this.getNullifierMembershipWitnessWithPreimage(index); + } + + private async getNullifierMembershipWitnessWithPreimage(index: bigint) { + const siblingPath = await this.db.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, index); const membershipWitness = new MembershipWitness( NULLIFIER_TREE_HEIGHT, index, siblingPath.toTuple(), ); - const leafPreimage = (await this.db.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index))! as NullifierLeafPreimage; + + const leafPreimage = await this.db.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index); + if (!leafPreimage) { + throw new Error(`Cannot find the leaf preimage at index ${index}.`); + } return { membershipWitness, leafPreimage }; } diff --git a/yarn-project/sequencer-client/src/sequencer/processed_tx.ts b/yarn-project/sequencer-client/src/sequencer/processed_tx.ts index daa2239cdcb..75575c0fbf9 100644 --- a/yarn-project/sequencer-client/src/sequencer/processed_tx.ts +++ b/yarn-project/sequencer-client/src/sequencer/processed_tx.ts @@ -1,17 +1,7 @@ -import { - ContractData, - ExtendedContractData, - PublicDataWrite, - SimulationError, - Tx, - TxEffect, - TxHash, - TxL2Logs, -} from '@aztec/circuit-types'; +import { PublicDataWrite, SimulationError, Tx, TxEffect, TxHash, TxL2Logs } from '@aztec/circuit-types'; import { Fr, Header, - MAX_NEW_CONTRACTS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, @@ -29,7 +19,7 @@ import { Tuple, fromFieldsTuple } from '@aztec/foundation/serialize'; * Represents a tx that has been processed by the sequencer public processor, * so its kernel circuit public inputs are filled in. */ -export type ProcessedTx = Pick & { +export type ProcessedTx = Pick & { /** * Output of the public kernel circuit for this tx. */ @@ -153,7 +143,6 @@ export function makeProcessedTx( proof: previousProof, encryptedLogs: revertReason ? new TxL2Logs([]) : tx.encryptedLogs, unencryptedLogs: revertReason ? new TxL2Logs([]) : tx.unencryptedLogs, - newContracts: revertReason ? [ExtendedContractData.empty()] : tx.newContracts, isEmpty: false, revertReason, }; @@ -177,7 +166,6 @@ export function makeEmptyProcessedTx(header: Header, chainId: Fr, version: Fr): unencryptedLogs: new TxL2Logs([]), data: emptyKernelOutput, proof: emptyProof, - newContracts: [ExtendedContractData.empty()], isEmpty: true, revertReason: undefined, }; @@ -195,10 +183,6 @@ export function toTxEffect(tx: ProcessedTx): TxEffect { PublicDataWrite, typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX >, - tx.data.combinedData.newContracts.map(cd => cd.hash()) as Tuple, - tx.data.combinedData.newContracts.map( - cd => new ContractData(cd.contractAddress, cd.portalContractAddress), - ) as Tuple, tx.encryptedLogs || new TxL2Logs([]), tx.unencryptedLogs || new TxL2Logs([]), ); diff --git a/yarn-project/sequencer-client/src/sequencer/public_processor.test.ts b/yarn-project/sequencer-client/src/sequencer/public_processor.test.ts index 17e639a7000..1e98b368f0e 100644 --- a/yarn-project/sequencer-client/src/sequencer/public_processor.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/public_processor.test.ts @@ -1,5 +1,4 @@ import { - ExtendedContractData, FunctionCall, FunctionL2Logs, PublicDataWrite, @@ -135,7 +134,6 @@ describe('public_processor', () => { proof: tx.proof, encryptedLogs: tx.encryptedLogs, unencryptedLogs: tx.unencryptedLogs, - newContracts: tx.newContracts, isEmpty: false, revertReason: undefined, }; @@ -213,9 +211,7 @@ describe('public_processor', () => { ); kernelOutput.end.unencryptedLogsHash = [Fr.ZERO, Fr.ZERO]; - const tx = new Tx(kernelOutput, proof, TxL2Logs.empty(), TxL2Logs.empty(), publicCallRequests, [ - ExtendedContractData.random(), - ]); + const tx = new Tx(kernelOutput, proof, TxL2Logs.empty(), TxL2Logs.empty(), publicCallRequests); tx.data.needsSetup = false; tx.data.needsTeardown = false; @@ -261,14 +257,7 @@ describe('public_processor', () => { kernelOutput.needsSetup = false; kernelOutput.needsTeardown = false; - const tx = new Tx( - kernelOutput, - proof, - TxL2Logs.empty(), - TxL2Logs.empty(), - [callRequest], - [ExtendedContractData.random()], - ); + const tx = new Tx(kernelOutput, proof, TxL2Logs.empty(), TxL2Logs.empty(), [callRequest]); const publicExecutionResult = PublicExecutionResultBuilder.fromPublicCallRequest({ request: callRequest, @@ -320,7 +309,6 @@ describe('public_processor', () => { TxL2Logs.empty(), // reverse because `enqueuedPublicFunctions` expects the last element to be the front of the queue callRequests.slice().reverse(), - [ExtendedContractData.random()], ); const contractSlotA = fr(0x100); @@ -403,8 +391,6 @@ describe('public_processor', () => { expect(txEffect.publicDataWrites[1]).toEqual( new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotC), fr(0x201)), ); - expect(txEffect.contractData[0].isEmpty()).toBe(true); - expect(txEffect.contractLeaves[0].isZero()).toBe(true); expect(txEffect.encryptedLogs.getTotalLogCount()).toBe(0); expect(txEffect.unencryptedLogs.getTotalLogCount()).toBe(0); }); @@ -437,7 +423,6 @@ describe('public_processor', () => { TxL2Logs.empty(), // reverse because `enqueuedPublicFunctions` expects the last element to be the front of the queue callRequests.slice().reverse(), - [ExtendedContractData.random()], ); // const baseContractAddress = makeAztecAddress(30); @@ -570,7 +555,7 @@ class PublicExecutionResultBuilder { revertReason?: SimulationError; }) { const builder = new PublicExecutionResultBuilder({ - callContext: new CallContext(from, tx.to, EthAddress.ZERO, tx.functionData.selector, false, false, false, 0), + callContext: new CallContext(from, tx.to, EthAddress.ZERO, tx.functionData.selector, false, false, 0), contractAddress: tx.to, functionData: tx.functionData, args: tx.args, @@ -612,6 +597,7 @@ class PublicExecutionResultBuilder { execution: this._execution, nestedExecutions: this._nestedExecutions, nullifierReadRequests: [], + nullifierNonExistentReadRequests: [], contractStorageUpdateRequests: this._contractStorageUpdateRequests, returnValues: this._returnValues, newNoteHashes: [], diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index 5ee994cd26d..831ddb4c2fb 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -1,13 +1,4 @@ -import { - ExtendedContractData, - L1ToL2MessageSource, - L2Block, - L2BlockSource, - MerkleTreeId, - Tx, - TxHash, - mockTx, -} from '@aztec/circuit-types'; +import { L1ToL2MessageSource, L2Block, L2BlockSource, MerkleTreeId, Tx, TxHash, mockTx } from '@aztec/circuit-types'; import { AztecAddress, EthAddress, @@ -222,45 +213,6 @@ describe('sequencer', () => { expect(publisher.processL2Block).not.toHaveBeenCalled(); }); - - it('publishes contract data', async () => { - const txWithContract = mockTx(0x10000); - (txWithContract.newContracts as Array) = [ExtendedContractData.random()]; - txWithContract.data.constants.txContext.chainId = chainId; - - const txWithEmptyContract = mockTx(0x20000); - (txWithEmptyContract.newContracts as Array) = [ExtendedContractData.empty()]; - txWithEmptyContract.data.constants.txContext.chainId = chainId; - - const block = L2Block.random(lastBlockNumber + 1); - const proof = makeEmptyProof(); - - p2p.getTxs.mockResolvedValueOnce([txWithContract, txWithEmptyContract]); - blockBuilder.buildL2Block.mockResolvedValueOnce([block, proof]); - publisher.processL2Block.mockResolvedValueOnce(true); - publisher.processNewContractData.mockResolvedValueOnce(true); - globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce( - new GlobalVariables(chainId, version, new Fr(lastBlockNumber + 1), Fr.ZERO, coinbase, feeRecipient), - ); - - await sequencer.initialSync(); - await sequencer.work(); - - // check that the block was built with both transactions - expect(blockBuilder.buildL2Block).toHaveBeenCalledWith( - expect.anything(), - expect.arrayContaining([ - expect.objectContaining({ hash: txWithContract.getTxHash() }), - expect.objectContaining({ hash: txWithEmptyContract.getTxHash() }), - ]), - expect.any(Array), - ); - - // check that the empty contract did not get published - expect(publisher.processNewContractData).toHaveBeenCalledWith(block.number, block.body.getTxsEffectsHash(), [ - txWithContract.newContracts[0], - ]); - }); }); class TestSubject extends Sequencer { diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 47ce5804eb5..39f9b12e058 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -227,10 +227,6 @@ export class Sequencer { await assertBlockHeight(); - await this.publishExtendedContractData(processedValidTxs, block); - - await assertBlockHeight(); - await this.publishL2Block(block); this.log.info(`Submitted rollup block ${block.number} with ${processedValidTxs.length} transactions`); } catch (err) { @@ -239,37 +235,6 @@ export class Sequencer { } } - /** - * Gets new extended contract data from the txs and publishes it on chain. - * @param validTxs - The set of real transactions being published as part of the block. - * @param block - The L2Block to be published. - */ - protected async publishExtendedContractData(validTxs: ProcessedTx[], block: L2Block) { - // Publishes contract data for txs to the network and awaits the tx to be mined - this.state = SequencerState.PUBLISHING_CONTRACT_DATA; - const newContracts = validTxs.flatMap(tx => tx.newContracts).filter(cd => !cd.isEmpty()); - - if (newContracts.length === 0) { - this.log.debug(`No new contracts to publish in block ${block.number}`); - return; - } - - const txsEffectsHash = block.body.getTxsEffectsHash(); - this.log.info(`Publishing ${newContracts.length} contracts in block ${block.number}`); - - const publishedContractData = await this.publisher.processNewContractData( - block.number, - txsEffectsHash, - newContracts, - ); - - if (publishedContractData) { - this.log(`Successfully published new contract data for block ${block.number}`); - } else if (!publishedContractData && newContracts.length) { - this.log(`Failed to publish new contract data for block ${block.number}`); - } - } - /** * Publishes the L2Block to the rollup contract. * @param block - The L2Block to be published. diff --git a/yarn-project/sequencer-client/src/simulator/public_executor.ts b/yarn-project/sequencer-client/src/simulator/public_executor.ts index 3c7c7bdcbf1..9af59f7729b 100644 --- a/yarn-project/sequencer-client/src/simulator/public_executor.ts +++ b/yarn-project/sequencer-client/src/simulator/public_executor.ts @@ -45,16 +45,6 @@ export class ContractsDataSourcePublicDB implements PublicContractsDB { * @param tx - The transaction to add contracts from. */ public addNewContracts(tx: Tx): Promise { - for (const contract of tx.newContracts) { - const contractAddress = contract.contractData.contractAddress; - - if (contractAddress.isZero()) { - continue; - } - - this.cache.set(contractAddress.toString(), contract); - } - // Extract contract class and instance data from logs and add to cache for this block const logs = tx.unencryptedLogs.unrollLogs().map(UnencryptedL2Log.fromBuffer); ContractClassRegisteredEvent.fromLogs(logs, ClassRegistererAddress).forEach(e => { @@ -76,16 +66,6 @@ export class ContractsDataSourcePublicDB implements PublicContractsDB { * @param tx - The tx's contracts to be removed */ public removeNewContracts(tx: Tx): Promise { - for (const contract of tx.newContracts) { - const contractAddress = contract.contractData.contractAddress; - - if (contractAddress.isZero()) { - continue; - } - - this.cache.delete(contractAddress.toString()); - } - // TODO(@spalladino): Can this inadvertently delete a valid contract added by another tx? // Let's say we have two txs adding the same contract on the same block. If the 2nd one reverts, // wouldn't that accidentally remove the contract added on the first one? diff --git a/yarn-project/simulator/src/acvm/acvm.ts b/yarn-project/simulator/src/acvm/acvm.ts index 178ccbee21d..ffa53b6ad05 100644 --- a/yarn-project/simulator/src/acvm/acvm.ts +++ b/yarn-project/simulator/src/acvm/acvm.ts @@ -110,7 +110,7 @@ export async function acvm( } else { typedError = new Error(`Error in oracle callback ${err}`); } - logger.error(`Error in oracle callback ${name}`); + logger.error(`Error in oracle callback ${name}: ${typedError.message}`); throw typedError; } }, diff --git a/yarn-project/simulator/src/acvm/serialize.ts b/yarn-project/simulator/src/acvm/serialize.ts index 1ddcf1ea98d..c35f16545b1 100644 --- a/yarn-project/simulator/src/acvm/serialize.ts +++ b/yarn-project/simulator/src/acvm/serialize.ts @@ -1,4 +1,4 @@ -import { PublicCallRequest } from '@aztec/circuits.js'; +import { ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH, PublicCallRequest } from '@aztec/circuits.js'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; @@ -53,12 +53,18 @@ export function toACVMField( * TODO(#4380): Nuke this and replace it with PublicCallRequest.toFields() */ export function toAcvmEnqueuePublicFunctionResult(item: PublicCallRequest): ACVMField[] { - return [ + const fields = [ item.contractAddress.toField(), ...item.functionData.toFields(), ...item.callContext.toFields(), item.getArgsHash(), - ].map(toACVMField); + ]; + if (fields.length !== ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH) { + throw new Error( + `Invalid length for EnqueuePublicFunctionResult (got ${fields.length} expected ${ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH})`, + ); + } + return fields.map(toACVMField); } /** diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index f74a9356371..2f57c0ff514 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -24,7 +24,7 @@ function getAvmTestContractBytecode(functionName: string): Buffer { const artifact = AvmTestContractArtifact.functions.find(f => f.name === functionName)!; assert( !!artifact?.bytecode, - `No bytecode found for function ${functionName}. Try re-running bootstraph.sh on the repository root.`, + `No bytecode found for function ${functionName}. Try re-running bootstrap.sh on the repository root.`, ); return Buffer.from(artifact.bytecode, 'base64'); } @@ -240,8 +240,9 @@ describe('AVM simulator', () => { const expectedFields = [new Fr(10), new Fr(20), new Fr(30)]; const expectedString = 'Hello, world!'.split('').map(c => new Fr(c.charCodeAt(0))); - // FIXME: Try this once Brillig codegen produces uniform bit sizes for LT - // const expectedCompressedString = Buffer.from('Hello, world!'); + const expectedCompressedString = Buffer.from( + '\0A long time ago, in a galaxy fa' + '\0r far away...\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', + ); expect(context.persistableState.flush().newLogs).toEqual([ new UnencryptedL2Log( context.environment.address, @@ -253,11 +254,7 @@ describe('AVM simulator', () => { new EventSelector(8), Buffer.concat(expectedString.map(f => f.toBuffer())), ), - // new UnencryptedL2Log( - // context.environment.address, - // new EventSelector(10), - // expectedCompressedString, - // ), + new UnencryptedL2Log(context.environment.address, new EventSelector(10), expectedCompressedString), ]); }); @@ -424,6 +421,63 @@ describe('AVM simulator', () => { expect(results.reverted).toBe(false); expect(results.output).toEqual([new Fr(3)]); }); + + it(`Should execute contract function that makes a nested static call`, async () => { + const calldata: Fr[] = [new Fr(1), new Fr(2)]; + const callBytecode = getAvmTestContractBytecode('avm_raw_nested_static_call_to_add'); + const addBytecode = getAvmTestContractBytecode('avm_addArgsReturn'); + const context = initContext({ env: initExecutionEnvironment({ calldata }) }); + jest + .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') + .mockReturnValueOnce(Promise.resolve(addBytecode)); + + const results = await new AvmSimulator(context).executeBytecode(callBytecode); + + expect(results.reverted).toBe(false); + expect(results.output).toEqual([/*result=*/ new Fr(3), /*success=*/ new Fr(1)]); + }); + + it(`Should execute contract function that makes a nested static call which modifies storage`, async () => { + const callBytecode = getAvmTestContractBytecode('avm_raw_nested_static_call_to_set_admin'); + const nestedBytecode = getAvmTestContractBytecode('avm_setAdmin'); + const context = initContext(); + jest + .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') + .mockReturnValueOnce(Promise.resolve(nestedBytecode)); + + const results = await new AvmSimulator(context).executeBytecode(callBytecode); + + expect(results.reverted).toBe(false); // The outer call should not revert. + expect(results.output).toEqual([new Fr(0)]); // The inner call should have reverted. + }); + + it(`Should execute contract function that makes a nested static call (old interface)`, async () => { + const calldata: Fr[] = [new Fr(1), new Fr(2)]; + const callBytecode = getAvmTestContractBytecode('avm_nested_static_call_to_add'); + const addBytecode = getAvmTestContractBytecode('avm_addArgsReturn'); + const context = initContext({ env: initExecutionEnvironment({ calldata }) }); + jest + .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') + .mockReturnValueOnce(Promise.resolve(addBytecode)); + + const results = await new AvmSimulator(context).executeBytecode(callBytecode); + + expect(results.reverted).toBe(false); + expect(results.output).toEqual([/*result=*/ new Fr(3)]); + }); + + it(`Should execute contract function that makes a nested static call which modifies storage (old interface)`, async () => { + const callBytecode = getAvmTestContractBytecode('avm_nested_static_call_to_set_admin'); + const nestedBytecode = getAvmTestContractBytecode('avm_setAdmin'); + const context = initContext(); + jest + .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') + .mockReturnValueOnce(Promise.resolve(nestedBytecode)); + + const results = await new AvmSimulator(context).executeBytecode(callBytecode); + + expect(results.reverted).toBe(true); // The outer call should revert. + }); }); describe('Storage accesses', () => { diff --git a/yarn-project/simulator/src/avm/temporary_executor_migration.ts b/yarn-project/simulator/src/avm/temporary_executor_migration.ts index 999f97fbb69..f33205ae850 100644 --- a/yarn-project/simulator/src/avm/temporary_executor_migration.ts +++ b/yarn-project/simulator/src/avm/temporary_executor_migration.ts @@ -94,6 +94,7 @@ export function temporaryConvertAvmResults( // Disabled. const nestedExecutions: PublicExecutionResult[] = []; const nullifierReadRequests: ReadRequest[] = []; + const nullifierNonExistentReadRequests: ReadRequest[] = []; const newNullifiers: SideEffectLinkedToNoteHash[] = []; const unencryptedLogs = FunctionL2Logs.empty(); const newL2ToL1Messages = newWorldState.newL1Messages.map(() => L2ToL1Message.empty()); @@ -101,6 +102,7 @@ export function temporaryConvertAvmResults( return { execution, nullifierReadRequests, + nullifierNonExistentReadRequests, newNoteHashes, newL2ToL1Messages, newNullifiers, diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index ccefed30157..c0f90ab2758 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -10,7 +10,6 @@ import { } from '@aztec/circuit-types'; import { CallContext, - ContractDeploymentData, FunctionData, FunctionSelector, Header, @@ -89,8 +88,6 @@ export class ClientExecutionContext extends ViewDataOracle { * @returns The initial witness. */ public getInitialWitness(abi: FunctionAbi) { - const contractDeploymentData = this.txContext.contractDeploymentData; - const argumentsSize = countArgumentsSize(abi); const args = this.packedArgsCache.unpack(this.argsHash); @@ -102,7 +99,6 @@ export class ClientExecutionContext extends ViewDataOracle { const fields = [ ...this.callContext.toFields(), ...this.historicalHeader.toFields(), - ...contractDeploymentData.toFields(), this.txContext.chainId, this.txContext.version, @@ -348,14 +344,7 @@ export class ClientExecutionContext extends ViewDataOracle { const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector); const targetFunctionData = FunctionData.fromAbi(targetArtifact); - const derivedTxContext = new TxContext( - false, - false, - false, - ContractDeploymentData.empty(), - this.txContext.chainId, - this.txContext.version, - ); + const derivedTxContext = new TxContext(false, false, this.txContext.chainId, this.txContext.version); const derivedCallContext = await this.deriveCallContext( targetContractAddress, @@ -470,7 +459,6 @@ export class ClientExecutionContext extends ViewDataOracle { FunctionSelector.fromNameAndParameters(targetArtifact.name, targetArtifact.parameters), isDelegateCall, isStaticCall, - false, startSideEffectCounter, ); } diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index e41a9aac433..7eab890fad0 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -3,7 +3,6 @@ import { AppendOnlyTreeSnapshot, CallContext, CompleteAddress, - ContractDeploymentData, FunctionData, Header, L1_TO_L2_MSG_TREE_HEIGHT, @@ -20,7 +19,7 @@ import { sideEffectArrayToValueArray, } from '@aztec/circuits.js'; import { computeCommitmentNonce, computeMessageSecretHash, computeVarArgsHash } from '@aztec/circuits.js/hash'; -import { makeContractDeploymentData, makeHeader } from '@aztec/circuits.js/testing'; +import { makeHeader } from '@aztec/circuits.js/testing'; import { FunctionArtifact, FunctionSelector, @@ -86,12 +85,10 @@ describe('Private Execution test suite', () => { let trees: { [name: keyof typeof treeHeights]: AppendOnlyTree } = {}; const txContextFields: FieldsOf = { - isContractDeploymentTx: false, isFeePaymentTx: false, isRebatePaymentTx: false, chainId: new Fr(10), version: new Fr(20), - contractDeploymentData: ContractDeploymentData.empty(), }; const runSimulator = ({ @@ -154,7 +151,6 @@ describe('Private Execution test suite', () => { new PartialStateReference( name === 'noteHash' ? newSnap : header.state.partial.noteHashTree, header.state.partial.nullifierTree, - header.state.partial.contractTree, header.state.partial.publicDataTree, ), ), @@ -222,13 +218,10 @@ describe('Private Execution test suite', () => { describe('empty constructor', () => { it('should run the empty constructor', async () => { const artifact = getFunctionArtifact(TestContractArtifact, 'constructor'); - const contractDeploymentData = makeContractDeploymentData(100); - const txContext = { isContractDeploymentTx: true, contractDeploymentData }; - const result = await runSimulator({ artifact, txContext }); + const result = await runSimulator({ artifact }); const emptyCommitments = new Array(MAX_NEW_NOTE_HASHES_PER_CALL).fill(Fr.ZERO); expect(sideEffectArrayToValueArray(result.callStackItem.publicInputs.newNoteHashes)).toEqual(emptyCommitments); - expect(result.callStackItem.publicInputs.contractDeploymentData).toEqual(contractDeploymentData); }); it('emits a field as an unencrypted log', async () => { @@ -795,7 +788,8 @@ describe('Private Execution test suite', () => { describe('enqueued calls', () => { it.each([false, true])('parent should enqueue call to child (internal %p)', async isInternal => { const parentArtifact = getFunctionArtifact(ParentContractArtifact, 'enqueueCallToChild'); - const childContractArtifact = ParentContractArtifact.functions[0]; + const childContractArtifact = ChildContractArtifact.functions.find(fn => fn.name === 'pubSetValue')!; + expect(childContractArtifact).toBeDefined(); const childAddress = AztecAddress.random(); const childPortalContractAddress = EthAddress.random(); const childSelector = FunctionSelector.fromNameAndParameters( @@ -828,7 +822,6 @@ describe('Private Execution test suite', () => { storageContractAddress: childAddress, portalContractAddress: childPortalContractAddress, functionSelector: childSelector, - isContractDeployment: false, isDelegateCall: false, isStaticCall: false, startSideEffectCounter: 1, @@ -838,7 +831,6 @@ describe('Private Execution test suite', () => { storageContractAddress: parentAddress, portalContractAddress: EthAddress.ZERO, functionSelector: FunctionSelector.fromNameAndParameters(parentArtifact.name, parentArtifact.parameters), - isContractDeployment: false, isDelegateCall: false, isStaticCall: false, startSideEffectCounter: 1, diff --git a/yarn-project/simulator/src/client/simulator.ts b/yarn-project/simulator/src/client/simulator.ts index 4d5e89e8647..c98a4a6cf5c 100644 --- a/yarn-project/simulator/src/client/simulator.ts +++ b/yarn-project/simulator/src/client/simulator.ts @@ -92,10 +92,9 @@ export class AcirSimulator { FunctionSelector.fromNameAndParameters(entryPointArtifact.name, entryPointArtifact.parameters), false, false, - request.functionData.isConstructor, // TODO: when contract deployment is done in-app, we should only reserve one counter for the tx hash // 2 counters are reserved for tx hash and contract deployment nullifier - request.txContext.isContractDeploymentTx ? 2 : 1, + 1, ); const context = new ClientExecutionContext( contractAddress, diff --git a/yarn-project/simulator/src/public/avm_executor.test.ts b/yarn-project/simulator/src/public/avm_executor.test.ts index aaff6232443..5de5e968c7c 100644 --- a/yarn-project/simulator/src/public/avm_executor.test.ts +++ b/yarn-project/simulator/src/public/avm_executor.test.ts @@ -20,7 +20,6 @@ describe('AVM WitGen and Proof Generation', () => { storageContractAddress: AztecAddress.random(), portalContractAddress: EthAddress.random(), functionSelector: FunctionSelector.empty(), - isContractDeployment: false, isDelegateCall: false, isStaticCall: false, startSideEffectCounter: 0, diff --git a/yarn-project/simulator/src/public/execution.ts b/yarn-project/simulator/src/public/execution.ts index cb9c42df332..31d306f3952 100644 --- a/yarn-project/simulator/src/public/execution.ts +++ b/yarn-project/simulator/src/public/execution.ts @@ -30,6 +30,8 @@ export interface PublicExecutionResult { newNullifiers: SideEffectLinkedToNoteHash[]; /** The nullifier read requests emitted in this call. */ nullifierReadRequests: ReadRequest[]; + /** The nullifier non existent read requests emitted in this call. */ + nullifierNonExistentReadRequests: ReadRequest[]; /** The contract storage reads performed by the function. */ contractStorageReads: ContractStorageRead[]; /** The contract storage update requests performed by the function. */ diff --git a/yarn-project/simulator/src/public/executor.ts b/yarn-project/simulator/src/public/executor.ts index 5e307e3a45f..a513baf77e9 100644 --- a/yarn-project/simulator/src/public/executor.ts +++ b/yarn-project/simulator/src/public/executor.ts @@ -85,6 +85,7 @@ export async function executePublicFunction( newL2ToL1Messages: [], newNullifiers: [], nullifierReadRequests: [], + nullifierNonExistentReadRequests: [], contractStorageReads: [], contractStorageUpdateRequests: [], nestedExecutions: [], @@ -102,12 +103,14 @@ export async function executePublicFunction( const { returnValues, nullifierReadRequests: nullifierReadRequestsPadded, + nullifierNonExistentReadRequests: nullifierNonExistentReadRequestsPadded, newL2ToL1Msgs, newNoteHashes: newNoteHashesPadded, newNullifiers: newNullifiersPadded, } = PublicCircuitPublicInputs.fromFields(returnWitness); const nullifierReadRequests = nullifierReadRequestsPadded.filter(v => !v.isEmpty()); + const nullifierNonExistentReadRequests = nullifierNonExistentReadRequestsPadded.filter(v => !v.isEmpty()); const newL2ToL1Messages = newL2ToL1Msgs.filter(v => !v.isEmpty()); const newNoteHashes = newNoteHashesPadded.filter(v => !v.isEmpty()); const newNullifiers = newNullifiersPadded.filter(v => !v.isEmpty()); @@ -134,6 +137,7 @@ export async function executePublicFunction( newL2ToL1Messages, newNullifiers, nullifierReadRequests, + nullifierNonExistentReadRequests, contractStorageReads, contractStorageUpdateRequests, returnValues, diff --git a/yarn-project/simulator/src/public/index.test.ts b/yarn-project/simulator/src/public/index.test.ts index 098c72dc096..a4212f61a07 100644 --- a/yarn-project/simulator/src/public/index.test.ts +++ b/yarn-project/simulator/src/public/index.test.ts @@ -108,7 +108,6 @@ describe('ACIR public execution simulator', () => { storageContractAddress: contractAddress, portalContractAddress: EthAddress.random(), functionSelector: FunctionSelector.empty(), - isContractDeployment: false, isDelegateCall: false, isStaticCall: false, startSideEffectCounter: 0, @@ -182,7 +181,6 @@ describe('ACIR public execution simulator', () => { storageContractAddress: contractAddress, portalContractAddress: EthAddress.random(), functionSelector: FunctionSelector.empty(), - isContractDeployment: false, isDelegateCall: false, isStaticCall: false, startSideEffectCounter: 0, @@ -272,7 +270,6 @@ describe('ACIR public execution simulator', () => { storageContractAddress: parentContractAddress, portalContractAddress: EthAddress.random(), functionSelector: FunctionSelector.empty(), - isContractDeployment: false, isDelegateCall: false, isStaticCall: false, startSideEffectCounter: 0, @@ -352,7 +349,6 @@ describe('ACIR public execution simulator', () => { storageContractAddress: contractAddress, portalContractAddress: EthAddress.random(), functionSelector: FunctionSelector.empty(), - isContractDeployment: false, isDelegateCall: false, isStaticCall: false, startSideEffectCounter: 0, @@ -387,7 +383,6 @@ describe('ACIR public execution simulator', () => { storageContractAddress: contractAddress, portalContractAddress, functionSelector: FunctionSelector.empty(), - isContractDeployment: false, isDelegateCall: false, isStaticCall: false, startSideEffectCounter: 0, @@ -418,7 +413,6 @@ describe('ACIR public execution simulator', () => { storageContractAddress: contractAddress, portalContractAddress: EthAddress.random(), functionSelector: FunctionSelector.empty(), - isContractDeployment: false, isDelegateCall: false, isStaticCall: false, startSideEffectCounter: 0, @@ -477,7 +471,6 @@ describe('ACIR public execution simulator', () => { storageContractAddress: contractAddress, portalContractAddress: crossChainMsgSender ?? preimage.sender.sender, functionSelector: FunctionSelector.empty(), - isContractDeployment: false, isDelegateCall: false, isStaticCall: false, startSideEffectCounter: 0, @@ -677,7 +670,6 @@ describe('ACIR public execution simulator', () => { storageContractAddress: AztecAddress.random(), portalContractAddress: EthAddress.ZERO, functionSelector: FunctionSelector.empty(), - isContractDeployment: false, isDelegateCall: false, isStaticCall: false, startSideEffectCounter: 0, @@ -761,7 +753,6 @@ describe('ACIR public execution simulator', () => { storageContractAddress: AztecAddress.random(), portalContractAddress: EthAddress.ZERO, functionSelector: FunctionSelector.empty(), - isContractDeployment: false, isDelegateCall: false, isStaticCall: false, startSideEffectCounter: 0, diff --git a/yarn-project/simulator/src/public/public_execution_context.ts b/yarn-project/simulator/src/public/public_execution_context.ts index 597b0456358..8d332e8edb7 100644 --- a/yarn-project/simulator/src/public/public_execution_context.ts +++ b/yarn-project/simulator/src/public/public_execution_context.ts @@ -186,7 +186,6 @@ export class PublicExecutionContext extends TypedOracle { storageContractAddress: isDelegateCall ? this.execution.contractAddress : targetContractAddress, portalContractAddress: portalAddress, functionSelector, - isContractDeployment: false, isDelegateCall, isStaticCall, startSideEffectCounter: 0, // TODO use counters in public execution diff --git a/yarn-project/types/src/abi/contract_artifact.ts b/yarn-project/types/src/abi/contract_artifact.ts index 8faf80a682b..4096888503c 100644 --- a/yarn-project/types/src/abi/contract_artifact.ts +++ b/yarn-project/types/src/abi/contract_artifact.ts @@ -7,7 +7,13 @@ import { FunctionType, } from '@aztec/foundation/abi'; -import { NoirCompiledContract } from '../noir/index.js'; +import { + AZTEC_INTERNAL_ATTRIBUTE, + AZTEC_PRIVATE_ATTRIBUTE, + AZTEC_PUBLIC_ATTRIBUTE, + AZTEC_PUBLIC_VM_ATTRIBUTE, + NoirCompiledContract, +} from '../noir/index.js'; import { mockVerificationKey } from './mocked_keys.js'; /** @@ -98,8 +104,13 @@ type NoirCompiledContractFunction = NoirCompiledContract['functions'][number]; * @returns Function artifact. */ function generateFunctionArtifact(fn: NoirCompiledContractFunction): FunctionArtifact { - const functionType = fn.function_type.toLowerCase() as FunctionType; - const isInternal = fn.is_internal; + if (fn.custom_attributes === undefined) { + throw new Error( + `No custom attributes found for contract function ${fn.name}. Try rebuilding the contract with the latest nargo version.`, + ); + } + const functionType = getFunctionType(fn); + const isInternal = fn.custom_attributes.includes(AZTEC_INTERNAL_ATTRIBUTE); // If the function is not unconstrained, the first item is inputs or CallContext which we should omit let parameters = fn.abi.parameters.map(generateFunctionParameter); @@ -125,6 +136,22 @@ function generateFunctionArtifact(fn: NoirCompiledContractFunction): FunctionArt }; } +function getFunctionType(fn: NoirCompiledContractFunction): FunctionType { + if (fn.custom_attributes.includes(AZTEC_PRIVATE_ATTRIBUTE)) { + return FunctionType.SECRET; + } else if ( + fn.custom_attributes.includes(AZTEC_PUBLIC_ATTRIBUTE) || + fn.custom_attributes.includes(AZTEC_PUBLIC_VM_ATTRIBUTE) + ) { + return FunctionType.OPEN; + } else if (fn.is_unconstrained) { + return FunctionType.UNCONSTRAINED; + } else { + // Default to a private function (see simple_macro_example_expanded for an example of this behavior) + return FunctionType.SECRET; + } +} + /** * Returns true if the first parameter is kernel function inputs. * diff --git a/yarn-project/types/src/noir/index.ts b/yarn-project/types/src/noir/index.ts index 65d7c88cb29..097129d74fb 100644 --- a/yarn-project/types/src/noir/index.ts +++ b/yarn-project/types/src/noir/index.ts @@ -7,8 +7,11 @@ import { EventAbi, } from '@aztec/foundation/abi'; -/** The Aztec.nr function types. */ -type NoirFunctionType = 'Open' | 'Secret' | 'Unconstrained'; +export const AZTEC_PRIVATE_ATTRIBUTE = 'aztec(private)'; +export const AZTEC_PUBLIC_ATTRIBUTE = 'aztec(public)'; +export const AZTEC_PUBLIC_VM_ATTRIBUTE = 'aztec(public-vm)'; +export const AZTEC_INTERNAL_ATTRIBUTE = 'aztec(internal)'; +export const AZTEC_INITIALIZER_ATTRIBUTE = 'aztec(initializer)'; /** The witness indices of the parameters. */ type ParamWitnessIndices = { /** Start */ start: number; /** End */ end: number }; @@ -40,10 +43,10 @@ export interface NoirFunctionAbi { export interface NoirFunctionEntry { /** The name of the function. */ name: string; - /** The type of the function. */ - function_type: NoirFunctionType; - /** Whether the function is internal. */ - is_internal: boolean; + /** Whether the function is unconstrained. */ + is_unconstrained: boolean; + /** Custom attributes attached to function */ + custom_attributes: string[]; /** The ABI of the function. */ abi: NoirFunctionAbi; /** The bytecode of the function in base64. */ diff --git a/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.test.ts b/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.test.ts index 3e6866bfd6d..86923600b4d 100644 --- a/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.test.ts +++ b/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.test.ts @@ -1,5 +1,4 @@ import { L2Block, L2BlockSource, MerkleTreeId, SiblingPath } from '@aztec/circuit-types'; -import { Fr } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { sleep } from '@aztec/foundation/sleep'; import { AztecKVStore } from '@aztec/kv-store'; @@ -22,19 +21,6 @@ const consumeNextBlocks = () => { return Promise.resolve(blocks); }; -const getMockBlock = (blockNumber: number, newContractsCommitments?: Buffer[]) => { - const block = L2Block.random(blockNumber); - - if (newContractsCommitments) { - for (let i = 0; i < newContractsCommitments.length; i++) { - // Assuming one new contract per tx - block.body.txEffects[i].contractLeaves = [Fr.fromBuffer(newContractsCommitments[i])]; - } - } - - return block; -}; - const log = createDebugLogger('aztec:server_world_state_synchronizer_test'); describe('server_world_state_synchronizer', () => { @@ -46,7 +32,7 @@ describe('server_world_state_synchronizer', () => { const merkleTreeDb = mock({ getTreeInfo: jest.fn(() => - Promise.resolve({ depth: 8, treeId: MerkleTreeId.CONTRACT_TREE, root: Buffer.alloc(32, 0), size: 0n }), + Promise.resolve({ depth: 8, treeId: MerkleTreeId.NOTE_HASH_TREE, root: Buffer.alloc(32, 0), size: 0n }), ), getSiblingPath: jest.fn(() => { const pedersen: Pedersen = new Pedersen(); @@ -64,7 +50,7 @@ describe('server_world_state_synchronizer', () => { // create the initial blocks nextBlocks = Array(LATEST_BLOCK_NUMBER) .fill(0) - .map((_, index: number) => getMockBlock(index + 1)); + .map((_, index: number) => L2Block.random(index + 1)); // start the sync process and await it await server.start().catch(err => log.error('Sync not completed: ', err)); @@ -82,7 +68,7 @@ describe('server_world_state_synchronizer', () => { // create the initial blocks nextBlocks = Array(count) .fill(0) - .map((_, index: number) => getMockBlock(LATEST_BLOCK_NUMBER + index + 1)); + .map((_, index: number) => L2Block.random(LATEST_BLOCK_NUMBER + index + 1)); rollupSource.getBlockNumber.mockResolvedValueOnce(LATEST_BLOCK_NUMBER + count); @@ -125,7 +111,7 @@ describe('server_world_state_synchronizer', () => { // create an initial block let currentBlockNumber = 0; - nextBlocks = [getMockBlock(currentBlockNumber + 1)]; + nextBlocks = [L2Block.random(currentBlockNumber + 1)]; // start the sync process but don't await server.start().catch(err => log.error('Sync not completed: ', err)); @@ -147,7 +133,7 @@ describe('server_world_state_synchronizer', () => { continue; } currentBlockNumber++; - nextBlocks = [getMockBlock(currentBlockNumber + 1)]; + nextBlocks = [L2Block.random(currentBlockNumber + 1)]; } // check the status again, should be fully synced @@ -171,7 +157,7 @@ describe('server_world_state_synchronizer', () => { const newBlocks = async () => { while (currentBlockNumber <= LATEST_BLOCK_NUMBER) { await sleep(100); - nextBlocks = [...nextBlocks, getMockBlock(++currentBlockNumber)]; + nextBlocks = [...nextBlocks, L2Block.random(++currentBlockNumber)]; } }; @@ -202,7 +188,7 @@ describe('server_world_state_synchronizer', () => { const newBlocks = async () => { while (currentBlockNumber < LATEST_BLOCK_NUMBER) { await sleep(100); - const newBlock = getMockBlock(++currentBlockNumber); + const newBlock = L2Block.random(++currentBlockNumber); nextBlocks = [...nextBlocks, newBlock]; } }; @@ -260,7 +246,7 @@ describe('server_world_state_synchronizer', () => { const totalBlocks = LATEST_BLOCK_NUMBER + 1; nextBlocks = Array(totalBlocks) .fill(0) - .map((_, index) => getMockBlock(index, [Buffer.alloc(32, index)])); + .map((_, index) => L2Block.random(index)); // sync the server await server.start(); @@ -275,13 +261,13 @@ describe('server_world_state_synchronizer', () => { // the server should now be asleep for a long time // we will add a new block and force an immediate sync - nextBlocks = [getMockBlock(LATEST_BLOCK_NUMBER + 1)]; + nextBlocks = [L2Block.random(LATEST_BLOCK_NUMBER + 1)]; await server.syncImmediate(); let status = await server.status(); expect(status.syncedToL2Block).toBe(LATEST_BLOCK_NUMBER + 1); - nextBlocks = [getMockBlock(LATEST_BLOCK_NUMBER + 2), getMockBlock(LATEST_BLOCK_NUMBER + 3)]; + nextBlocks = [L2Block.random(LATEST_BLOCK_NUMBER + 2), L2Block.random(LATEST_BLOCK_NUMBER + 3)]; await server.syncImmediate(); status = await server.status(); @@ -305,7 +291,7 @@ describe('server_world_state_synchronizer', () => { // we will add 20 blocks and force a sync to at least LATEST + 5 nextBlocks = Array(20) .fill(0) - .map((_, index: number) => getMockBlock(index + 1 + LATEST_BLOCK_NUMBER)); + .map((_, index: number) => L2Block.random(index + 1 + LATEST_BLOCK_NUMBER)); await server.syncImmediate(LATEST_BLOCK_NUMBER + 5); // we should have synced all of the blocks @@ -352,7 +338,7 @@ describe('server_world_state_synchronizer', () => { // we will add 2 blocks and force a sync to at least LATEST + 5 nextBlocks = Array(2) .fill(0) - .map((_, index: number) => getMockBlock(index + 1 + LATEST_BLOCK_NUMBER)); + .map((_, index: number) => L2Block.random(index + 1 + LATEST_BLOCK_NUMBER)); await expect(server.syncImmediate(LATEST_BLOCK_NUMBER + 5)).rejects.toThrow( `Unable to sync to block number ${LATEST_BLOCK_NUMBER + 5}, currently synced to block ${LATEST_BLOCK_NUMBER + 2}`, ); @@ -380,7 +366,7 @@ describe('server_world_state_synchronizer', () => { // create an initial block nextBlocks = Array(LATEST_BLOCK_NUMBER) .fill(0) - .map((_, index: number) => getMockBlock(index + 1)); + .map((_, index: number) => L2Block.random(index + 1)); await expect(server.syncImmediate()).rejects.toThrow(`World State is not running, unable to perform sync`); }); diff --git a/yarn-project/world-state/src/world-state-db/merkle_tree_snapshot_operations_facade.ts b/yarn-project/world-state/src/world-state-db/merkle_tree_snapshot_operations_facade.ts index 8c645dc6ca7..f58dd1295b0 100644 --- a/yarn-project/world-state/src/world-state-db/merkle_tree_snapshot_operations_facade.ts +++ b/yarn-project/world-state/src/world-state-db/merkle_tree_snapshot_operations_facade.ts @@ -83,7 +83,6 @@ export class MerkleTreeSnapshotOperationsFacade implements MerkleTreeOperations async getStateReference(): Promise { const snapshots = await Promise.all([ - this.#getTreeSnapshot(MerkleTreeId.CONTRACT_TREE), this.#getTreeSnapshot(MerkleTreeId.NULLIFIER_TREE), this.#getTreeSnapshot(MerkleTreeId.NOTE_HASH_TREE), this.#getTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE), @@ -105,10 +104,6 @@ export class MerkleTreeSnapshotOperationsFacade implements MerkleTreeOperations Fr.fromBuffer(snapshots[MerkleTreeId.NULLIFIER_TREE].getRoot()), Number(snapshots[MerkleTreeId.NULLIFIER_TREE].getNumLeaves()), ), - new AppendOnlyTreeSnapshot( - Fr.fromBuffer(snapshots[MerkleTreeId.CONTRACT_TREE].getRoot()), - Number(snapshots[MerkleTreeId.CONTRACT_TREE].getNumLeaves()), - ), new AppendOnlyTreeSnapshot( Fr.fromBuffer(snapshots[MerkleTreeId.PUBLIC_DATA_TREE].getRoot()), Number(snapshots[MerkleTreeId.PUBLIC_DATA_TREE].getNumLeaves()), diff --git a/yarn-project/world-state/src/world-state-db/merkle_trees.ts b/yarn-project/world-state/src/world-state-db/merkle_trees.ts index de119f5ac58..2e5b1d44db2 100644 --- a/yarn-project/world-state/src/world-state-db/merkle_trees.ts +++ b/yarn-project/world-state/src/world-state-db/merkle_trees.ts @@ -2,7 +2,6 @@ import { L2Block, MerkleTreeId, SiblingPath } from '@aztec/circuit-types'; import { ARCHIVE_HEIGHT, AppendOnlyTreeSnapshot, - CONTRACT_TREE_HEIGHT, ContentCommitment, Fr, GlobalVariables, @@ -89,13 +88,7 @@ export class MerkleTrees implements MerkleTreeDb { const initializeTree = fromDb ? loadTree : newTree; const hasher = new Pedersen(); - const contractTree: AppendOnlyTree = await initializeTree( - StandardTree, - this.store, - hasher, - `${MerkleTreeId[MerkleTreeId.CONTRACT_TREE]}`, - CONTRACT_TREE_HEIGHT, - ); + const nullifierTree = await initializeTree( NullifierTree, this.store, @@ -133,7 +126,7 @@ export class MerkleTrees implements MerkleTreeDb { `${MerkleTreeId[MerkleTreeId.ARCHIVE]}`, ARCHIVE_HEIGHT, ); - this.trees = [contractTree, nullifierTree, noteHashTree, publicDataTree, l1Tol2MessageTree, archive]; + this.trees = [nullifierTree, noteHashTree, publicDataTree, l1Tol2MessageTree, archive]; this.jobQueue.start(); @@ -213,7 +206,6 @@ export class MerkleTrees implements MerkleTreeDb { new PartialStateReference( getAppendOnlyTreeSnapshot(MerkleTreeId.NOTE_HASH_TREE), getAppendOnlyTreeSnapshot(MerkleTreeId.NULLIFIER_TREE), - getAppendOnlyTreeSnapshot(MerkleTreeId.CONTRACT_TREE), getAppendOnlyTreeSnapshot(MerkleTreeId.PUBLIC_DATA_TREE), ), ); @@ -488,7 +480,6 @@ export class MerkleTrees implements MerkleTreeDb { */ async #handleL2Block(l2Block: L2Block): Promise { const treeRootWithIdPairs = [ - [l2Block.header.state.partial.contractTree.root, MerkleTreeId.CONTRACT_TREE], [l2Block.header.state.partial.nullifierTree.root, MerkleTreeId.NULLIFIER_TREE], [l2Block.header.state.partial.noteHashTree.root, MerkleTreeId.NOTE_HASH_TREE], [l2Block.header.state.partial.publicDataTree.root, MerkleTreeId.PUBLIC_DATA_TREE], @@ -509,7 +500,6 @@ export class MerkleTrees implements MerkleTreeDb { // Sync the append only trees for (const [tree, leaves] of [ - [MerkleTreeId.CONTRACT_TREE, l2Block.body.txEffects.flatMap(txEffect => txEffect.contractLeaves)], [MerkleTreeId.NOTE_HASH_TREE, l2Block.body.txEffects.flatMap(txEffect => txEffect.noteHashes)], [MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l2Block.body.l1ToL2Messages], ] as const) { diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 543a2887af7..ae278e45d44 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -2787,7 +2787,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/noirc_abi@portal:../noir/packages/noirc_abi::locator=%40aztec%2Faztec3-packages%40workspace%3A." dependencies: - "@noir-lang/types": 0.24.0 + "@noir-lang/types": 0.25.0 languageName: node linkType: soft